Initial revision

From-SVN: r102074
This commit is contained in:
Tom Tromey
2005-07-16 00:30:23 +00:00
parent 6f4434b39b
commit f911ba985a
4557 changed files with 1000262 additions and 0 deletions
@@ -0,0 +1,61 @@
/* java.beans.AppletInitializer
Copyright (C) 2001, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.applet.Applet;
import java.beans.beancontext.BeanContext;
/** This interface is a mechanism for the initialization of a Java
* Bean that is also an Applet. It is used by
* <code>Beans.instantiate()</code>.
*
* @author Tom Tromey (tromey@redhat.com)
* @since 1.2
*/
public interface AppletInitializer
{
/** Activate the applet. */
void activate (Applet applet);
/** This method will be called by <code>Beans.instantiate()</code>
* to associated the new Applet with its AppletContext, AppletStub,
* and Container.
*/
void initialize (Applet applet, BeanContext context);
}
@@ -0,0 +1,89 @@
/* java.beans.BeanDescriptor
Copyright (C) 1998, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
/**
** 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;
// Set the FeatureDescriptor programmatic name.
String name = beanClass.getName();
int lastInd = name.lastIndexOf('.');
if (lastInd != -1)
name = name.substring(lastInd + 1);
setName(name);
}
/** Get the Bean's class. **/
public Class getBeanClass() {
return beanClass;
}
/** Get the Bean's customizer's class. **/
public Class getCustomizerClass() {
return customizerClass;
}
}
+181
View File
@@ -0,0 +1,181 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
/**
** BeanInfo can be implemented in order to provide explicit information to the Introspector.
**
** When you write a BeanInfo class, you implement this interface
** and provide explicit information by returning a non-null
** value from the appropriate method. If you wish the
** Introspector to determine certain information in the normal
** way, just return null (or in the case of int methods, return
** -1). There is a class called SimpleBeanInfo which returns
** null from all methods, which you may extend and only
** override the methods you wish to override.<P>
**
** When you have written the class, give it the name
** <CODE>&lt;Bean Class Name&gt;BeanInfo</CODE> and place it in
** the same package as the Bean, or in the bean info search path
** (see Introspector for information on search paths).<P>
**
** A simple note about the way the Introspector interacts with
** BeanInfo. Introspectors look at a Bean class and determine
** if there is a BeanInfo class with it. If there is not a
** BeanInfo class, it will behave as if the BeanInfo class
** provided was a SimpleBeanInfo class (i.e. it will determine
** all information automatically).<P>If there is a BeanInfo
** class, then any methods that do *not* return null are
** regarded as providing definitive information about the class
** and all of its superclasses for those information types.
** Even if a parent BeanInfo class explicitly returns that
** information, it will not be used.
**
** @author John Keiser
** @since JDK1.1
** @version 1.1.0, 28 Jul 1998
**/
public interface BeanInfo {
/** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
int ICON_COLOR_16x16 = 1;
/** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
int ICON_COLOR_32x32 = 2;
/** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
int ICON_MONO_16x16 = 3;
/** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
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.
**/
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.
**/
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.
**/
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.
**/
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.
**/
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.
**/
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).
**/
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.
**/
java.awt.Image getIcon(int iconType);
}
+368
View File
@@ -0,0 +1,368 @@
/* java.beans.Beans
Copyright (C) 1998, 1999, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import gnu.java.beans.DummyAppletStub;
import gnu.java.io.ClassLoaderObjectInputStream;
import java.applet.Applet;
import java.beans.beancontext.BeanContext;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.URL;
/**
* <code>Beans</code> provides some helper methods that allow the basic
* operations of Bean-ness.
*
* @author John Keiser
* @author Robert Schuster
*
* @since 1.1
* @status updated to 1.4
*
*/
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()
{
// Does intentionally nothing here.
}
/** Creates a bean.
* <p>This is a convenience method that calls <code>instantiate(cl, beanName, null, null)</code>.</p>
*
* @see instantiate(ClassLoader, String, BeanContext, AppletInitializer)
* @param cl ClassLoader to be used or <code>null</code> for the system classloader.
* @param beanName Name of a serialized bean or class name.
* @return A newly created bean.
* @throws IOException If access of an IO resource failed.
* @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
*/
public static Object instantiate(ClassLoader cl, String beanName)
throws IOException, ClassNotFoundException
{
return instantiate(cl, beanName, null, null);
}
/** Creates a bean.
*
* <p>This is a convenience method that calls <code>instantiate(cl, beanName, beanContext, null)</code>.</p>
*
* @see instantiate(ClassLoader, String, BeanContext, AppletInitializer)
* @param cl ClassLoader to be used or <code>null</code> for the system classloader.
* @param beanName Name of a serialized bean or class name.
* @param beanContext Context to which the newly created Bean should be added.
* @return A newly created bean.
* @throws IOException If access of an IO resource failed.
* @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
*/
public static Object instantiate(
ClassLoader cl,
String beanName,
BeanContext beanContext)
throws IOException, ClassNotFoundException
{
return instantiate(cl, beanName, beanContext, null);
}
/** Instantiates a bean according to Beans 1.0.
*
* <p>In Beans 1.0 the instantiation scheme is as follows:</p>
* <p>The name should be dot-separated (e.g "place.for.beans.myBean") and indicate either a
* serialized object or a class name. In the first case all dots in the name are replaced with
* slashes ('/') and ".ser" is appended ("place.for.beans.myBean" becomes "place/for/beans/myBean.ser").
* The bean is then loaded as an application or system resource depending on whether a
* <code>ClassLoader</code> was provided.</p>
*
* <p>If no such resource exists or if it contains no bean the name is interpreted as a class name of
* which an instance is then created.</p>
*
* <p>If a <code>BeanContext</code> instance is available the created bean is added to it.</p>
*
* <p>If the created Bean is an <code>Applet</code> or subclass and an <code>AppletInitializer</code>
* instance is available the applet is initialized and afterwards activated using the initializer. Additionally
* every instantiated <code>Applet</code> bean is initialized using the {@link Applet.init} method.
* Furthermore every applet gets a default <code>AppletStub</code>. The <code>Applet</code>'s
* document base is the location of the ".ser" file if it was deserialized or the location of its class
* file if it was instantiated.</p>
*
* <p>A <code>ClassNotFoundException</code> is not only thrown when a class name was unknown
* but even when the class has public no-argument constructor
* (<code>IllegalAccessException</code> is wrapped) or an exception is thrown while
* invoking such a constructor (causing exception is wrapped).</p>
*
* @param cl ClassLoader to be used or <code>null</code> for the system classloader.
* @param beanName Name of a serialized bean or class name.
* @param beanContext Context to which the newly created Bean should be added.
* @param initializer The AppletInitializer which is used for initializing <code>Applet</code> beans.
* @return A newly created bean.
* @throws IOException If access of an IO resource failed.
* @throws ClassNotFoundException If the class name is not known or does not lead to a proper bean class.
*/
public static Object instantiate(
ClassLoader cl,
String beanName,
BeanContext beanContext,
AppletInitializer initializer)
throws IOException, ClassNotFoundException
{
Object bean = null;
URL beanLocation = null;
URL classLocation = null;
// Converts bean name into a resource name (eg. "a.b.c" -> "a/b/c").
String resourceName = beanName.replace('.', '/');
/* Tries to get an input stream of the Bean, reading it as a system resource
* if no ClassLoader is present or as an application resource if a classloader
* is given.
*/
beanLocation =
(cl == null)
? ClassLoader.getSystemResource(resourceName + ".ser")
: cl.getResource(resourceName + ".ser");
// Reads the serialized Bean from the returned URL.
if (beanLocation != null)
{
// Deserializes the bean instance.
ObjectInputStream ois =
(cl == null)
? new ObjectInputStream(beanLocation.openStream())
: new ClassLoaderObjectInputStream(
beanLocation.openStream(),
cl);
bean = ois.readObject();
/* Implementation note: The result of ObjectInputStream.readObject()
* may have been null at this point (its a valid value to deserialize)
* and we explicitly want to try instantiation in such a case
* (this is important for compatibility).
*/
}
// Instantiates the Bean using reflective instantiation if it has not been created yet.
if (bean == null)
{
// Makes sure that the deserialization was NOT done.
beanLocation = null;
Class beanClass;
if (cl == null)
{
beanClass = Class.forName(beanName);
classLocation =
ClassLoader.getSystemResource(resourceName + ".class");
}
else
{
beanClass = cl.loadClass(beanName);
classLocation = cl.getResource(resourceName + ".class");
}
// Instantiates and optionally registers the new bean.
try
{
bean = beanClass.newInstance();
}
catch(Exception e) {
/* Wraps all kinds of Exceptions in a ClassNotFoundException (this behavior
* matches with official >= 1.5, this was different for <=1.4)
*/
throw new ClassNotFoundException(null, e);
}
}
/* Applet beans are treated in the following way:
* - all AppletS get a default AppletStub
* - all AppletS are initialized using the AppletInitializer instance (if it is available)
* - as every other Bean Applets are added to a BeanContext if one is available
* - each instantiated Applet is initialized using Applet.init() (this is not done for deserialized ones)
* - finally AppletS get activated using the AppletInitializerS activate-Method
*
* The order of operations is important for compatibility.
*/
Applet applet = null;
if (bean instanceof Applet)
{
// Makes a second instanceof call unneccessary (instanceof is expensive).
applet = (Applet) bean;
/* The AppletStub's code and document base is set as follows:
* The code base is always the URL from where the class data originated
* (without the package name).
* If the Applet was deserialized the document base is the location of
* the serialized instance (usually the ".ser" file) otherwise its the URL
* from where the class data originated (usually the absolute directory
* location of the ".class" file).
*/
applet.setStub(
new DummyAppletStub(
applet
.getClass()
.getProtectionDomain()
.getCodeSource()
.getLocation(),
(beanLocation == null) ? classLocation : beanLocation));
// Runs the Applet's initialization using an AppletInitializer.
if (initializer != null)
{
initializer.initialize(applet, beanContext);
}
}
// Adds the new bean to its BeanContext.
if (beanContext != null)
{
beanContext.add(bean);
}
if (applet != null)
{
// Initializes an instantiated (not deserialized) Applet using its own method.
if (beanLocation == null)
{
applet.init();
}
// Runs the Applet's activation using an AppletInitializer.
if (initializer != null)
{
initializer.activate(applet);
}
}
return bean;
}
/**
* Returns 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;
}
/**
* Determines 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);
}
/**
* Returns whether the GUI is available to use.
* <p>Defaults to true.</p>
*
* @return whether the GUI is available to use.
*/
public static boolean isGuiAvailable()
{
return guiAvailable;
}
/**
* Returns whether it is design time. Design time means
* we are in a RAD tool.
* <p>Defaults to false.</p>
*
* @return whether it is design time.
*/
public static boolean isDesignTime()
{
return designTime;
}
/**
* Sets 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;
}
/**
* Sets 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;
}
}
@@ -0,0 +1,86 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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.
**/
void setObject(Object bean);
/** Add a PropertyChangeListener.
** @param l the PropertyChangeListener to add.
**/
void addPropertyChangeListener(PropertyChangeListener l);
/** Remove a PropertyChangeListener.
** @param l the PropertyChangeListener to remove.
**/
void removePropertyChangeListener(PropertyChangeListener l);
}
@@ -0,0 +1,93 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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.
*/
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
*/
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.
*/
boolean isDesignTime();
}
@@ -0,0 +1,606 @@
/* java.beans.EventHandler
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* <p>EventHandler forms a bridge between dynamically created listeners and
* arbitrary properties and methods.</p>
*
* <p>You can use this class to easily create listener implementations for
* some basic interactions between an event source and its target. Using
* the three static methods named <code>create</code> you can create
* these listener implementations.</p>
*
* <p>See the documentation of each method for usage examples.</p>
*
* @author Jerry Quinn (jlquinn@optonline.net)
* @author Robert Schuster (thebohemian@gmx.net)
* @since 1.4
*/
public class EventHandler implements InvocationHandler
{
// The name of the method that will be implemented. If null, any method.
private String listenerMethod;
// The object to call action on.
private Object target;
// The name of the method or property setter in target.
private String action;
// The property to extract from an event passed to listenerMethod.
private String property;
// The target objects Class.
private Class targetClass;
// String class doesn't already have a capitalize routine.
private String capitalize(String s)
{
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
/**
* Creates a new <code>EventHandler</code> instance.
*
* <p>Typical creation is done with the create method, not by knewing an
* EventHandler.</p>
*
* <p>This constructs an EventHandler that will connect the method
* listenerMethodName to target.action, extracting eventPropertyName from
* the first argument of listenerMethodName. and sending it to action.</p>
*
* <p>Throws a <code>NullPointerException</code> if the <code>target</code>
* argument is <code>null</code>.
*
* @param target Object that will perform the action.
* @param action A property or method of the target.
* @param eventPropertyName A readable property of the inbound event.
* @param listenerMethodName The listener method name triggering the action.
*/
public EventHandler(Object target, String action, String eventPropertyName,
String listenerMethodName)
{
this.target = target;
// Retrieving the class is done for two reasons:
// 1) The class object is needed very frequently in the invoke() method.
// 2) The constructor should throw a NullPointerException if target is null.
targetClass = target.getClass();
this.action = action; // Turn this into a method or do we wait till
// runtime
property = eventPropertyName;
listenerMethod = listenerMethodName;
}
/**
* Returns the event property name.
*/
public String getEventPropertyName()
{
return property;
}
/**
* Returns the listener's method name.
*/
public String getListenerMethodName()
{
return listenerMethod;
}
/**
* Returns the target object.
*/
public Object getTarget()
{
return target;
}
/**
* Returns the action method name.
*/
public String getAction()
{
return action;
}
// Fetch a qualified property like a.b.c from object o. The properties can
// be boolean isProp or object getProp properties.
//
// Returns a length 2 array with the first entry containing the value
// extracted from the property, and the second entry contains the class of
// the method return type.
//
// We play this game because if the method returns a native type, the return
// value will be a wrapper. If we then take the type of the wrapper and use
// it to locate the action method that takes the native type, it won't match.
private Object[] getProperty(Object o, String prop)
{
// Isolate the first property name from a.b.c.
int pos;
String rest = null;
if ((pos = prop.indexOf('.')) != -1)
{
rest = prop.substring(pos + 1);
prop = prop.substring(0, pos);
}
// Find a method named getProp. It could be isProp instead.
Method getter;
try
{
// Look for boolean property getter isProperty
getter = o.getClass().getMethod("is" + capitalize(prop),
null);
}
catch (NoSuchMethodException nsme1)
{
try {
// Look for regular property getter getProperty
getter = o.getClass().getMethod("get" + capitalize(prop),
null);
} catch(NoSuchMethodException nsme2) {
try {
// Finally look for a method of the name prop
getter = o.getClass().getMethod(prop, null);
} catch(NoSuchMethodException nsme3) {
// Ok, give up with an intelligent hint for the user.
throw new RuntimeException("Method not called: Could not find a property or method '" + prop
+ "' in " + o.getClass() + " while following the property argument '" + property + "'.");
}
}
}
try {
Object val = getter.invoke(o, null);
if (rest != null)
return getProperty(val, rest);
return new Object[] {val, getter.getReturnType()};
} catch(InvocationTargetException ite) {
throw new RuntimeException("Method not called: Property or method '" + prop + "' has thrown an exception.", ite);
} catch(IllegalAccessException iae) {
// This cannot happen because we looked up method with Class.getMethod()
// which returns public methods only.
throw (InternalError) new InternalError("Non-public method was invoked.").initCause(iae);
}
}
/**
* Invokes the <code>EventHandler</code>.
*
* <p>This method is normally called by the listener's proxy implementation.</p>
*
* @param proxy The listener interface that is implemented using
* the proxy mechanism.
* @param method The method that was called on the proxy instance.
* @param arguments The arguments which where given to the method.
* @throws Throwable <code>NoSuchMethodException</code> is thrown when the EventHandler's
* action method or property cannot be found.
*/
public Object invoke(Object proxy, Method method, Object[] arguments)
{
try {
// The method instance of the target object. We have to find out which
// one we have to invoke.
Method actionMethod = null;
// Listener methods that weren't specified are ignored. If listenerMethod
// is null, then all listener methods are processed.
if (listenerMethod != null && !method.getName().equals(listenerMethod))
return null;
// If a property is defined we definitely need a valid object at
// arguments[0] that can be used to retrieve a value to which the
// property of the target gets set.
if(property != null) {
// Extracts the argument. We will let it fail with a NullPointerException
// the caller used a listener method that has no arguments.
Object event = arguments[0];
// Obtains the property XXX propertyType keeps showing up null - why?
// because the object inside getProperty changes, but the ref variable
// can't change this way, dolt! need a better way to get both values out
// - need method and object to do the invoke and get return type
Object v[] = getProperty(event, property);
Object[] args = new Object[] { v[0] };
// Changes the class array that controls which method signature we are going
// to look up in the target object.
Class[] argTypes = new Class[] { initClass((Class) v[1]) };
// Tries to find a setter method to which we can apply the
while(argTypes[0] != null) {
try
{
// Look for a property setter for action.
actionMethod = targetClass.getMethod("set" + capitalize(action), argTypes);
return actionMethod.invoke(target, args);
}
catch (NoSuchMethodException e)
{
// If action as property didn't work, try as method later.
}
argTypes[0] = nextClass(argTypes[0]);
}
// We could not find a suitable setter method. Now we try again interpreting
// action as the method name itself.
// Since we probably have changed the block local argTypes array
// we need to rebuild it.
argTypes = new Class[] { initClass((Class) v[1]) };
// Tries to find a setter method to which we can apply the
while(argTypes[0] != null) {
try
{
actionMethod = targetClass.getMethod(action, argTypes);
return actionMethod.invoke(target, args);
}
catch (NoSuchMethodException e)
{
}
argTypes[0] = nextClass(argTypes[0]);
}
throw new RuntimeException("Method not called: Could not find a public method named '"
+ action + "' in target " + targetClass + " which takes a '"
+ v[1] + "' argument or a property of this type.");
}
// If property was null we will search for a no-argument method here.
// Note: The ordering of method lookups is important because we want to prefer no-argument
// calls like the JDK does. This means if we have actionMethod() and actionMethod(Event) we will
// call the first *EVEN* if we have a valid argument for the second method. This is behavior compliant
// to the JDK.
// If actionMethod() is not available but there is a actionMethod(Event) we take this. That makes us
// more specification compliant than the JDK itself because this one will fail in such a case.
try
{
actionMethod = targetClass.getMethod(action, null);
}
catch(NoSuchMethodException nsme)
{
// Note: If we want to be really strict the specification says that a no-argument method should
// accept an EventObject (or subclass I guess). However since the official implementation is broken
// anyways, it's more flexible without the EventObject restriction and we are compatible on everything
// else this can stay this way.
if(arguments != null && arguments.length >= 1/* && arguments[0] instanceof EventObject*/) {
Class[] targetArgTypes = new Class[] { initClass(arguments[0].getClass()) };
while(targetArgTypes[0] != null) {
try
{
// If no property exists we expect the first element of the arguments to be
// an EventObject which is then applied to the target method.
actionMethod = targetClass.getMethod(action, targetArgTypes);
return actionMethod.invoke(target, new Object[] { arguments[0] });
}
catch(NoSuchMethodException nsme2)
{
}
targetArgTypes[0] = nextClass(targetArgTypes[0]);
}
}
}
// If we do not have a Method instance at this point this means that all our tries
// failed. The JDK throws an ArrayIndexOutOfBoundsException in this case.
if(actionMethod == null)
throw new ArrayIndexOutOfBoundsException(0);
// Invoke target.action(property)
return actionMethod.invoke(target, null);
} catch(InvocationTargetException ite) {
throw new RuntimeException(ite.getCause());
} catch(IllegalAccessException iae) {
// Cannot happen because we always use getMethod() which returns public
// methods only. Otherwise there is something seriously broken in
// GNU Classpath.
throw (InternalError) new InternalError("Non-public method was invoked.").initCause(iae);
}
}
/**
* <p>Returns the primitive type for every wrapper class or the
* class itself if it is no wrapper class.</p>
*
* <p>This is needed because to be able to find both kinds of methods:
* One that takes a wrapper class as the first argument and one that
* accepts a primitive instead.</p>
*/
private Class initClass(Class klass) {
if(klass == Boolean.class) {
return Boolean.TYPE;
} else if(klass == Byte.class) {
return Byte.TYPE;
} else if(klass == Short.class) {
return Short.TYPE;
} else if(klass == Integer.class) {
return Integer.TYPE;
} else if(klass == Long.class) {
return Long.TYPE;
} else if(klass == Float.class) {
return Float.TYPE;
} else if(klass == Double.class) {
return Double.TYPE;
} else {
return klass;
}
}
/**
*
*
* @param klass
* @return
*/
private Class nextClass(Class klass) {
if(klass == Boolean.TYPE) {
return Boolean.class;
} else if(klass == Byte.TYPE) {
return Byte.class;
} else if(klass == Short.TYPE) {
return Short.class;
} else if(klass == Integer.TYPE) {
return Integer.class;
} else if(klass == Long.TYPE) {
return Long.class;
} else if(klass == Float.TYPE) {
return Float.class;
} else if(klass == Double.TYPE) {
return Double.class;
} else {
return klass.getSuperclass();
}
}
/**
* <p>Constructs an implementation of <code>listenerInterface</code>
* to dispatch events.</p>
*
* <p>You can use such an implementation to simply call a public
* no-argument method of an arbitrary target object or to forward
* the first argument of the listener method to the target method.</p>
*
* <p>Call this method like:</p>
* <code>
* button.addActionListener((ActionListener)
* EventHandler.create(ActionListener.class, target, "dispose"));
* </code>
*
* <p>to achieve the following behavior:</p>
* <code>
* button.addActionListener(new ActionListener() {
* public void actionPerformed(ActionEvent ae) {
* target.dispose();
* }
* });
* </code>
*
* <p>That means if you need a listener implementation that simply calls a
* a no-argument method on a given instance for <strong>each</strong>
* method of the listener interface.</p>
*
* <p>Note: The <code>action</code> is interpreted as a method name. If your target object
* has no no-argument method of the given name the EventHandler tries to find
* a method with the same name but which can accept the first argument of the
* listener method. Usually this will be an event object but any other object
* will be forwarded, too. Keep in mind that using a property name instead of a
* real method here is wrong and will throw an <code>ArrayIndexOutOfBoundsException</code>
* whenever one of the listener methods is called.<p/>
*
* <p>The <code>EventHandler</code> will automatically convert primitives
* to their wrapper class and vice versa. Furthermore it will call
* a target method if it accepts a superclass of the type of the
* first argument of the listener method.</p>
*
* <p>In case that the method of the target object throws an exception
* it will be wrapped in a <code>RuntimeException</code> and thrown out
* of the listener method.</p>
*
* <p>In case that the method of the target object cannot be found an
* <code>ArrayIndexOutOfBoundsException</code> will be thrown when the
* listener method is invoked.</p>
*
* <p>A call to this method is equivalent to:
* <code>create(listenerInterface, target, action, null, null)</code></p>
*
* @param listenerInterface Listener interface to implement.
* @param target Object to invoke action on.
* @param action Target property or method to invoke.
* @return A constructed proxy object.
*/
public static Object create(Class listenerInterface, Object target, String action)
{
return create(listenerInterface, target, action, null, null);
}
/**
* <p>Constructs an implementation of <code>listenerInterface</code>
* to dispatch events.</p>
*
* <p>Use this method if you want to create an implementation that retrieves
* a property value from the <b>first</b> argument of the listener method
* and applies it to the target's property or method. This first argument
* of the listener is usually an event object but any other object is
* valid, too.</p>
*
* <p>You can set the value of <code>eventPropertyName</code> to "prop"
* to denote the retrieval of a property named "prop" from the event
* object. In case that no such property exists the <code>EventHandler</code>
* will try to find a method with that name.</p>
*
* <p>If you set <code>eventPropertyName</code> to a value like this "a.b.c"
* <code>EventHandler</code> will recursively evaluate the properties "a", "b"
* and "c". Again if no property can be found the <code>EventHandler</code>
* tries a method name instead. This allows mixing the names, too: "a.toString"
* will retrieve the property "a" from the event object and will then call
* the method "toString" on it.</p>
*
* <p>An exception thrown in any of these methods will provoke a
* <code>RuntimeException</code> to be thrown which contains an
* <code>InvocationTargetException</code> containing the triggering exception.</p>
*
* <p>If you set <code>eventPropertyName</code> to a non-null value the
* <code>action</code> parameter will be interpreted as a property name
* or a method name of the target object.</p>
*
* <p>Any object retrieved from the event object and applied to the
* target will converted from primitives to their wrapper class or
* vice versa or applied to a method that accepts a superclass
* of the object.</p>
*
* <p>Examples:</p>
* <p>The following code:</p><code>
* button.addActionListener(
* new ActionListener() {
* public void actionPerformed(ActionEvent ae) {
* Object o = ae.getSource().getClass().getName();
* textField.setText((String) o);
* }
* });
* </code>
*
* <p>Can be expressed using the <code>EventHandler</code> like this:</p>
* <p>
* <code>button.addActionListener((ActionListener)
* EventHandler.create(ActionListener.class, textField, "text", "source.class.name");
* <code>
* </p>
*
* <p>As said above you can specify the target as a method, too:</p>
* <p>
* <code>button.addActionListener((ActionListener)
* EventHandler.create(ActionListener.class, textField, "setText", "source.class.name");
* <code>
* </p>
*
* <p>Furthermore you can use method names in the property:</p>
* <p>
* <code>button.addActionListener((ActionListener)
* EventHandler.create(ActionListener.class, textField, "setText", "getSource.getClass.getName");
* <code>
* </p>
*
* <p>Finally you can mix names:</p>
* <p>
* <code>button.addActionListener((ActionListener)
* EventHandler.create(ActionListener.class, textField, "setText", "source.getClass.name");
* <code>
* </p>
*
* <p>A call to this method is equivalent to:
* <code>create(listenerInterface, target, action, null, null)</code>
* </p>
*
* @param listenerInterface Listener interface to implement.
* @param target Object to invoke action on.
* @param action Target property or method to invoke.
* @param eventPropertyName Name of property to extract from event.
* @return A constructed proxy object.
*/
public static Object create(Class listenerInterface, Object target,
String action, String eventPropertyName)
{
return create(listenerInterface, target, action, eventPropertyName, null);
}
/**
* <p>Constructs an implementation of <code>listenerInterface</code>
* to dispatch events.</p>
*
* <p>Besides the functionality described for {@link create(Class, Object, String)}
* and {@link create(Class, Object, String, String)} this method allows you
* to filter the listener method that should have an effect. Look at these
* method's documentation for more information about the <code>EventHandler</code>'s
* usage.</p>
*
* <p>If you want to call <code>dispose</code> on a <code>JFrame</code> instance
* when the <code>WindowListener.windowClosing()</code> method was invoked use
* the following code:</p>
* <p>
* <code>
* EventHandler.create(WindowListener.class, jframeInstance, "dispose", null, "windowClosing");
* </code>
* </p>
*
* <p>A <code>NullPointerException</code> is thrown if the <code>listenerInterface</code>
* or <code>target</code> argument are <code>null</code>.
*
* @param listenerInterface Listener interface to implement.
* @param target Object to invoke action on.
* @param action Target method name to invoke.
* @param eventPropertyName Name of property to extract from event.
* @param listenerMethodName Listener method to implement.
* @return A constructed proxy object.
*/
public static Object create(Class listenerInterface, Object target,
String action, String eventPropertyName,
String listenerMethodName)
{
// Create EventHandler instance
EventHandler eh = new EventHandler(target, action, eventPropertyName,
listenerMethodName);
// Create proxy object passing in the event handler
Object proxy = Proxy.newProxyInstance(listenerInterface.getClassLoader(),
new Class[] {listenerInterface},
eh);
return proxy;
}
}
@@ -0,0 +1,442 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import gnu.java.lang.ClassHelper;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Vector;
/**
** EventSetDescriptor describes the hookup between an event source
** class and an event listener class.
**
** EventSets have several attributes: the listener class, the events
** that can be fired to the listener (methods in the listener class), and
** an add and remove listener method from the event firer's class.<P>
**
** The methods have these constraints on them:<P>
** <UL>
** <LI>event firing methods: must have <CODE>void</CODE> return value. Any
** parameters and exceptions are allowed. May be public, protected or
** package-protected. (Don't ask me why that is, I'm just following the spec.
** The only place it is even mentioned is in the Java Beans white paper, and
** there it is only implied.)</LI>
** <LI>add listener method: must have <CODE>void</CODE> return value. Must
** take exactly one argument, of the listener class's type. May fire either
** zero exceptions, or one exception of type <CODE>java.util.TooManyListenersException</CODE>.
** Must be public.</LI>
** <LI>remove listener method: must have <CODE>void</CODE> return value.
** Must take exactly one argument, of the listener class's type. May not
** fire any exceptions. Must be public.</LI>
** </UL>
**
** A final constraint is that event listener classes must extend from EventListener.<P>
**
** There are also various design patterns associated with some of the methods
** of construction. Those are explained in more detail in the appropriate
** constructors.<P>
**
** <STRONG>Documentation Convention:</STRONG> for proper
** Internalization of Beans inside an RAD tool, sometimes there
** are two names for a property or method: a programmatic, or
** locale-independent name, which can be used anywhere, and a
** localized, display name, for ease of use. In the
** documentation I will specify different String values as
** either <EM>programmatic</EM> or <EM>localized</EM> to
** make this distinction clear.
**
** @author John Keiser
** @since JDK1.1
** @version 1.1.0, 31 May 1998
**/
public class EventSetDescriptor extends FeatureDescriptor {
private Method addListenerMethod;
private Method removeListenerMethod;
private Class listenerType;
private MethodDescriptor[] listenerMethodDescriptors;
private Method[] listenerMethods;
private boolean unicast;
private boolean inDefaultEventSet = true;
/** Create a new EventSetDescriptor.
** This version of the constructor enforces the rules imposed on the methods
** described at the top of this class, as well as searching for:<P>
** <OL>
** <LI>The event-firing method must be non-private with signature
** <CODE>void &lt;listenerMethodName&gt;(&lt;eventSetName&gt;Event)</CODE>
** (where <CODE>&lt;eventSetName&gt;</CODE> has its first character capitalized
** by the constructor and the Event is a descendant of
** <CODE>java.util.EventObject</CODE>) in class <CODE>listenerType</CODE>
** (any exceptions may be thrown).
** <B>Implementation note:</B> Note that there could conceivably be multiple
** methods with this type of signature (example: java.util.MouseEvent vs.
** my.very.own.MouseEvent). In this implementation, all methods fitting the
** description will be put into the <CODE>EventSetDescriptor</CODE>, even
** though the spec says only one should be chosen (they probably weren't thinking as
** pathologically as I was). I don't like arbitrarily choosing things.
** If your class has only one such signature, as most do, you'll have no problems.</LI>
** <LI>The add and remove methods must be public and named
** <CODE>void add&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> and
** <CODE>void remove&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> in
** in class <CODE>eventSourceClass</CODE>, where
** <CODE>&lt;eventSetName&gt;</CODE> will have its first letter capitalized.
** Standard exception rules (see class description) apply.</LI>
** </OL>
** @param eventSourceClass the class containing the add/remove listener methods.
** @param eventSetName the programmatic name of the event set, generally starting
** with a lowercase letter (i.e. fooManChu instead of FooManChu). This will be used
** to generate the name of the event object as well as the names of the add and
** remove methods.
** @param listenerType the class containing the event firing method.
** @param listenerMethodName the name of the event firing method.
** @exception IntrospectionException if listenerType is not an EventListener,
** or if methods are not found or are invalid.
**/
public EventSetDescriptor(Class eventSourceClass,
String eventSetName,
Class listenerType,
String listenerMethodName) throws IntrospectionException {
setName(eventSetName);
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
throw new IntrospectionException("Listener type is not an EventListener.");
}
String[] names = new String[1];
names[0] = listenerMethodName;
try {
eventSetName = Character.toUpperCase(eventSetName.charAt(0)) + eventSetName.substring(1);
} catch(StringIndexOutOfBoundsException e) {
eventSetName = "";
}
findMethods(eventSourceClass,listenerType,names,"add"+eventSetName+"Listener","remove"+eventSetName+"Listener",eventSetName+"Event");
this.listenerType = listenerType;
checkAddListenerUnicast();
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
throw new IntrospectionException("Listener remove method throws exceptions.");
}
}
/** Create a new EventSetDescriptor.
** This form of the constructor allows you to specify the names of the methods and adds
** no new constraints on top of the rules already described at the top of the class.<P>
**
** @param eventSourceClass the class containing the add and remove listener methods.
** @param eventSetName the programmatic name of the event set, generally starting
** with a lowercase letter (i.e. fooManChu instead of FooManChu).
** @param listenerType the class containing the event firing methods.
** @param listenerMethodNames the names of the even firing methods.
** @param addListenerMethodName the name of the add listener method.
** @param removeListenerMethodName the name of the remove listener method.
** @exception IntrospectionException if listenerType is not an EventListener
** or if methods are not found or are invalid.
**/
public EventSetDescriptor(Class eventSourceClass,
String eventSetName,
Class listenerType,
String[] listenerMethodNames,
String addListenerMethodName,
String removeListenerMethodName) throws IntrospectionException {
setName(eventSetName);
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
throw new IntrospectionException("Listener type is not an EventListener.");
}
findMethods(eventSourceClass,listenerType,listenerMethodNames,addListenerMethodName,removeListenerMethodName,null);
this.listenerType = listenerType;
checkAddListenerUnicast();
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
throw new IntrospectionException("Listener remove method throws exceptions.");
}
}
/** Create a new EventSetDescriptor.
** This form of constructor allows you to explicitly say which methods do what, and
** no reflection is done by the EventSetDescriptor. The methods are, however,
** checked to ensure that they follow the rules set forth at the top of the class.
** @param eventSetName the programmatic name of the event set, generally starting
** with a lowercase letter (i.e. fooManChu instead of FooManChu).
** @param listenerType the class containing the listenerMethods.
** @param listenerMethods the event firing methods.
** @param addListenerMethod the add listener method.
** @param removeListenerMethod the remove listener method.
** @exception IntrospectionException if the listenerType is not an EventListener,
** or any of the methods are invalid.
**/
public EventSetDescriptor(String eventSetName,
Class listenerType,
Method[] listenerMethods,
Method addListenerMethod,
Method removeListenerMethod) throws IntrospectionException {
setName(eventSetName);
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
throw new IntrospectionException("Listener type is not an EventListener.");
}
this.listenerMethods = listenerMethods;
this.addListenerMethod = addListenerMethod;
this.removeListenerMethod = removeListenerMethod;
this.listenerType = listenerType;
checkMethods();
checkAddListenerUnicast();
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
throw new IntrospectionException("Listener remove method throws exceptions.");
}
}
/** Create a new EventSetDescriptor.
** This form of constructor allows you to explicitly say which methods do what, and
** no reflection is done by the EventSetDescriptor. The methods are, however,
** checked to ensure that they follow the rules set forth at the top of the class.
** @param eventSetName the programmatic name of the event set, generally starting
** with a lowercase letter (i.e. fooManChu instead of FooManChu).
** @param listenerType the class containing the listenerMethods.
** @param listenerMethodDescriptors the event firing methods.
** @param addListenerMethod the add listener method.
** @param removeListenerMethod the remove listener method.
** @exception IntrospectionException if the listenerType is not an EventListener,
** or any of the methods are invalid.
**/
public EventSetDescriptor(String eventSetName,
Class listenerType,
MethodDescriptor[] listenerMethodDescriptors,
Method addListenerMethod,
Method removeListenerMethod) throws IntrospectionException {
setName(eventSetName);
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
throw new IntrospectionException("Listener type is not an EventListener.");
}
this.listenerMethodDescriptors = listenerMethodDescriptors;
this.listenerMethods = new Method[listenerMethodDescriptors.length];
for(int i=0;i<this.listenerMethodDescriptors.length;i++) {
this.listenerMethods[i] = this.listenerMethodDescriptors[i].getMethod();
}
this.addListenerMethod = addListenerMethod;
this.removeListenerMethod = removeListenerMethod;
this.listenerType = listenerType;
checkMethods();
checkAddListenerUnicast();
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
throw new IntrospectionException("Listener remove method throws exceptions.");
}
}
/** Get the class that contains the event firing methods. **/
public Class getListenerType() {
return listenerType;
}
/** Get the event firing methods. **/
public Method[] getListenerMethods() {
return listenerMethods;
}
/** Get the event firing methods as MethodDescriptors. **/
public MethodDescriptor[] getListenerMethodDescriptors() {
if(listenerMethodDescriptors == null) {
listenerMethodDescriptors = new MethodDescriptor[listenerMethods.length];
for(int i=0;i<listenerMethods.length;i++) {
listenerMethodDescriptors[i] = new MethodDescriptor(listenerMethods[i]);
}
}
return listenerMethodDescriptors;
}
/** Get the add listener method. **/
public Method getAddListenerMethod() {
return addListenerMethod;
}
/** Get the remove listener method. **/
public Method getRemoveListenerMethod() {
return removeListenerMethod;
}
/** Set whether or not multiple listeners may be added.
** @param unicast whether or not multiple listeners may be added.
**/
public void setUnicast(boolean unicast) {
this.unicast = unicast;
}
/** Get whether or not multiple listeners may be added. (Defaults to false.) **/
public boolean isUnicast() {
return unicast;
}
/** Set whether or not this is in the default event set.
** @param inDefaultEventSet whether this is in the default event set.
**/
public void setInDefaultEventSet(boolean inDefaultEventSet) {
this.inDefaultEventSet = inDefaultEventSet;
}
/** Get whether or not this is in the default event set. (Defaults to true.)**/
public boolean isInDefaultEventSet() {
return inDefaultEventSet;
}
private void checkAddListenerUnicast() throws IntrospectionException {
Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
if(addListenerExceptions.length > 1) {
throw new IntrospectionException("Listener add method throws too many exceptions.");
} else if(addListenerExceptions.length == 1
&& !java.util.TooManyListenersException.class.isAssignableFrom(addListenerExceptions[0])) {
throw new IntrospectionException("Listener add method throws too many exceptions.");
}
}
private void checkMethods() throws IntrospectionException {
if(!addListenerMethod.getDeclaringClass().isAssignableFrom(removeListenerMethod.getDeclaringClass())
&& !removeListenerMethod.getDeclaringClass().isAssignableFrom(addListenerMethod.getDeclaringClass())) {
throw new IntrospectionException("add and remove listener methods do not come from the same class. This is bad.");
}
if(!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
|| addListenerMethod.getParameterTypes().length != 1
|| !listenerType.equals(addListenerMethod.getParameterTypes()[0])
|| !Modifier.isPublic(addListenerMethod.getModifiers())) {
throw new IntrospectionException("Add Listener Method invalid.");
}
if(!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
|| removeListenerMethod.getParameterTypes().length != 1
|| !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
|| removeListenerMethod.getExceptionTypes().length > 0
|| !Modifier.isPublic(removeListenerMethod.getModifiers())) {
throw new IntrospectionException("Remove Listener Method invalid.");
}
for(int i=0;i<listenerMethods.length;i++) {
if(!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
|| Modifier.isPrivate(listenerMethods[i].getModifiers())) {
throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " non-void or private.");
}
if(!listenerMethods[i].getDeclaringClass().isAssignableFrom(listenerType)) {
throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " not from class " + listenerType.getName());
}
}
}
private void findMethods(Class eventSourceClass,
Class listenerType,
String listenerMethodNames[],
String addListenerMethodName,
String removeListenerMethodName,
String absurdEventClassCheckName) throws IntrospectionException {
/* Find add listener method and remove listener method. */
Class[] listenerArgList = new Class[1];
listenerArgList[0] = listenerType;
try {
this.addListenerMethod = eventSourceClass.getMethod(addListenerMethodName,listenerArgList);
} catch(SecurityException E) {
throw new IntrospectionException("SecurityException trying to access method " + addListenerMethodName + ".");
} catch(NoSuchMethodException E) {
throw new IntrospectionException("Could not find method " + addListenerMethodName + ".");
}
if(this.addListenerMethod == null || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
throw new IntrospectionException("Add listener method does not exist, is not public, or is not void.");
}
try {
this.removeListenerMethod = eventSourceClass.getMethod(removeListenerMethodName,listenerArgList);
} catch(SecurityException E) {
throw new IntrospectionException("SecurityException trying to access method " + removeListenerMethodName + ".");
} catch(NoSuchMethodException E) {
throw new IntrospectionException("Could not find method " + removeListenerMethodName + ".");
}
if(this.removeListenerMethod == null || !this.removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
throw new IntrospectionException("Remove listener method does not exist, is not public, or is not void.");
}
/* Find the listener methods. */
Method[] methods;
try {
methods = ClassHelper.getAllMethods(listenerType);
} catch(SecurityException E) {
throw new IntrospectionException("Security: You cannot access fields in this class.");
}
Vector chosenMethods = new Vector();
boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
for(int i=0;i<methods.length;i++) {
if(Modifier.isPrivate(methods[i].getModifiers())) {
continue;
}
Method currentMethod = methods[i];
Class retval = currentMethod.getReturnType();
if(retval.equals(java.lang.Void.TYPE)) {
for(int j=0;j<listenerMethodNames.length;j++) {
if(currentMethod.getName().equals(listenerMethodNames[j])
&& (absurdEventClassCheckName == null
|| (currentMethod.getParameterTypes().length == 1
&& ((currentMethod.getParameterTypes()[0]).getName().equals(absurdEventClassCheckName)
|| (currentMethod.getParameterTypes()[0]).getName().endsWith("."+absurdEventClassCheckName)
)
)
)
) {
chosenMethods.addElement(currentMethod);
listenerMethodFound[j] = true;
}
}
}
}
/* Make sure we found all the methods we were looking for. */
for(int i=0;i<listenerMethodFound.length;i++) {
if(!listenerMethodFound[i]) {
throw new IntrospectionException("Could not find event method " + listenerMethodNames[i]);
}
}
/* Now that we've chosen the listener methods we want, store them. */
this.listenerMethods = new Method[chosenMethods.size()];
for(int i=0;i<chosenMethods.size();i++) {
this.listenerMethods[i] = (Method)chosenMethods.elementAt(i);
}
}
}
@@ -0,0 +1,57 @@
/* ExceptionListener.java -- listen for recoverable internal exceptions
Copyright (C) 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
/**
* This interface allows a class to monitor internal exceptions, to try to
* recover from them.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.4
* @status updated to 1.4
*/
public interface ExceptionListener
{
/**
* Fired after an exception occurs.
*
* @param e the trapped exception
*/
void exceptionThrown(Exception e);
} // interface ExceptionListener
@@ -0,0 +1,133 @@
/* java.beans.Expression
Copyright (C) 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
/**
* class Expression
*
* An Expression captures the execution of an object method that
* returns a value. It stores an object, the method to call, and the
* arguments to pass to the method.
*
* @since 1.4
*/
public class Expression extends Statement
{
// This is a placeholder to indicate that value hasn't been set
// yet;
private static final Object unset = new Object();
// The value to return. This is equal to unset until getValue is called.
private Object value;
/**
* Constructor
*
* Constructs an Expression representing the invocation of
* object.methodName(arg[0], arg[1], ...); However, it will never
* be executed. Instead, value will always be returned.
*
* @param value The value to return.
* @param target The object to invoke the method on.
* @param methodName The object method to invoke.
* @param arguments An array of arguments to pass to the method.
*/
public Expression(Object value, Object target, String methodName,
Object[] arguments)
{
super(target, methodName, arguments);
this.value = value;
}
/**
* Constructor
*
* Constructs an Expression representing the invocation of
* object.methodName(arg[0], arg[1], ...);
*
* @param target The object to invoke the method on.
* @param methodName The object method to invoke.
* @param arguments An array of arguments to pass to the method.
*/
public Expression(Object target, String methodName, Object[] arguments)
{
super(target, methodName, arguments);
this.value = unset;
}
/**
* Return the result of executing the method.
*
* If the cached value has not yet been set, the method is
* executed in the same way as Statement.execute(), except that
* the value is cached, and then returned. If the value has been
* set, it is returned without executing the method again.
*
* @return the result of executing the method.
* @exception Exception if an error occurs
*/
public Object getValue() throws Exception
{
if (value == unset)
value = doExecute();
return value;
}
/**
* Set the cached value to be returned by getValue()
*
* @param value the value to cache and return.
*/
public void setValue(Object value)
{
this.value = value;
}
/**
* Return a string representation of this expression.
*/
public String toString()
{
String result = super.toString();
if (value != unset)
return value.getClass().getName() + " " + result;
return result;
}
}
@@ -0,0 +1,232 @@
/* java.beans.FeatureDescriptor
Copyright (C) 1998, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* 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 1.1
*/
public class FeatureDescriptor
{
String name;
String displayName;
String shortDescription;
boolean expert;
boolean hidden;
boolean preferred;
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.
*
* @returns The localized display name of this feature or falls
* back to the programmatic name.
*/
public String getDisplayName()
{
return (displayName == null) ? name : 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.
*
* @returns A short localized description of this feature or
* what <code>getDisplayName</code> returns in case, that no short description
* is available.
*/
public String getShortDescription()
{
return (shortDescription == null) ? getDisplayName() : 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;
}
public boolean isPreferred ()
{
return preferred;
}
public void setPreferred (boolean preferred)
{
this.preferred = preferred;
}
/**
* 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();
}
}
@@ -0,0 +1,307 @@
/* java.beans.IndexedPropertyDescriptor
Copyright (C) 1998, 2003 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
/**
** IndexedPropertyDescriptor describes information about a JavaBean
** indexed property, by which we mean an array-like property that
** has been exposed via a pair of get and set methods and another
** pair that allows you to get to the property by an index.<P>
**
** An example property would have four methods like this:<P>
** <CODE>FooBar[] getFoo()</CODE><BR>
** <CODE>void setFoo(FooBar[])</CODE><BR>
** <CODE>FooBar getFoo(int)</CODE><BR>
** <CODE>void setFoo(int,FooBar)</CODE><P>
**
** The constraints put on get and set methods are:<P>
** <OL>
** <LI>There must be at least a get(int) or a set(int,...) method.
** Nothing else is required. <B>Spec note:</B>One nice restriction
** would be that if there is a get() there must be a get(int), same
** with set, but that is not in the spec and is fairly harmless.)</LI>
** <LI>A get array method must have signature
** <CODE>&lt;propertyType&gt;[] &lt;getMethodName&gt;()</CODE></LI>
** <LI>A set array method must have signature
** <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;[])</CODE></LI>
** <LI>A get index method must have signature
** <CODE>&lt;propertyType&gt; &lt;getMethodName&gt;(int)</CODE></LI>
** <LI>A set index method must have signature
** <CODE>void &lt;setMethodName&gt;(int,&lt;propertyType&gt;)</CODE></LI>
** <LI>All these methods may throw any exception.</LI>
** <LI>All these methods must be public.</LI>
** </OL>
**
** @author John Keiser
** @since JDK1.1
** @version 1.1.0, 26 Jul 1998
**/
public class IndexedPropertyDescriptor extends PropertyDescriptor {
private Class indexedPropertyType;
private Method setIndex;
private Method getIndex;
/** Create a new IndexedPropertyDescriptor by introspection.
** This form of constructor creates the PropertyDescriptor by
** looking for getter methods named <CODE>get&lt;name&gt;()</CODE>
** and setter methods named
** <CODE>set&lt;name&gt;()</CODE> in class
** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
** first letter capitalized by the constructor.<P>
**
** <B>Implementation note:</B> If there is a get(int) method,
** then the return type of that method is used to find the
** remaining methods. If there is no get method, then the
** set(int) method is searched for exhaustively and that type
** is used to find the others.<P>
**
** <B>Spec note:</B>
** If there is no get(int) method and multiple set(int) methods with
** the same name and the correct parameters (different type of course),
** then an IntrospectionException is thrown. While Sun's spec
** does not state this, it can make Bean behavior different on
** different systems (since method order is not guaranteed) and as
** such, can be treated as a bug in the spec. I am not aware of
** whether Sun's implementation catches this.
**
** @param name the programmatic name of the property, usually
** starting with a lowercase letter (e.g. fooManChu
** instead of FooManChu).
** @param beanClass the class the get and set methods live in.
** @exception IntrospectionException if the methods are not found or invalid.
**/
public IndexedPropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
super(name);
String capitalized;
try {
capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
} catch(StringIndexOutOfBoundsException e) {
capitalized = "";
}
findMethods(beanClass, "get" + capitalized, "set" + capitalized, "get" + capitalized, "set" + capitalized);
}
/** Create a new IndexedPropertyDescriptor by introspection.
** This form of constructor allows you to specify the
** names of the get and set methods to search for.<P>
**
** <B>Implementation note:</B> If there is a get(int) method,
** then the return type of that method is used to find the
** remaining methods. If there is no get method, then the
** set(int) method is searched for exhaustively and that type
** is used to find the others.<P>
**
** <B>Spec note:</B>
** If there is no get(int) method and multiple set(int) methods with
** the same name and the correct parameters (different type of course),
** then an IntrospectionException is thrown. While Sun's spec
** does not state this, it can make Bean behavior different on
** different systems (since method order is not guaranteed) and as
** such, can be treated as a bug in the spec. I am not aware of
** whether Sun's implementation catches this.
**
** @param name the programmatic name of the property, usually
** starting with a lowercase letter (e.g. fooManChu
** instead of FooManChu).
** @param beanClass the class the get and set methods live in.
** @param getMethodName the name of the get array method.
** @param setMethodName the name of the set array method.
** @param getIndexName the name of the get index method.
** @param setIndexName the name of the set index method.
** @exception IntrospectionException if the methods are not found or invalid.
**/
public IndexedPropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
super(name);
findMethods(beanClass, getMethodName, setMethodName, getIndexName, setIndexName);
}
/** Create a new PropertyDescriptor using explicit Methods.
** Note that the methods will be checked for conformance to standard
** Property method rules, as described above at the top of this class.
**
** @param name the programmatic name of the property, usually
** starting with a lowercase letter (e.g. fooManChu
** instead of FooManChu).
** @param getMethod the get array method.
** @param setMethod the set array method.
** @param getIndex the get index method.
** @param setIndex the set index method.
** @exception IntrospectionException if the methods are not found or invalid.
**/
public IndexedPropertyDescriptor(String name, Method getMethod, Method setMethod, Method getIndex, Method setIndex) throws IntrospectionException {
super(name);
if(getMethod != null && getMethod.getParameterTypes().length > 0) {
throw new IntrospectionException("get method has parameters");
}
if(getMethod != null && setMethod.getParameterTypes().length != 1) {
throw new IntrospectionException("set method does not have exactly one parameter");
}
if(getMethod != null && setMethod != null) {
if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
throw new IntrospectionException("set and get methods do not share the same type");
}
if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
&& !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
throw new IntrospectionException("set and get methods are not in the same class.");
}
}
if(getIndex != null && (getIndex.getParameterTypes().length != 1
|| !(getIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
throw new IntrospectionException("get index method has wrong parameters");
}
if(setIndex != null && (setIndex.getParameterTypes().length != 2
|| !(setIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
throw new IntrospectionException("set index method has wrong parameters");
}
if(getIndex != null && setIndex != null) {
if(!getIndex.getReturnType().equals(setIndex.getParameterTypes()[1])) {
throw new IntrospectionException("set index methods do not share the same type");
}
if(!getIndex.getDeclaringClass().isAssignableFrom(setIndex.getDeclaringClass())
&& !setIndex.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
throw new IntrospectionException("get and set index methods are not in the same class.");
}
}
if(getIndex != null && getMethod != null && !getIndex.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())
&& !getMethod.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
throw new IntrospectionException("methods are not in the same class.");
}
if(getIndex != null && getMethod != null && !Array.newInstance(getIndex.getReturnType(),0).getClass().equals(getMethod.getReturnType())) {
throw new IntrospectionException("array methods do not match index methods.");
}
this.getMethod = getMethod;
this.setMethod = setMethod;
this.getIndex = getIndex;
this.setIndex = setIndex;
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.");
}
}
}
@@ -0,0 +1,67 @@
/* IntrospectionException -- thrown when an exception occurs in introspection
Copyright (C) 1998, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
/**
* IntrospectionException is thrown when the Introspector fails. Typical
* causes are the inability to map a name to its Class, or specifying a
* wrong type signature.
*
* @author John Keiser
* @see Introspector
* @since 1.1
* @status updated to 1.4
*/
public class IntrospectionException extends Exception
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = -3728150539969542619L;
/**
* Instantiate this exception with the given message.
*
* @param msg the message for the exception
*/
public IntrospectionException(String msg)
{
super(msg);
}
}
@@ -0,0 +1,608 @@
/* java.beans.Introspector
Copyright (C) 1998, 2002, 2003 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import gnu.java.beans.BeanInfoEmbryo;
import gnu.java.beans.ExplicitBeanInfo;
import gnu.java.beans.IntrospectionIncubator;
import gnu.java.lang.ClassHelper;
import java.util.Hashtable;
import java.util.Vector;
/**
* 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 &lt;bean class name&gt;BeanInfo in different
* packages, first searching the bean class's package
* and then moving on to search the beanInfoSearchPath.<P>
*
* If it does not find a BeanInfo class, it acts as though
* it had found a BeanInfo class returning null from all
* methods (meaning it should discover everything through
* Introspection). If it does, then it takes the
* information it finds in the BeanInfo class to be
* canonical (that is, the information speaks for its
* class as well as all superclasses).<P>
*
* When it has introspected the class, calls
* getBeanInfo(c.getSuperclass) and adds that information
* to the information it has, not adding to any information
* it already has that is canonical.<P>
*
* <STRONG>Introspection Design Patterns</STRONG><P>
*
* When the Introspector goes in to read the class, it
* follows a well-defined order in order to not leave any
* methods unaccounted for. Its job is to step over all
* of the public methods in a class and determine whether
* they are part of a property, an event, or a method (in
* that order).
*
*
* <STRONG>Properties:</STRONG><P>
*
* <OL>
* <LI>If there is a <CODE>public boolean isXXX()</CODE>
* method, then XXX is a read-only boolean property.
* <CODE>boolean getXXX()</CODE> may be supplied in
* addition to this method, although isXXX() is the
* one that will be used in this case and getXXX()
* will be ignored. If there is a
* <CODE>public void setXXX(boolean)</CODE> method,
* it is part of this group and makes it a read-write
* property.</LI>
* <LI>If there is a
* <CODE>public &lt;type&gt; getXXX(int)</CODE>
* method, then XXX is a read-only indexed property of
* type &lt;type&gt;. If there is a
* <CODE>public void setXXX(int,&lt;type&gt;)</CODE>
* method, then it is a read-write indexed property of
* type &lt;type&gt;. There may also be a
* <CODE>public &lt;type&gt;[] getXXX()</CODE> and a
* <CODE>public void setXXX(&lt;type&gt;)</CODE>
* method as well.</LI>
* <LI>If there is a
* <CODE>public void setXXX(int,&lt;type&gt;)</CODE>
* method, then it is a write-only indexed property of
* type &lt;type&gt;. There may also be a
* <CODE>public &lt;type&gt;[] getXXX()</CODE> and a
* <CODE>public void setXXX(&lt;type&gt;)</CODE>
* method as well.</LI>
* <LI>If there is a
* <CODE>public &lt;type&gt; getXXX()</CODE> method,
* then XXX is a read-only property of type
* &lt;type&gt;. If there is a
* <CODE>public void setXXX(&lt;type&gt;)</CODE>
* method, then it will be used for the property and
* the property will be considered read-write.</LI>
* <LI>If there is a
* <CODE>public void setXXX(&lt;type&gt;)</CODE>
* method, then as long as XXX is not already used as
* the name of a property, XXX is assumed to be a
* write-only property of type &lt;type&gt;.</LI>
* <LI>In all of the above cases, if the setXXX() method
* throws <CODE>PropertyVetoException</CODE>, then the
* property in question is assumed to be constrained.
* No properties are ever assumed to be bound
* (<STRONG>Spec Note:</STRONG> this is not in the
* spec, it just makes sense). See PropertyDescriptor
* for a description of bound and constrained
* properties.</LI>
* </OL>
*
* <STRONG>Events:</STRONG><P>
*
* If there is a pair of methods,
* <CODE>public void addXXX(&lt;type&gt;)</CODE> and
* <CODE>public void removeXXX(&lt;type&gt;)</CODE>, where
* &lt;type&gt; is a descendant of
* <CODE>java.util.EventListener</CODE>, then the pair of
* methods imply that this Bean will fire events to
* listeners of type &lt;type&gt;.<P>
*
* If the addXXX() method throws
* <CODE>java.util.TooManyListenersException</CODE>, then
* the event set is assumed to be <EM>unicast</EM>. See
* EventSetDescriptor for a discussion of unicast event
* sets.<P>
*
* <STRONG>Spec Note:</STRONG> the spec seems to say that
* the listener type's classname must be equal to the XXX
* part of addXXX() and removeXXX(), but that is not the
* case in Sun's implementation, so I am assuming it is
* not the case in general.<P>
*
* <STRONG>Methods:</STRONG><P>
*
* Any public methods (including those which were used
* for Properties or Events) are used as Methods.
*
* @author John Keiser
* @since JDK1.1
* @see java.beans.BeanInfo
*/
public class Introspector {
public static final int USE_ALL_BEANINFO = 1;
public static final int IGNORE_IMMEDIATE_BEANINFO = 2;
public static final int IGNORE_ALL_BEANINFO = 3;
static String[] beanInfoSearchPath = {"gnu.java.beans.info"};
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;
}
}
/**
* Flush all of the Introspector's internal caches.
*
* @since 1.2
*/
public static void flushCaches()
{
beanInfoCache.clear();
// Clears all the intermediate ExplicitInfo instances which
// have been created.
// This makes sure we have to retrieve stuff like BeanDescriptors
// again. (Remember that FeatureDescriptor can be modified by the user.)
ExplicitInfo.flushCaches();
}
/**
* Flush the Introspector's internal cached information for a given
* class.
*
* @param clz the class to be flushed.
* @throws NullPointerException if clz is null.
* @since 1.2
*/
public static void flushFromCaches(Class clz)
{
synchronized (clz)
{
beanInfoCache.remove(clz);
}
}
/**
* 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]);
}
}
}
// Sets the info's BeanDescriptor to the one we extracted from the
// explicit BeanInfo instance(s) if they contained one. Otherwise we
// create the BeanDescriptor from scratch.
// Note: We do not create a copy the retrieved BeanDescriptor which will allow
// the user to modify the instance while it is cached. However this is how
// the RI does it.
currentInfo.setBeanDescriptor(
(explicit.explicitBeanDescriptor == null ?
new BeanDescriptor(beanClass, null) :
explicit.explicitBeanDescriptor));
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;
static Hashtable explicitBeanInfos = new Hashtable();
static Vector emptyBeanInfos = new Vector();
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;
}
}
/** Throws away all cached data and makes sure we re-instantiate things
* like BeanDescriptors again.
*/
static void flushCaches() {
explicitBeanInfos.clear();
emptyBeanInfos.clear();
}
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)
{
ClassLoader beanClassLoader = beanClass.getClassLoader();
BeanInfo beanInfo;
beanInfo = getBeanInfo(beanClassLoader, beanClass.getName() + "BeanInfo");
if (beanInfo == null)
{
String newName;
newName = ClassHelper.getTruncatedClassName(beanClass) + "BeanInfo";
for(int i = 0; i < Introspector.beanInfoSearchPath.length; i++)
{
if (Introspector.beanInfoSearchPath[i].equals(""))
beanInfo = getBeanInfo(beanClassLoader, newName);
else
beanInfo = getBeanInfo(beanClassLoader,
Introspector.beanInfoSearchPath[i] + "."
+ newName);
// Returns the beanInfo if it exists and the described class matches
// the one we searched.
if (beanInfo != null && beanInfo.getBeanDescriptor() != null &&
beanInfo.getBeanDescriptor().getBeanClass() == beanClass)
return beanInfo;
}
}
return beanInfo;
}
/**
* Returns an instance of the given class name when it can be loaded
* through the given class loader, or null otherwise.
*/
private static BeanInfo getBeanInfo(ClassLoader cl, String infoName)
{
try
{
return (BeanInfo) Class.forName(infoName, true, cl).newInstance();
}
catch (ClassNotFoundException cnfe)
{
return null;
}
catch (IllegalAccessException iae)
{
return null;
}
catch (InstantiationException ie)
{
return null;
}
}
}
@@ -0,0 +1,88 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.lang.reflect.Method;
/** 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;
}
}
@@ -0,0 +1,52 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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 {
}
@@ -0,0 +1,189 @@
/* PropertyChangeEvent.java -- describes a change in a property
Copyright (C) 1998, 2000, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.util.EventObject;
/**
* PropertyChangeEvents are fired in the PropertyChange and VetoableChange
* event classes. They represent the old and new values as well as the
* source Bean. 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. Also, if the set of properties itself has
* changed, the name should be null, and the old and new values may also be
* null. 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
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.1
* @status udpated to 1.4
*/
public class PropertyChangeEvent extends EventObject
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = 7042693688939648123L;
/**
* The name of the property that changed, may be null. Package visible for
* use by PropertyChangeSupport.
*
* @serial the changed property name
*/
final String propertyName;
/**
* The new value of the property, may be null. Package visible for use by
* PropertyChangeSupport.
*
* @serial the new property value
*/
final Object newValue;
/**
* The old value of the property, may be null. Package visible for use by
* PropertyChangeSupport.
*
* @serial the old property value
*/
final Object oldValue;
/**
* The propagation ID, reserved for future use. May be null.
*
* @see #getPropagationId()
* @serial the Propagation ID
*/
private 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
* @throws IllegalArgumentException if source is null
*/
public PropertyChangeEvent(Object source, String propertyName,
Object oldVal, Object newVal)
{
super(source);
this.propertyName = propertyName;
oldValue = oldVal;
newValue = newVal;
}
/**
* Get the property name. May be null if multiple properties changed.
*
* @return the property name
*/
public String getPropertyName()
{
return propertyName;
}
/**
* Get the property's new value. May be null if multiple properties changed.
*
* @return the property's new value
*/
public Object getNewValue()
{
return newValue;
}
/**
* Get the property's old value. May be null if multiple properties changed.
*
* @return the property's old value
*/
public Object getOldValue()
{
return oldValue;
}
/**
* 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
* @see #getPropagationId()
*/
public void setPropagationId(Object propagationId)
{
this.propagationId = propagationId;
}
/**
* Get the propagation ID. Right now, it is not used for anything.
*
* @return the propagation ID
* @see #setPropagationId(Object)
*/
public Object getPropagationId()
{
return propagationId;
}
/**
* Utility method to rollback a change.
*
* @param event the event to rollback
* @return a new event with old and new swapped
*/
PropertyChangeEvent rollback()
{
PropertyChangeEvent result
= new PropertyChangeEvent(source, propertyName, newValue, oldValue);
result.propagationId = propagationId;
return result;
}
} // class PropertyChangeEvent
@@ -0,0 +1,61 @@
/* PropertyChangeListener.java -- listen for changes in a bound property
Copyright (C) 1998, 2000, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.util.EventListener;
/**
* PropertyChangeListener allows a class to monitor properties of a Bean for
* changes. A propertyChange() event will only be fired <em>after</em> the
* property has changed.
*
* @author John Keiser
* @see PropertyChangeSupport
* @since 1.1
* @status updated to 1.4
*/
public interface PropertyChangeListener extends EventListener
{
/**
* Fired after a Bean's property has changed.
*
* @param e the change (containing the old and new values)
*/
void propertyChange(PropertyChangeEvent e);
} // interface PropertyChangeListener
@@ -0,0 +1,102 @@
/* PropertyChangeListenerProxy.java -- adds a name to a property listener
Copyright (C) 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.util.EventListenerProxy;
/**
* This class provides an extension to <code>PropertyChangeListener</code> -
* associating a name with the listener. This can be used to filter the
* changes that one is interested in.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.4
* @status udpated to 1.4
*/
public class PropertyChangeListenerProxy extends EventListenerProxy
implements PropertyChangeListener
{
/**
* The name of the property to listen for. Package visible for use by
* PropertyChangeSupport.
*/
final String propertyName;
/**
* Create a new proxy which filters property change events and only passes
* changes to the named property on to the delegate. A null propertyName
* or listener does not fail now, but may cause a NullPointerException down
* the road.
*
* @param propertyName the property's name to filter on
* @param listener the delegate listener
*/
public PropertyChangeListenerProxy(String propertyName,
PropertyChangeListener listener)
{
super(listener);
this.propertyName = propertyName;
}
/**
* Forwards the event on to the delegate if the property name matches.
*
* @param event the event to pass on, if it meets the filter
* @throws NullPointerException if the delegate this was created with is null
*/
public void propertyChange(PropertyChangeEvent event)
{
// Note: Sun does not filter, under the assumption that since
// PropertyChangeSupport unwraps proxys, this method should never be
// called by normal use of listeners.
String name = event == null ? null : event.getPropertyName();
if (name == null ? propertyName == null : name.equals(propertyName))
((PropertyChangeListener) getListener()).propertyChange(event);
}
/**
* Gets the name of the property this proxy is filtering on.
*
* @return the property name
*/
public String getPropertyName()
{
return propertyName;
}
} // class PropertyChangeListenerProxy
@@ -0,0 +1,488 @@
/* PropertyChangeSupport.java -- support to manage property change listeners
Copyright (C) 1998, 1999, 2000, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Vector;
/**
* PropertyChangeSupport makes it easy to fire property change events and
* handle listeners. It allows chaining of listeners, as well as filtering
* by property name. In addition, it will serialize only those listeners
* which are serializable, ignoring the others without problem. This class
* is thread-safe.
*
* @author John Keiser
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.1
* @status updated to 1.4
*/
public class PropertyChangeSupport implements Serializable
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = 6401253773779951803L;
/**
* Maps property names (String) to named listeners (PropertyChangeSupport).
* If this is a child instance, this field will be null.
*
* @serial the map of property names to named listener managers
* @since 1.2
*/
private Hashtable children;
/**
* The non-null source object for any generated events.
*
* @serial the event source
*/
private final Object source;
/**
* A field to compare serialization versions - this class uses version 2.
*
* @serial the serialization format
*/
private static final int propertyChangeSupportSerializedDataVersion = 2;
/**
* The list of all registered property listeners. If this instance was
* created by user code, this only holds the global listeners (ie. not tied
* to a name), and may be null. If it was created by this class, as a
* helper for named properties, then this vector will be non-null, and this
* instance appears as a value in the <code>children</code> hashtable of
* another instance, so that the listeners are tied to the key of that
* hashtable entry.
*/
private transient Vector listeners;
/**
* Create a PropertyChangeSupport to work with a specific source bean.
*
* @param source the source bean to use
* @throws NullPointerException if source is null
*/
public PropertyChangeSupport(Object source)
{
this.source = source;
if (source == null)
throw new NullPointerException();
}
/**
* Adds a PropertyChangeListener to the list of global listeners. All
* property change events will be sent to this listener. 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. Adding a null listener may cause a NullPointerException
* down the road. This method will unwrap a PropertyChangeListenerProxy,
* registering the underlying delegate to the named property list.
*
* @param l the listener to add
*/
public synchronized void addPropertyChangeListener(PropertyChangeListener l)
{
if (l instanceof PropertyChangeListenerProxy)
{
PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
addPropertyChangeListener(p.propertyName,
(PropertyChangeListener) p.getListener());
}
else
{
if (listeners == null)
listeners = new Vector();
listeners.add(l);
}
}
/**
* Removes a PropertyChangeListener from the list of global 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. 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. This method will unwrap a
* PropertyChangeListenerProxy, removing the underlying delegate from the
* named property list.
*
* @param l the listener to remove
*/
public synchronized void
removePropertyChangeListener(PropertyChangeListener l)
{
if (l instanceof PropertyChangeListenerProxy)
{
PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
removePropertyChangeListener(p.propertyName,
(PropertyChangeListener) p.getListener());
}
else if (listeners != null)
{
listeners.remove(l);
if (listeners.isEmpty())
listeners = null;
}
}
/**
* Returns an array of all registered property change listeners. Those that
* were registered under a name will be wrapped in a
* <code>PropertyChangeListenerProxy</code>, so you must check whether the
* listener is an instance of the proxy class in order to see what name the
* real listener is registered under. If there are no registered listeners,
* this returns an empty array.
*
* @return the array of registered listeners
* @see PropertyChangeListenerProxy
* @since 1.4
*/
public synchronized PropertyChangeListener[] getPropertyChangeListeners()
{
ArrayList list = new ArrayList();
if (listeners != null)
list.addAll(listeners);
if (children != null)
{
int i = children.size();
Iterator iter = children.entrySet().iterator();
while (--i >= 0)
{
Entry e = (Entry) iter.next();
String name = (String) e.getKey();
Vector v = ((PropertyChangeSupport) e.getValue()).listeners;
int j = v.size();
while (--j >= 0)
list.add(new PropertyChangeListenerProxy
(name, (PropertyChangeListener) v.get(j)));
}
}
return (PropertyChangeListener[])
list.toArray(new PropertyChangeListener[list.size()]);
}
/**
* Adds a PropertyChangeListener listening on the specified property. Events
* will be sent to the listener only if the property name matches. 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. 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. Adding a null
* listener may cause a NullPointerException down the road. This method
* will unwrap a PropertyChangeListenerProxy, registering the underlying
* delegate to the named property list if the names match, and discarding
* it otherwise.
*
* @param propertyName the name of the property to listen on
* @param l the listener to add
* @throws NullPointerException if propertyName is null
*/
public synchronized void addPropertyChangeListener(String propertyName,
PropertyChangeListener l)
{
while (l instanceof PropertyChangeListenerProxy)
{
PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
if (propertyName == null ? p.propertyName != null
: ! propertyName.equals(p.propertyName))
return;
l = (PropertyChangeListener) p.getListener();
}
PropertyChangeSupport s = null;
if (children == null)
children = new Hashtable();
else
s = (PropertyChangeSupport) children.get(propertyName);
if (s == null)
{
s = new PropertyChangeSupport(source);
s.listeners = new Vector();
children.put(propertyName, s);
}
s.listeners.add(l);
}
/**
* Removes a PropertyChangeListener from listening to a specific property.
* 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. This method will unwrap a
* PropertyChangeListenerProxy, removing the underlying delegate from the
* named property list if the names match.
*
* @param propertyName the property to stop listening on
* @param l the listener to remove
* @throws NullPointerException if propertyName is null
*/
public synchronized void
removePropertyChangeListener(String propertyName, PropertyChangeListener l)
{
if (children == null)
return;
PropertyChangeSupport s
= (PropertyChangeSupport) children.get(propertyName);
if (s == null)
return;
while (l instanceof PropertyChangeListenerProxy)
{
PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
if (propertyName == null ? p.propertyName != null
: ! propertyName.equals(p.propertyName))
return;
l = (PropertyChangeListener) p.getListener();
}
s.listeners.remove(l);
if (s.listeners.isEmpty())
{
children.remove(propertyName);
if (children.isEmpty())
children = null;
}
}
/**
* Returns an array of all property change listeners registered under the
* given property name. If there are no registered listeners, this returns
* an empty array.
*
* @return the array of registered listeners
* @throws NullPointerException if propertyName is null
* @since 1.4
*/
public synchronized PropertyChangeListener[]
getPropertyChangeListeners(String propertyName)
{
if (children == null)
return new PropertyChangeListener[0];
PropertyChangeSupport s
= (PropertyChangeSupport) children.get(propertyName);
if (s == null)
return new PropertyChangeListener[0];
return (PropertyChangeListener[])
s.listeners.toArray(new PropertyChangeListener[s.listeners.size()]);
}
/**
* Fire a PropertyChangeEvent containing the old and new values of the
* property to all the global listeners, and to all the listeners for the
* specified property name. This does nothing if old and new are non-null
* and equal.
*
* @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(source, propertyName,
oldVal, newVal));
}
/**
* Fire a PropertyChangeEvent containing the old and new values of the
* property to all the global listeners, and to all the listeners for the
* specified property name. This does nothing if old and new are equal.
*
* @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)
{
if (oldVal != newVal)
firePropertyChange(new PropertyChangeEvent(source, propertyName,
new Integer(oldVal),
new Integer(newVal)));
}
/**
* Fire a PropertyChangeEvent containing the old and new values of the
* property to all the global listeners, and to all the listeners for the
* specified property name. This does nothing if old and new are equal.
*
* @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)
{
if (oldVal != newVal)
firePropertyChange(new PropertyChangeEvent(source, propertyName,
Boolean.valueOf(oldVal),
Boolean.valueOf(newVal)));
}
/**
* Fire a PropertyChangeEvent to all the global listeners, and to all the
* listeners for the specified property name. This does nothing if old and
* new values of the event are equal.
*
* @param event the event to fire
* @throws NullPointerException if event is null
*/
public void firePropertyChange(PropertyChangeEvent event)
{
if (event.oldValue != null && event.oldValue.equals(event.newValue))
return;
Vector v = listeners; // Be thread-safe.
if (v != null)
{
int i = v.size();
while (--i >= 0)
((PropertyChangeListener) v.get(i)).propertyChange(event);
}
Hashtable h = children; // Be thread-safe.
if (h != null && event.propertyName != null)
{
PropertyChangeSupport s
= (PropertyChangeSupport) h.get(event.propertyName);
if (s != null)
{
v = s.listeners; // Be thread-safe.
int i = v == null ? 0 : v.size();
while (--i >= 0)
((PropertyChangeListener) v.get(i)).propertyChange(event);
}
}
}
/**
* 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
* @throws NullPointerException if propertyName is null
*/
public synchronized boolean hasListeners(String propertyName)
{
return listeners != null || (children != null
&& children.get(propertyName) != null);
}
/**
* Saves the state of the object to the stream.
*
* @param s the stream to write to
* @throws IOException if anything goes wrong
* @serialData this writes out a null-terminated list of serializable
* global property change listeners (the listeners for a named
* property are written out as the global listeners of the
* children, when the children hashtable is saved)
*/
private synchronized void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
if (listeners != null)
{
int i = listeners.size();
while (--i >= 0)
if (listeners.get(i) instanceof Serializable)
s.writeObject(listeners.get(i));
}
s.writeObject(null);
}
/**
* Reads the object back from stream (deserialization).
*
* XXX Since serialization for 1.1 streams was not documented, this may
* not work if propertyChangeSupportSerializedDataVersion is 1.
*
* @param s the stream to read from
* @throws IOException if reading the stream fails
* @throws ClassNotFoundException if deserialization fails
* @serialData this reads in a null-terminated list of serializable
* global property change listeners (the listeners for a named
* property are written out as the global listeners of the
* children, when the children hashtable is saved)
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
PropertyChangeListener l = (PropertyChangeListener) s.readObject();
while (l != null)
{
addPropertyChangeListener(l);
l = (PropertyChangeListener) s.readObject();
}
// Sun is not as careful with children as we are, and lets some proxys
// in that can never receive events. So, we clean up anything that got
// serialized, to make sure our invariants hold.
if (children != null)
{
int i = children.size();
Iterator iter = children.entrySet().iterator();
while (--i >= 0)
{
Entry e = (Entry) iter.next();
String name = (String) e.getKey();
PropertyChangeSupport pcs = (PropertyChangeSupport) e.getValue();
if (pcs.listeners == null)
pcs.listeners = new Vector();
if (pcs.children != null)
pcs.listeners.addAll
(Arrays.asList(pcs.getPropertyChangeListeners(name)));
if (pcs.listeners.size() == 0)
iter.remove();
else
pcs.children = null;
}
if (children.size() == 0)
children = null;
}
}
} // class PropertyChangeSupport
@@ -0,0 +1,583 @@
/* java.beans.PropertyDescriptor
Copyright (C) 1998, 2001, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.lang.reflect.Method;
/**
** PropertyDescriptor describes information about a JavaBean property,
** by which we mean a property that has been exposed via a pair of
** get and set methods. (There may be no get method, which means
** the property is write-only, or no set method, which means the
** the property is read-only.)<P>
**
** The constraints put on get and set methods are:<P>
** <OL>
** <LI>A get method must have signature
** <CODE>&lt;propertyType&gt; &lt;getMethodName&gt;()</CODE></LI>
** <LI>A set method must have signature
** <CODE>void &lt;setMethodName&gt;(&lt;propertyType&gt;)</CODE></LI>
** <LI>Either method type may throw any exception.</LI>
** <LI>Both methods must be public.</LI>
** </OL>
**
** @author John Keiser
** @author Robert Schuster (thebohemian@gmx.net)
** @since 1.1
** @status updated to 1.4
**/
public class PropertyDescriptor extends FeatureDescriptor
{
Class propertyType;
Method getMethod;
Method setMethod;
Class propertyEditorClass;
boolean bound;
boolean constrained;
PropertyDescriptor(String name)
{
setName(name);
}
/** Create a new PropertyDescriptor by introspection.
** This form of constructor creates the PropertyDescriptor by
** looking for a getter method named <CODE>get&lt;name&gt;()</CODE>
** (or, optionally, if the property is boolean,
** <CODE>is&lt;name&gt;()</CODE>) and
** <CODE>set&lt;name&gt;()</CODE> in class
** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
** first letter capitalized by the constructor.<P>
**
** Note that using this constructor the given property must be read- <strong>and</strong>
** writeable. If the implementation does not both, a read and a write method, an
** <code>IntrospectionException</code> is thrown.
**
** <B>Implementation note:</B> If there is both are both isXXX and
** getXXX methods, the former is used in preference to the latter.
** We do not check that an isXXX method returns a boolean. In both
** cases, this matches the behaviour of JDK 1.4<P>
**
** @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);
if (name.length() == 0)
{
throw new IntrospectionException("empty property name");
}
String caps = Character.toUpperCase(name.charAt(0)) + name.substring(1);
findMethods(beanClass, "is" + caps, "get" + caps, "set" + caps);
if (getMethod == null)
{
throw new IntrospectionException(
"Cannot find a is" + caps + " or get" + caps + " method");
}
if (setMethod == null)
{
throw new IntrospectionException(
"Cannot find a " + caps + " method");
}
// finally check the methods compatibility
propertyType = checkMethods(getMethod, setMethod);
}
/** 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 or <code>null</code> if the property is write-only.
** @param setMethodName the name of the set method or <code>null</code> if the property is read-only.
** @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);
if (getMethod == null && getMethodName != null)
{
throw new IntrospectionException(
"Cannot find a getter method called " + getMethodName);
}
if (setMethod == null && setMethodName != null)
{
throw new IntrospectionException(
"Cannot find a setter method called " + setMethodName);
}
propertyType = checkMethods(getMethod, setMethod);
}
/** 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.
**<br>
** It is possible to call this method with both <code>Method</code> arguments
** being <code>null</code>. In such a case the property type is <code>null</code>.
**
** @param name the programmatic name of the property, usually
** starting with a lowercase letter (e.g. fooManChu
** instead of FooManChu).
** @param readMethod the read method or <code>null</code> if the property is write-only.
** @param writeMethod the write method or <code>null</code> if the property is read-only.
** @exception IntrospectionException if the methods are not found
** or invalid.
**/
public PropertyDescriptor(
String name,
Method readMethod,
Method writeMethod)
throws IntrospectionException
{
setName(name);
getMethod = readMethod;
setMethod = writeMethod;
propertyType = checkMethods(getMethod, setMethod);
}
/** 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;
}
/** Sets the read method.<br/>
* The read method is used to retrieve the value of a property. A legal
* read method must have no arguments. Its return type must not be
* <code>void</code>. If this methods succeeds the property type
* is adjusted to the return type of the read method.<br/>
* <br/>
* It is legal to set the read and the write method to <code>null</code>
* or provide method which have been declared in distinct classes.
*
* @param readMethod The new method to be used or <code>null</code>.
* @throws IntrospectionException If the given method is invalid.
* @since 1.2
*/
public void setReadMethod(Method readMethod) throws IntrospectionException
{
propertyType = checkMethods(readMethod, setMethod);
getMethod = readMethod;
}
/** Get the set method. Why they call it writeMethod here and
** set everywhere else is beyond me.
**/
public Method getWriteMethod()
{
return setMethod;
}
/** Sets the write method.<br/>
* The write method is used to set the value of a property. A legal write method
* must have a single argument which can be assigned to the property. If no
* read method exists the property type changes to the argument type of the
* write method.<br/>
* <br/>
* It is legal to set the read and the write method to <code>null</code>
* or provide method which have been declared in distinct classes.
*
* @param writeMethod The new method to be used or <code>null</code>.
* @throws IntrospectionException If the given method is invalid.
* @since 1.2
*/
public void setWriteMethod(Method writeMethod)
throws IntrospectionException
{
propertyType = checkMethods(getMethod, writeMethod);
setMethod = writeMethod;
}
/** 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
{
// Try the first get method name
if (getMethodName1 != null)
{
try
{
getMethod =
beanClass.getMethod(getMethodName1, new Class[0]);
}
catch (NoSuchMethodException e)
{}
}
// Fall back to the second get method name
if (getMethod == null && getMethodName2 != null)
{
try
{
getMethod =
beanClass.getMethod(getMethodName2, new Class[0]);
}
catch (NoSuchMethodException e)
{}
}
// Try the set method name
if (setMethodName != null)
{
if (getMethod != null)
{
// If there is a get method, use its return type to help
// select the corresponding set method.
Class propertyType = getMethod.getReturnType();
if (propertyType == Void.TYPE)
{
String msg =
"The property's read method has return type 'void'";
throw new IntrospectionException(msg);
}
Class[] setArgs = new Class[] { propertyType };
try
{
setMethod = beanClass.getMethod(setMethodName, setArgs);
}
catch (NoSuchMethodException e)
{}
}
else if (getMethodName1 == null && getMethodName2 == null)
{
// If this is a write-only property, choose the first set method
// with the required name, one parameter and return type 'void'
Method[] methods = beanClass.getMethods();
for (int i = 0; i < methods.length; i++)
{
if (methods[i].getName().equals(setMethodName)
&& methods[i].getParameterTypes().length == 1
&& methods[i].getReturnType() == Void.TYPE)
{
setMethod = methods[i];
break;
}
}
}
}
}
catch (SecurityException e)
{
// FIXME -- shouldn't we just allow SecurityException to propagate?
String msg =
"SecurityException thrown on attempt to access methods.";
throw new IntrospectionException(msg);
}
}
/** Checks whether the given <code>Method</code> instances are legal read and
* write methods. The following requirements must be met:<br/>
* <ul>
* <li>the read method must not have an argument</li>
* <li>the read method must have a non void return type</li>
* <li>the read method may not exist</li>
* <li>the write method must have a single argument</li>
* <li>the property type and the read method's return type must be assignable from the
* write method's argument type</li>
* <li>the write method may not exist</li>
* </ul>
* While checking the methods a common new property type is calculated. If the method
* succeeds this property type is returned.<br/>
* <br/>
* For compatibility this has to be noted:<br/>
* The two methods are allowed to be defined in two distinct classes and may both be null.
*
* @param readMethod The new read method to check.
* @param writeMethod The new write method to check.
* @return The common property type of the two method.
* @throws IntrospectionException If any of the above requirements are not met.
*/
private Class checkMethods(Method readMethod, Method writeMethod)
throws IntrospectionException
{
Class newPropertyType = propertyType;
// a valid read method has zero arguments and a non-void return type.
if (readMethod != null)
{
if (readMethod.getParameterTypes().length > 0)
{
throw new IntrospectionException("read method has unexpected parameters");
}
newPropertyType = readMethod.getReturnType();
if (newPropertyType == Void.TYPE)
{
throw new IntrospectionException("read method return type is void");
}
}
// a valid write method has one argument which can be assigned to the property
if (writeMethod != null)
{
if (writeMethod.getParameterTypes().length != 1)
{
String msg = "write method does not have exactly one parameter";
throw new IntrospectionException(msg);
}
if (readMethod == null)
{
// changes the property type if there is no read method
newPropertyType = writeMethod.getParameterTypes()[0];
}
else
{
// checks whether the write method can be assigned to the return type of the read
// method (if this is not the case, the methods are not compatible)
// note: newPropertyType may be null if no methods or method names have been
// delivered in the constructor.
if (newPropertyType != null
&& !newPropertyType.isAssignableFrom(
writeMethod.getParameterTypes()[0]))
{
// note: newPropertyType is the same as readMethod.getReturnType() at this point
throw new IntrospectionException("read and write method are not compatible");
}
/* note: the check whether both method are defined in related classes makes sense but is not
* done in the JDK.
* I leave this code here in case someone at Sun decides to add that functionality in later versions (rschuster)
if ((!readMethod
.getDeclaringClass()
.isAssignableFrom(writeMethod.getDeclaringClass()))
&& (!writeMethod
.getDeclaringClass()
.isAssignableFrom(readMethod.getDeclaringClass())))
{
String msg =
"set and get methods are not in the same class.";
throw new IntrospectionException(msg);
}
*/
}
}
return newPropertyType;
}
/** Compares this <code>PropertyDescriptor</code> against the
* given object.
* Two PropertyDescriptors are equals if
* <ul>
* <li>the read methods are equal</li>
* <li>the write methods are equal</li>
* <li>the property types are equals</li>
* <li>the property editor classes are equal</li>
* <li>the flags (constrained and bound) are equal</li>
* </ul>
* @return Whether both objects are equal according to the rules given above.
* @since 1.4
*/
public boolean equals(Object o)
{
if (o instanceof PropertyDescriptor)
{
PropertyDescriptor that = (PropertyDescriptor) o;
// compares the property types and checks the case where both are null
boolean samePropertyType =
(propertyType == null)
? that.propertyType == null
: propertyType.equals(that.propertyType);
// compares the property editor classes and checks the case where both are null
boolean samePropertyEditorClass =
(propertyEditorClass == null)
? that.propertyEditorClass == null
: propertyEditorClass.equals(that.propertyEditorClass);
// compares the flags for equality
boolean sameFlags =
bound == that.bound && constrained == that.constrained;
// compares the read methods and checks the case where both are null
boolean sameReadMethod =
(getMethod == null)
? that.getMethod == null
: getMethod.equals(that.getMethod);
boolean sameWriteMethod =
(setMethod == null)
? that.setMethod == null
: setMethod.equals(that.setMethod);
return samePropertyType
&& sameFlags
&& sameReadMethod
&& sameWriteMethod
&& samePropertyEditorClass;
}
else
{
return false;
}
}
}
@@ -0,0 +1,209 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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>
** <LI>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.
**/
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.
**/
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.
**/
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.
**/
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.
**/
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.
**/
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
**/
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.
**/
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.
**/
java.awt.Component getCustomEditor();
/** Adds a property change listener to this PropertyEditor.
** @param listener the listener to add
**/
void addPropertyChangeListener(PropertyChangeListener listener);
/** Removes a property change listener from this PropertyEditor.
** @param listener the listener to remove
**/
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.
**/
String getJavaInitializationString();
}
@@ -0,0 +1,215 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import gnu.java.beans.editors.ColorEditor;
import gnu.java.beans.editors.FontEditor;
import gnu.java.beans.editors.NativeBooleanEditor;
import gnu.java.beans.editors.NativeByteEditor;
import gnu.java.beans.editors.NativeDoubleEditor;
import gnu.java.beans.editors.NativeFloatEditor;
import gnu.java.beans.editors.NativeIntEditor;
import gnu.java.beans.editors.NativeLongEditor;
import gnu.java.beans.editors.NativeShortEditor;
import gnu.java.beans.editors.StringEditor;
import gnu.java.lang.ClassHelper;
import java.awt.Color;
import java.awt.Font;
/**
* 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>
*
* <p><strong>Spec Suggestion:</strong> Perhaps an editor for
* Filename or something like it should be provided. As well
* as char.</p>
*
* @author John Keiser
* @since 1.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(Boolean.TYPE, NativeBooleanEditor.class);
registerEditor(Byte.TYPE, NativeByteEditor.class);
registerEditor(Short.TYPE, NativeShortEditor.class);
registerEditor(Integer.TYPE, NativeIntEditor.class);
registerEditor(Long.TYPE, NativeLongEditor.class);
registerEditor(Float.TYPE, NativeFloatEditor.class);
registerEditor(Double.TYPE, NativeDoubleEditor.class);
registerEditor(String.class, StringEditor.class);
registerEditor(Color.class, ColorEditor.class);
registerEditor(Font.class, FontEditor.class);
}
/**
* Beats me why this class can be instantiated, but there
* you have it.
*/
public PropertyEditorManager()
{
// Do nothing here
}
/**
* 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();
}
ClassLoader contextClassLoader
= Thread.currentThread().getContextClassLoader();
try
{
found = Class.forName(editedClass.getName()+"Editor", true,
contextClassLoader);
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,
true, contextClassLoader);
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;
}
}
}
@@ -0,0 +1,265 @@
/* java.beans.PropertyEditorSupport
Copyright (C) 1998, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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
* @author Robert Schuster
* @since 1.1
* @status updated to 1.5
*/
public class PropertyEditorSupport implements PropertyEditor
{
Object eventSource;
Object value;
PropertyChangeSupport pSupport;
/** Call this constructor when you are deriving from
* PropertyEditorSupport.
*
* Using this constructor the event source is this PropertyEditorSupport
* instance itself.
*
* @since 1.5
* @specnote this was <code>protected</code> prior to 1.5
*/
public PropertyEditorSupport()
{
eventSource = this;
pSupport = new PropertyChangeSupport(this);
}
/** Call this constructor when you are using
* PropertyEditorSupport as a helper object.
*
* This constructor throws a NullPointerException when <code>source</code> is <code>null</code>,
* for compatibility reasons with J2SDK 1.5.0 .
*
* @param source The source to use when firing
* property change events.
* @since 1.5
* @specnote this was <code>protected</code> prior to 1.5
*/
public PropertyEditorSupport(Object source)
{
// note: constructor rejects source being null for the sake of compatibility
// with official 1.5.0 implementation
if (source == null)
throw new NullPointerException("Event source must not be null.");
eventSource = source;
pSupport = new PropertyChangeSupport(eventSource);
}
/** Sets the current value of the property and a property change
* event is fired to all registered PropertyChangeListener instances.
*
* @param newValue The new value for the property.
*/
public void setValue(Object newValue)
{
value = newValue;
// specification in java.beans.PropertyChangeEvent says
// that without a property name (first argument) the
// new and the old value should always be null
pSupport.firePropertyChange(null, null, null);
}
/** Gets the current value of the property.
*
* @return the current value of the property.
*/
public Object getValue()
{
return value;
}
/** Gets whether this object is paintable or not.
*
* @return <CODE>false</CODE>
*/
public boolean isPaintable()
{
return false;
}
/** Paints this object. This class does nothing in
* this method.
*/
public void paintValue(java.awt.Graphics g, java.awt.Rectangle r)
{
}
/** Gets 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 "@$#^";
}
/** Gets 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 value != null ? value.toString() : "null";
}
/** Sets 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;
}
/** Returns a custom component to edit the value.
*
* @return <CODE>null</CODE> in this class.
*/
public java.awt.Component getCustomEditor()
{
return null;
}
/** Finds 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;
}
/** Adds a property change listener to this property editor.
*
* @param l the listener to add.
*/
public void addPropertyChangeListener(PropertyChangeListener l)
{
pSupport.addPropertyChangeListener(l);
}
/** Removes a property change listener from this property editor.
*
* @param l the listener to remove.
*/
public void removePropertyChangeListener(PropertyChangeListener l)
{
pSupport.removePropertyChangeListener(l);
}
/** Notifies people that we've changed, although we don't
* tell them just how.
*/
public void firePropertyChange()
{
pSupport.firePropertyChange(null, null, null);
}
/** Returns the bean that is used as the source of events.
*
* @return The event source object
* @since 1.5
*/
public Object getSource()
{
return eventSource;
}
/** Sets the bean that is used as the source of events
* when property changes occur.
*
* The event source bean is for informational purposes only
* and should not be changed by the <code>PropertyEditor</code>.
*
* @param source
* @since 1.5
*/
public void setSource(Object source)
{
eventSource = source;
}
}
@@ -0,0 +1,85 @@
/* PropertyVetoException.java -- thrown to veto a proposed property change
Copyright (C) 1998, 2000, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
/**
* PropertyVetoException is thrown when a VetoableChangeListener doesn't
* like the proposed change.
*
* @author John Keiser
* @see VetoableChangeListener
* @since 1.1
* @status updated to 1.4
*/
public class PropertyVetoException extends Exception
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = 129596057694162164L;
/**
* The vetoed change.
*
* @serial the event that was vetoed
*/
private final PropertyChangeEvent evt;
/**
* 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);
evt = changeEvent;
}
/**
* Get the PropertyChange event that was vetoed.
*
* @return the vetoed change
*/
public PropertyChangeEvent getPropertyChangeEvent()
{
return evt;
}
}
@@ -0,0 +1,139 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.awt.Image;
import java.awt.Toolkit;
/**
** 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));
}
}
+326
View File
@@ -0,0 +1,326 @@
/* java.beans.Statement
Copyright (C) 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* class Statement
*
* A Statement captures the execution of an object method. It stores
* the object, the method to call, and the arguments to the method and
* provides the ability to execute the method on the object, using the
* provided arguments.
*
* @since 1.4
*/
public class Statement
{
private Object target;
private String methodName;
private Object[] arguments;
// One or the other of these will get a value after execute is
// called once, but not both.
private transient Method method;
private transient Constructor ctor;
/**
* Constructs a statement representing the invocation of
* object.methodName(arg[0], arg[1], ...);
*
* @param target The object to invoke the method on.
* @param methodName The object method to invoke.
* @param arguments An array of arguments to pass to the method.
*/
public Statement(Object target, String methodName, Object[] arguments)
{
this.target = target;
this.methodName = methodName;
this.arguments = arguments;
}
/**
* Execute the statement.
*
* Finds the specified method in the target object and calls it with
* the arguments given in the constructor.
*
* The most specific method according to the JLS(15.11) is used when
* there are multiple methods with the same name.
*
* Execute performs some special handling for methods and
* parameters:
*
* Static methods can be executed by providing the class as a
* target.
*
* The method name new is reserved to call the constructor
* new() will construct an object and return it. Not useful unless
* an expression :-)
*
* If the target is an array, get and set as defined in
* java.util.List are recognized as valid methods and mapped to the
* methods of the same name in java.lang.reflect.Array.
*
* The native datatype wrappers Boolean, Byte, Character, Double,
* Float, Integer, Long, and Short will map to methods that have
* native datatypes as parameters, in the same way as Method.invoke.
* However, these wrappers also select methods that actually take
* the wrapper type as an argument.
*
* The Sun spec doesn't deal with overloading between int and
* Integer carefully. If there are two methods, one that takes an
* Integer and the other taking an int, the method chosen is not
* specified, and can depend on the order in which the methods are
* declared in the source file.
*
* @throws Exception if an exception occurs while locating or
* invoking the method.
*/
public void execute() throws Exception
{
doExecute();
}
private static Class wrappers[] =
{
Boolean.class, Byte.class, Character.class, Double.class, Float.class,
Integer.class, Long.class, Short.class
};
private static Class natives[] =
{
Boolean.TYPE, Byte.TYPE, Character.TYPE, Double.TYPE, Float.TYPE,
Integer.TYPE, Long.TYPE, Short.TYPE
};
// Given a wrapper class, return the native class for it. For
// example, if c is Integer, Integer.TYPE is returned.
private Class unwrap(Class c)
{
for (int i = 0; i < wrappers.length; i++)
if (c == wrappers[i])
return natives[i];
return null;
}
// Return true if all args can be assigned to params, false
// otherwise. Arrays are guaranteed to be the same length.
private boolean compatible(Class[] params, Class[] args)
{
for (int i = 0; i < params.length; i++)
{
// Treat Integer like int if appropriate
Class nativeType = unwrap(args[i]);
if (nativeType != null && params[i].isPrimitive()
&& params[i].isAssignableFrom(nativeType))
continue;
if (params[i].isAssignableFrom(args[i]))
continue;
return false;
}
return true;
}
/**
* Return true if the method arguments in first are more specific
* than the method arguments in second, i.e. all args in first can
* be assigned to those in second.
*
* A method is more specific if all parameters can also be fed to
* the less specific method, because, e.g. the less specific method
* accepts a base class of the equivalent argument for the more
* specific one.
*
* @param first a <code>Class[]</code> value
* @param second a <code>Class[]</code> value
* @return a <code>boolean</code> value
*/
private boolean moreSpecific(Class[] first, Class[] second)
{
for (int j=0; j < first.length; j++)
{
if (second[j].isAssignableFrom(first[j]))
continue;
return false;
}
return true;
}
final Object doExecute() throws Exception
{
Class klazz = (target instanceof Class)
? (Class) target : target.getClass();
Object args[] = (arguments == null) ? new Object[0] : arguments;
Class argTypes[] = new Class[args.length];
for (int i = 0; i < args.length; i++)
argTypes[i] = args[i].getClass();
if (target.getClass().isArray())
{
// FIXME: invoke may have to be used. For now, cast to Number
// and hope for the best. If caller didn't behave, we go boom
// and throw the exception.
if (methodName.equals("get") && argTypes.length == 1)
return Array.get(target, ((Number)args[0]).intValue());
if (methodName.equals("set") && argTypes.length == 2)
{
Object obj = Array.get(target, ((Number)args[0]).intValue());
Array.set(target, ((Number)args[0]).intValue(), args[1]);
return obj;
}
throw new NoSuchMethodException("No matching method for statement " + toString());
}
// If we already cached the method, just use it.
if (method != null)
return method.invoke(target, args);
else if (ctor != null)
return ctor.newInstance(args);
// Find a matching method to call. JDK seems to go through all
// this to find the method to call.
// if method name or length don't match, skip
// Need to go through each arg
// If arg is wrapper - check if method arg is matchable builtin
// or same type or super
// - check that method arg is same or super
if (methodName.equals("new") && target instanceof Class)
{
Constructor ctors[] = klazz.getConstructors();
for (int i = 0; i < ctors.length; i++)
{
// Skip methods with wrong number of args.
Class ptypes[] = ctors[i].getParameterTypes();
System.out.println("ptypeslen = " + ptypes.length);
System.out.println("ptypes = " + ptypes);
System.out.println("ctor = " + ctors[i].getName());
for (int j=0; j < ptypes.length; j++) {
System.out.println("param = " + ptypes[i].getName());
}
if (ptypes.length != args.length)
continue;
// Check if method matches
if (!compatible(ptypes, argTypes))
continue;
// Use method[i] if it is more specific.
// FIXME: should this check both directions and throw if
// neither is more specific?
if (ctor == null)
{
ctor = ctors[i];
continue;
}
Class mptypes[] = ctor.getParameterTypes();
if (moreSpecific(ptypes, mptypes))
ctor = ctors[i];
}
if (ctor == null)
throw new InstantiationException("No matching constructor for statement " + toString());
return ctor.newInstance(args);
}
Method methods[] = klazz.getMethods();
for (int i = 0; i < methods.length; i++)
{
// Skip methods with wrong name or number of args.
if (!methods[i].getName().equals(methodName))
continue;
Class ptypes[] = methods[i].getParameterTypes();
if (ptypes.length != args.length)
continue;
// Check if method matches
if (!compatible(ptypes, argTypes))
continue;
// Use method[i] if it is more specific.
// FIXME: should this check both directions and throw if
// neither is more specific?
if (method == null)
{
method = methods[i];
continue;
}
Class mptypes[] = method.getParameterTypes();
if (moreSpecific(ptypes, mptypes))
method = methods[i];
}
if (method == null)
throw new NoSuchMethodException("No matching method for statement " + toString());
return method.invoke(target, args);
}
/** Return the statement arguments. */
public Object[] getArguments() { return arguments; }
/** Return the statement method name. */
public String getMethodName() { return methodName; }
/** Return the statement object. */
public Object getTarget() { return target; }
/** Return a string representation. */
public String toString()
{
String result = target.getClass().getName() + "." + methodName + "(";
String sep = "";
for (int i = 0; i < arguments.length; i++)
{
result = result + sep + arguments[i].getClass().getName();
sep = ", ";
}
result = result + ")";
return result;
}
}
+4
View File
@@ -0,0 +1,4 @@
- add AppletStub and AppletContext to java.beans.Beans.instantiate().
- make Introspector more efficient.
- basic Introspection tests are in, but more tests are probably in order.
- 1.2 support (waiting on java.lang.Package, mainly)
@@ -0,0 +1,73 @@
/* VetoableChangeListener.java -- listen for a change which can be vetoed
Copyright (C) 1998, 2000, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.util.EventListener;
/**
* VetoableChangeListener allows a class to monitor proposed changes to
* properties of a Bean and, if desired, prevent them from occurring. A
* vetoableChange() event will be fired <em>after</em> the property change has
* been requested, but before it is permanent. 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 to revert back to the old value. Thus,
* the listener that threw the exception the first time should be prepared
* to rethrow it the second time. 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
* @see java.beans.PropertyChangeListener
* @see java.beans.VetoableChangeSupport
* @since 1.1
* @status updated to 1.4
*/
public interface VetoableChangeListener extends EventListener
{
/**
* Fired before a Bean's property changes.
*
* @param e the change (containing the old and new values)
* @throws PropertyVetoException if the change is vetoed by the listener
*/
void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException;
} // interface VetoableChangeListener
@@ -0,0 +1,102 @@
/* VetoableChangeListenerProxy.java -- adds a name to a vetoable listener
Copyright (C) 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.util.EventListenerProxy;
/**
* This class provides an extension to <code>VetoableChangeListener</code> -
* associating a name with the listener. This can be used to filter the
* changes that one is interested in.
*
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.4
* @status udpated to 1.4
*/
public class VetoableChangeListenerProxy extends EventListenerProxy
implements VetoableChangeListener
{
/**
* The name of the property to listen for. Package visible for use by
* VetoableChangeSupport.
*/
final String propertyName;
/**
* Create a new proxy which filters property change events and only passes
* changes to the named property on to the delegate.
*
* @param propertyName the property's name to filter on
* @param listener the delegate listener
*/
public VetoableChangeListenerProxy(String propertyName,
VetoableChangeListener listener)
{
super(listener);
this.propertyName = propertyName;
}
/**
* Forwards the event on to the delegate if the property name matches.
*
* @param event the event to pass on, if it meets the filter
* @throws NullPointerException if the delegate this was created with is null
* @throws PropertyVetoException if the change is vetoed by the listener
*/
public void vetoableChange(PropertyChangeEvent event)
throws PropertyVetoException
{
// Note: Sun does not filter, under the assumption that since
// VetoableChangeSupport unwraps proxys, this method should never be
// called by normal use of listeners.
String name = event == null ? null : event.getPropertyName();
if (name == null ? propertyName == null : name.equals(propertyName))
((VetoableChangeListener) getListener()).vetoableChange(event);
}
/**
* Gets the name of the property this proxy is filtering on.
*
* @return the property name
*/
public String getPropertyName()
{
return propertyName;
}
} // class VetoableChangeListenerProxy
@@ -0,0 +1,530 @@
/* VetoableChangeSupport.java -- support to manage vetoable change listeners
Copyright (C) 1998, 1999, 2000, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Vector;
/**
* VetoableChangeSupport makes it easy to fire vetoable change events and
* handle listeners. It allows chaining of listeners, as well as filtering
* by property name. In addition, it will serialize only those listeners
* which are serializable, ignoring the others without problem. This class
* is thread-safe.
*
* @author John Keiser
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.1
* @status updated to 1.4
*/
public class VetoableChangeSupport implements Serializable
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = -5090210921595982017L;
/**
* Maps property names (String) to named listeners (VetoableChangeSupport).
* If this is a child instance, this field will be null.
*
* @serial the map of property names to named listener managers
* @since 1.2
*/
private Hashtable children;
/**
* The non-null source object for any generated events.
*
* @serial the event source
*/
private final Object source;
/**
* A field to compare serialization versions - this class uses version 2.
*
* @serial the serialization format
*/
private static final int vetoableChangeSupportSerializedDataVersion = 2;
/**
* The list of all registered vetoable listeners. If this instance was
* created by user code, this only holds the global listeners (ie. not tied
* to a name), and may be null. If it was created by this class, as a
* helper for named properties, then this vector will be non-null, and this
* instance appears as a value in the <code>children</code> hashtable of
* another instance, so that the listeners are tied to the key of that
* hashtable entry.
*/
private transient Vector listeners;
/**
* Create a VetoableChangeSupport to work with a specific source bean.
*
* @param source the source bean to use
* @throws NullPointerException if source is null
*/
public VetoableChangeSupport(Object source)
{
this.source = source;
if (source == null)
throw new NullPointerException();
}
/**
* Adds a VetoableChangeListener to the list of global listeners. All
* vetoable change events will be sent to this listener. 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
* vetoable change. Adding a null listener may cause a NullPointerException
* down the road. This method will unwrap a VetoableChangeListenerProxy,
* registering the underlying delegate to the named property list.
*
* @param l the listener to add
*/
public synchronized void addVetoableChangeListener(VetoableChangeListener l)
{
if (l instanceof VetoableChangeListenerProxy)
{
VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
addVetoableChangeListener(p.propertyName,
(VetoableChangeListener) p.getListener());
}
else
{
if (listeners == null)
listeners = new Vector();
listeners.add(l);
}
}
/**
* Removes a VetoableChangeListener from the list of global 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. 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. This method will unwrap a
* VetoableChangeListenerProxy, removing the underlying delegate from the
* named property list.
*
* @param l the listener to remove
*/
public synchronized void
removeVetoableChangeListener(VetoableChangeListener l)
{
if (l instanceof VetoableChangeListenerProxy)
{
VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
removeVetoableChangeListener(p.propertyName,
(VetoableChangeListener) p.getListener());
}
else if (listeners != null)
{
listeners.remove(l);
if (listeners.isEmpty())
listeners = null;
}
}
/**
* Returns an array of all registered vetoable change listeners. Those that
* were registered under a name will be wrapped in a
* <code>VetoableChangeListenerProxy</code>, so you must check whether the
* listener is an instance of the proxy class in order to see what name the
* real listener is registered under. If there are no registered listeners,
* this returns an empty array.
*
* @return the array of registered listeners
* @see VetoableChangeListenerProxy
* @since 1.4
*/
public synchronized VetoableChangeListener[] getVetoableChangeListeners()
{
ArrayList list = new ArrayList();
if (listeners != null)
list.addAll(listeners);
if (children != null)
{
int i = children.size();
Iterator iter = children.entrySet().iterator();
while (--i >= 0)
{
Entry e = (Entry) iter.next();
String name = (String) e.getKey();
Vector v = ((VetoableChangeSupport) e.getValue()).listeners;
int j = v.size();
while (--j >= 0)
list.add(new VetoableChangeListenerProxy
(name, (VetoableChangeListener) v.get(j)));
}
}
return (VetoableChangeListener[])
list.toArray(new VetoableChangeListener[list.size()]);
}
/**
* Adds a VetoableChangeListener listening on the specified property. Events
* will be sent to the listener only if the property name matches. 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. The effect is
* cumulative, too; if you are registered to listen to receive events on
* all vetoable changes, and then you register on a particular property,
* you will receive change events for that property twice. Adding a null
* listener may cause a NullPointerException down the road. This method
* will unwrap a VetoableChangeListenerProxy, registering the underlying
* delegate to the named property list if the names match, and discarding
* it otherwise.
*
* @param propertyName the name of the property to listen on
* @param l the listener to add
* @throws NullPointerException if propertyName is null
*/
public synchronized void addVetoableChangeListener(String propertyName,
VetoableChangeListener l)
{
while (l instanceof VetoableChangeListenerProxy)
{
VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
if (propertyName == null ? p.propertyName != null
: ! propertyName.equals(p.propertyName))
return;
l = (VetoableChangeListener) p.getListener();
}
VetoableChangeSupport s = null;
if (children == null)
children = new Hashtable();
else
s = (VetoableChangeSupport) children.get(propertyName);
if (s == null)
{
s = new VetoableChangeSupport(source);
s.listeners = new Vector();
children.put(propertyName, s);
}
s.listeners.add(l);
}
/**
* Removes a VetoableChangeListener from listening to a specific property.
* 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. This method will unwrap a
* VetoableChangeListenerProxy, removing the underlying delegate from the
* named property list if the names match.
*
* @param propertyName the property to stop listening on
* @param l the listener to remove
* @throws NullPointerException if propertyName is null
*/
public synchronized void
removeVetoableChangeListener(String propertyName, VetoableChangeListener l)
{
if (children == null)
return;
VetoableChangeSupport s
= (VetoableChangeSupport) children.get(propertyName);
if (s == null)
return;
while (l instanceof VetoableChangeListenerProxy)
{
VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
if (propertyName == null ? p.propertyName != null
: ! propertyName.equals(p.propertyName))
return;
l = (VetoableChangeListener) p.getListener();
}
s.listeners.remove(l);
if (s.listeners.isEmpty())
{
children.remove(propertyName);
if (children.isEmpty())
children = null;
}
}
/**
* Returns an array of all vetoable change listeners registered under the
* given property name. If there are no registered listeners, this returns
* an empty array.
*
* @return the array of registered listeners
* @throws NullPointerException if propertyName is null
* @since 1.4
*/
public synchronized VetoableChangeListener[]
getVetoableChangeListeners(String propertyName)
{
if (children == null)
return new VetoableChangeListener[0];
VetoableChangeSupport s
= (VetoableChangeSupport) children.get(propertyName);
if (s == null)
return new VetoableChangeListener[0];
return (VetoableChangeListener[])
s.listeners.toArray(new VetoableChangeListener[s.listeners.size()]);
}
/**
* Fire a PropertyChangeEvent containing the old and new values of the
* property to all the global listeners, and to all the listeners for the
* specified property name. This does nothing if old and new are non-null
* and equal. If the change is vetoed, a new event is fired to notify
* listeners about the rollback before the exception is thrown.
*
* @param propertyName the name of the property that changed
* @param oldVal the old value
* @param newVal the new value
* @throws PropertyVetoException if the change is vetoed by a listener
*/
public void fireVetoableChange(String propertyName,
Object oldVal, Object newVal)
throws PropertyVetoException
{
fireVetoableChange(new PropertyChangeEvent(source, propertyName,
oldVal, newVal));
}
/**
* Fire a PropertyChangeEvent containing the old and new values of the
* property to all the global listeners, and to all the listeners for the
* specified property name. This does nothing if old and new are equal.
* If the change is vetoed, a new event is fired to notify listeners about
* the rollback before the exception is thrown.
*
* @param propertyName the name of the property that changed
* @param oldVal the old value
* @param newVal the new value
* @throws PropertyVetoException if the change is vetoed by a listener
*/
public void fireVetoableChange(String propertyName, int oldVal, int newVal)
throws PropertyVetoException
{
if (oldVal != newVal)
fireVetoableChange(new PropertyChangeEvent(source, propertyName,
new Integer(oldVal),
new Integer(newVal)));
}
/**
* Fire a PropertyChangeEvent containing the old and new values of the
* property to all the global listeners, and to all the listeners for the
* specified property name. This does nothing if old and new are equal.
* If the change is vetoed, a new event is fired to notify listeners about
* the rollback before the exception is thrown.
*
* @param propertyName the name of the property that changed
* @param oldVal the old value
* @param newVal the new value
* @throws PropertyVetoException if the change is vetoed by a listener
*/
public void fireVetoableChange(String propertyName,
boolean oldVal, boolean newVal)
throws PropertyVetoException
{
if (oldVal != newVal)
fireVetoableChange(new PropertyChangeEvent(source, propertyName,
Boolean.valueOf(oldVal),
Boolean.valueOf(newVal)));
}
/**
* Fire a PropertyChangeEvent to all the global listeners, and to all the
* listeners for the specified property name. This does nothing if old and
* new values of the event are equal. If the change is vetoed, a new event
* is fired to notify listeners about the rollback before the exception is
* thrown.
*
* @param event the event to fire
* @throws NullPointerException if event is null
* @throws PropertyVetoException if the change is vetoed by a listener
*/
public void fireVetoableChange(PropertyChangeEvent event)
throws PropertyVetoException
{
if (event.oldValue != null && event.oldValue.equals(event.newValue))
return;
Vector v = listeners; // Be thread-safe.
if (v != null)
{
int i = v.size();
try
{
while (--i >= 0)
((VetoableChangeListener) v.get(i)).vetoableChange(event);
}
catch (PropertyVetoException e)
{
event = event.rollback();
int limit = i;
i = v.size();
while (--i >= limit)
((VetoableChangeListener) v.get(i)).vetoableChange(event);
throw e;
}
}
Hashtable h = children; // Be thread-safe.
if (h != null && event.propertyName != null)
{
VetoableChangeSupport s
= (VetoableChangeSupport) h.get(event.propertyName);
if (s != null)
{
Vector v1 = s.listeners; // Be thread-safe.
int i = v1 == null ? 0 : v1.size();
try
{
while (--i >= 0)
((VetoableChangeListener) v1.get(i)).vetoableChange(event);
}
catch (PropertyVetoException e)
{
event = event.rollback();
int limit = i;
i = v.size();
while (--i >= 0)
((VetoableChangeListener) v.get(i)).vetoableChange(event);
i = v1.size();
while (--i >= limit)
((VetoableChangeListener) v1.get(i)).vetoableChange(event);
throw e;
}
}
}
}
/**
* 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
* @throws NullPointerException if propertyName is null
*/
public synchronized boolean hasListeners(String propertyName)
{
return listeners != null || (children != null
&& children.get(propertyName) != null);
}
/**
* Saves the state of the object to the stream.
*
* @param s the stream to write to
* @throws IOException if anything goes wrong
* @serialData this writes out a null-terminated list of serializable
* global vetoable change listeners (the listeners for a named
* property are written out as the global listeners of the
* children, when the children hashtable is saved)
*/
private synchronized void writeObject(ObjectOutputStream s)
throws IOException
{
s.defaultWriteObject();
if (listeners != null)
{
int i = listeners.size();
while (--i >= 0)
if (listeners.get(i) instanceof Serializable)
s.writeObject(listeners.get(i));
}
s.writeObject(null);
}
/**
* Reads the object back from stream (deserialization).
*
* XXX Since serialization for 1.1 streams was not documented, this may
* not work if vetoableChangeSupportSerializedDataVersion is 1.
*
* @param s the stream to read from
* @throws IOException if reading the stream fails
* @throws ClassNotFoundException if deserialization fails
* @serialData this reads in a null-terminated list of serializable
* global vetoable change listeners (the listeners for a named
* property are written out as the global listeners of the
* children, when the children hashtable is saved)
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
VetoableChangeListener l = (VetoableChangeListener) s.readObject();
while (l != null)
{
addVetoableChangeListener(l);
l = (VetoableChangeListener) s.readObject();
}
// Sun is not as careful with children as we are, and lets some proxys
// in that can never receive events. So, we clean up anything that got
// serialized, to make sure our invariants hold.
if (children != null)
{
int i = children.size();
Iterator iter = children.entrySet().iterator();
while (--i >= 0)
{
Entry e = (Entry) iter.next();
String name = (String) e.getKey();
VetoableChangeSupport vcs = (VetoableChangeSupport) e.getValue();
if (vcs.listeners == null)
vcs.listeners = new Vector();
if (vcs.children != null)
vcs.listeners.addAll
(Arrays.asList(vcs.getVetoableChangeListeners(name)));
if (vcs.listeners.size() == 0)
iter.remove();
else
vcs.children = null;
}
if (children.size() == 0)
children = null;
}
}
} // class VetoableChangeSupport
@@ -0,0 +1,85 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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.
*/
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.
*/
boolean avoidingGui();
/**
* Tells the Bean not to use GUI methods.
* If needsGUI() is false, then after this method is called,
* avoidingGui() should return true.
*/
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.
*/
void okToUseGui();
}
@@ -0,0 +1,307 @@
/* java.beans.XMLDecoder --
Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans;
import gnu.java.beans.decoder.DefaultExceptionListener;
import gnu.java.beans.decoder.PersistenceParser;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* The XMLDecoder reads XML data that is structured according to
* <a href="http://java.sun.com/products/jfc/tsc/articles/persistence3/javabeans.dtd">this</a> DTD
* and creates objects according to the content. Usually such data is generated using the
* {@link XMLEncoder} class.
* <p>
* An example XML document might look like this:
* <code>
* &lt;java&gt;
* &lt;string&gt;Hello World&lt;/string&gt;
* &lt;int&gt;200&lt;/int&gt;
* &lt;/java&gt;
* </code>
* <p>To read the <code>String</code> and the <code>Integer</code> instance the following can be used (assume
* the XML data can be obtained from the InputStream):</p>
* <code>
* XMLDecoder decoder = new XMLDecoder(inputStreamContainingXMLData);
* String message = (String) decoder.readObject();
* Integer number = (Integer) decoder.readObject();
* </code>
* <p>Besides this basic functionality the <code>XMLDecoder</code> has some more features that might come
* handy in certain situations:</p>
* <p>An owner object can be set using the <code>setOwner</code> method which can then be accessed when
* decoding. This feature is only useful if the XML data is aware of the owner object. Such data may
* look like this (assume that the owner object is a JFrame instance):</p>
* <code>
* &lt;java&gt;
* &lt;void method="getOwner"&gt;
* &lt;void method="setVisible"&gt;
* &lt;boolean&gt;true&lt;boolean&gt;
* &lt;/void&gt;
* &lt;/void&gt;
* &lt;/java&gt;
* </code>
* This accesses the <code>JFrame</code> and makes it visible using the <code>setVisible</code> method.
* <p>Please note that changing the owner <b>after</b> the having read the first object has no effect,
* because all object have been decoded then.</p>
* <p>If the <code>XMLDecoder</code> is created with no {@link ExceptionListener} instance a default one
* is used that prints an error message to <code>System.err</code> whenever a recoverable exception
* is thrown. Recovarable exceptions occur when the XML data cannot be interpreted correctly (e.g
* unknown classes or methods, invocation on null, ...). In general be very careful when the
* <code>XMLDecoder</code> provoked such exceptions because the resulting object(s) may be in an
* undesirable state.</p>
* <p>Note that changing the ExceptionListener instance after <code>readObject</code> has been called
* once has no effect because the decoding is completed then.</p>
* <p>At last one can provide a specific <code>ClassLoader</code> which is then used when <code>Class</code>
* objects are accessed. See {@link java.lang.Class#forName(String, boolean, ClassLoader)} for details
* on this.</p>
* <p>Note: If the <code>InputStream</code> instance given to any of the constructors is <code>null</code>
* the resulting <code>XMLDecoder</code> will be silently (without any exception) useless. Each call
* to <code>readObject</code> will return <code>null</code> and never throws an
* <code>ArrayIndexOutOfBoundsException</code>.</p>
*
* @author Robert Schuster
* @since 1.4
* @status updated to 1.5
*/
public class XMLDecoder
{
private Object owner;
private ExceptionListener exceptionListener;
private InputStream inputStream;
private boolean isStreamClosed;
private ClassLoader classLoader;
private Iterator iterator;
/** Creates a XMLDecoder instance that parses the XML data of the given input stream.
* Using this constructor no special ClassLoader, a default ExceptionListener
* and no owner object is used.
*
* @param in InputStream to read XML data from.
*/
public XMLDecoder(InputStream in)
{
this(in, null);
}
/** Creates a XMLDecoder instance that parses the XML data of the given input stream.
* Using this constructor no special ClassLoader and a default ExceptionListener
* is used.
*
* @param in InputStream to read XML data from.
* @param owner Owner object which can be accessed and modified while parsing.
*/
public XMLDecoder(InputStream in, Object owner)
{
this(in, owner, null);
}
/** Creates a XMLDecoder instance that parses the XML data of the given input stream.
* If the ExceptionListener argument is null a default implementation is used.
*
* @param in InputStream to read XML data from.
* @param owner Owner object which can be accessed and modified while parsing.
* @param exceptionListener ExceptionListener instance to which exception notifications are send.
*/
public XMLDecoder(
InputStream in,
Object owner,
ExceptionListener exceptionListener)
{
this(
in,
owner,
exceptionListener,
Thread.currentThread().getContextClassLoader());
}
/** Creates a XMLDecoder instance that parses the XML data of the given input stream.
* If the ExceptionListener argument is null a default implementation is used.
*
* @param in InputStream to read XML data from.
* @param owner Owner object which can be accessed and modified while parsing.
* @param exceptionListener ExceptionListener instance to which exception notifications are send.
* @param cl ClassLoader instance that is used for calls to <code>Class.forName(String, boolean, ClassLoader)</code>
* @since 1.5
*/
public XMLDecoder(
InputStream in,
Object owner,
ExceptionListener listener,
ClassLoader cl)
{
// initially here was a check for the validity of the InputStream argument but some
// great engineers decided that this API should silently discard this and behave rather
// odd: readObject will always return null ...
inputStream = in;
setExceptionListener(listener);
// validity of this object is checked in Class.forName() and therefore may be null
classLoader = cl;
this.owner = owner;
}
/** Closes the stream associated with this decoder. This should be done after having read all
* decoded objects.
* <p>See the description of the {@link #readObject()} for the effect caused by <code>close</code>.</p>
*/
public void close()
{
if (isStreamClosed)
{
return;
}
try
{
inputStream.close();
isStreamClosed = true;
}
catch (IOException e)
{
// bad style forced by original API design ...
}
}
/** Returns the ExceptionListener instance associated with this decoder.
* <p>See the description of {@link XMLDecoder} class for more information on the ExceptionListener.</p>
*
* @return Current ExceptionListener of the decoder.
*/
public ExceptionListener getExceptionListener()
{
return exceptionListener;
}
/** Returns the owner object of the decoder. This method is usually called
* from within the parsed XML data.
* <p>See the description of {@link XMLDecoder} class for more information on the owner object.</p>
*
* @return The owner object of this decoder.
*/
public Object getOwner()
{
return owner;
}
/** Returns the next available decoded object.
* <p>Note that the actual decoding takes place when the method is called for the first time.</p>
* <p>If the <code>close</code> method was already called a <code>NoSuchElementException</code>
* is thrown.</p>
* <p>If the InputStream instance used in the constructors was <code>null</code> this method
* will always return <code>null</code> itself.</p>
*
* @return The next object in a sequence decoded from XML data.
* @throws ArrayIndexOutOfBoundsException When no more objects are available.
*/
public Object readObject() throws ArrayIndexOutOfBoundsException
{
// note: the RI does it this way ...
if(inputStream == null) {
return null;
}
// note: the original API documentation says nothing on what to do
// when the stream was closed before readObject is called but it actually
// throws a NoSuchElementException - this behaviour is imitated here
if (isStreamClosed)
{
throw new NoSuchElementException("Cannot read any objects - XMLDecoder was already closed.");
}
// creates the PersistenceParser (doing the parsing and decoding) and returns its
// Iterator on first invocation
if (iterator == null)
{
iterator =
new PersistenceParser(
inputStream,
exceptionListener,
classLoader,
this)
.iterator();
}
// note: done according to the official documentation
if (!iterator.hasNext())
{
throw new ArrayIndexOutOfBoundsException("No more objects available from this XMLDecoder.");
}
// returns just the next object if there was no problem
return iterator.next();
}
/** Sets the ExceptionListener instance to which notifications of exceptions are send
* while parsing the XML data.
* <p>See the description of {@link XMLDecoder} class for more information on the ExceptionListener.</p>
*
* @param listener
*/
public void setExceptionListener(ExceptionListener listener)
{
// uses a default implementation when null
if (listener == null)
{
listener = new DefaultExceptionListener();
}
exceptionListener = listener;
}
/** Sets the owner object which can be accessed from the parsed XML data.
* <p>See the description of {@link XMLDecoder} class for more information on the owner object.</p>
*
* @param newOwner
*/
public void setOwner(Object newOwner)
{
owner = newOwner;
}
}
@@ -0,0 +1,272 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans.beancontext;
import java.beans.DesignMode;
import java.beans.Visibility;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
/**
* 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.
*/
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.
*/
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)
*/
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)
*/
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.
*/
void addBeanContextMembershipListener(BeanContextMembershipListener listener);
/**
* Remove a listener on changes to the membership of this
* <code>BeanContext</code> object.
* @param listener the listener to remove.
*/
void removeBeanContextMembershipListener(BeanContextMembershipListener listener);
}
@@ -0,0 +1,174 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans.beancontext;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
/**
* 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.
*/
void setBeanContext(BeanContext parent)
throws PropertyVetoException;
/**
* Get the parent <code>BeanContext</code>.
* @return the parent <code>BeanContext</code>.
*/
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.
*/
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.
*/
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.
*/
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.
*/
void removeVetoableChangeListener(String prop, VetoableChangeListener listener);
}
@@ -0,0 +1,60 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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>.
*/
Component getComponent();
}
@@ -0,0 +1,381 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans.beancontext;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
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 1.2
* @see java.beans.beancontext.BeanContextChild
*/
public class BeanContextChildSupport
implements BeanContextChild, BeanContextServicesListener, Serializable
{
static final long serialVersionUID = 6328947014421475877L;
/**
* 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() {
}
}
@@ -0,0 +1,63 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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>.
*/
Container getContainer();
}
@@ -0,0 +1,110 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans.beancontext;
import java.util.EventObject;
/**
* Generic superclass for events fired by <code>BeanContext</code>s.
*
* @author John Keiser
* @since 1.2
*/
public abstract class BeanContextEvent extends EventObject
{
private static final long serialVersionUID = 7267998073569045052L;
/**
* 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;
}
}
@@ -0,0 +1,112 @@
/* java.beans.beancontext.BeanContextMembershipEvent
Copyright (C) 1999, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans.beancontext;
import java.util.Arrays;
import java.util.Collection;
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 1.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);
}
}
@@ -0,0 +1,70 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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)
*/
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)
*/
void childrenRemoved(BeanContextMembershipEvent event);
}
@@ -0,0 +1,65 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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>.
*/
BeanContextChild getBeanContextProxy();
}
@@ -0,0 +1,95 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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();
}
}
@@ -0,0 +1,138 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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()</code>.
*
* <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)
*/
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)
*/
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)
*/
Iterator getCurrentServiceSelectors(BeanContextServices services, Class serviceClass);
}
@@ -0,0 +1,60 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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.
*/
BeanInfo[] getServicesBeanInfo();
}
@@ -0,0 +1,110 @@
/* java.beans.beancontext.BeanContextServiceRevokedEvent
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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 invalidateRefs;
/**
* 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;
invalidateRefs = 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 invalidateRefs;
}
}
@@ -0,0 +1,62 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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)
*/
void serviceRevoked(BeanContextServiceRevokedEvent event);
}
@@ -0,0 +1,216 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans.beancontext;
import java.util.Iterator;
import java.util.TooManyListenersException;
/**
* 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 1.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.
*/
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.
*/
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)
*/
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>.
*/
Object getService (BeanContextChild requestorChild, Object requestor,
Class serviceClass, Object serviceSelector,
BeanContextServiceRevokedListener listener)
throws TooManyListenersException;
/**
* 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
*/
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>.
*/
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 available.
*/
boolean hasService (Class serviceClass);
/**
* Add a listener on all adds and removes of services.
* @param listener the listener to add.
*/
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.
*/
void removeBeanContextServicesListener (BeanContextServicesListener listener);
}
@@ -0,0 +1,56 @@
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
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.
*/
void serviceAvailable(BeanContextServiceAvailableEvent event);
}
@@ -0,0 +1,300 @@
/* BeanContextServicesSupport.java --
Copyright (C) 2003, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans.beancontext;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.TooManyListenersException;
/**
* @author Michael Koch
* @since 1.2
*/
public class BeanContextServicesSupport
extends BeanContextSupport
implements BeanContextServices
{
private static final long serialVersionUID = -8494482757288719206L;
protected class BCSSChild
extends BeanContextSupport.BCSChild
{
private static final long serialVersionUID = -6848044915271367103L;
}
protected class BCSSProxyServiceProvider
implements BeanContextServiceProvider,
BeanContextServiceRevokedListener
{
private static final long serialVersionUID = 7078212910685744490L;
public Iterator getCurrentServiceSelectors (BeanContextServices bcs,
Class serviceClass)
{
throw new Error ("Not implemented");
}
public Object getService (BeanContextServices bcs,
Object requestor,
Class serviceClass,
Object serviceSelector)
{
throw new Error ("Not implemented");
}
public void releaseService (BeanContextServices bcs,
Object requestor,
Object service)
{
throw new Error ("Not implemented");
}
public void serviceRevoked (BeanContextServiceRevokedEvent bcsre)
{
throw new Error ("Not implemented");
}
}
protected static class BCSSServiceProvider
implements Serializable
{
private static final long serialVersionUID = 861278251667444782L;
protected BeanContextServiceProvider serviceProvider;
protected BeanContextServiceProvider getServiceProvider()
{
return serviceProvider;
}
}
protected transient ArrayList bcsListeners;
protected transient BCSSProxyServiceProvider proxy;
protected transient int serializable;
protected transient HashMap services;
public BeanContextServicesSupport ()
{
super();
}
public BeanContextServicesSupport (BeanContextServices peer)
{
super(peer);
}
public BeanContextServicesSupport(BeanContextServices peer, Locale locale)
{
super(peer, locale);
}
public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
boolean dtime)
{
super(peer, locale, dtime);
}
public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
boolean dtime, boolean visible)
{
super(peer, locale, dtime, visible);
}
public void addBeanContextServicesListener
(BeanContextServicesListener listener)
{
if (! bcsListeners.contains(listener))
bcsListeners.add(listener);
}
public boolean addService (Class serviceClass, BeanContextServiceProvider bcsp)
{
throw new Error ("Not implemented");
}
protected boolean addService (Class serviceClass,
BeanContextServiceProvider bcsp,
boolean fireEvent)
{
throw new Error ("Not implemented");
}
protected void bcsPreDeserializationHook (ObjectInputStream ois)
throws ClassNotFoundException, IOException
{
throw new Error ("Not implemented");
}
protected void bcsPreSerializationHook (ObjectOutputStream oos)
throws IOException
{
throw new Error ("Not implemented");
}
protected void childJustRemovedHook (Object child,
BeanContextSupport.BCSChild bcsc)
{
throw new Error ("Not implemented");
}
protected BeanContextSupport.BCSChild createBCSChild (Object targetChild,
Object peer)
{
throw new Error ("Not implemented");
}
protected BeanContextServicesSupport.BCSSServiceProvider
createBCSSServiceProvider (Class sc, BeanContextServiceProvider bcsp)
{
throw new Error ("Not implemented");
}
protected final void fireServiceAdded (BeanContextServiceAvailableEvent bcssae)
{
throw new Error ("Not implemented");
}
protected final void fireServiceAdded (Class serviceClass)
{
throw new Error ("Not implemented");
}
protected final void fireServiceRevoked(BeanContextServiceRevokedEvent event)
{
throw new Error ("Not implemented");
}
protected final void fireServiceRevoked (Class serviceClass,
boolean revokeNow)
{
throw new Error ("Not implemented");
}
public BeanContextServices getBeanContextServicesPeer ()
{
throw new Error ("Not implemented");
}
protected static final BeanContextServicesListener
getChildBeanContextServicesListener (Object child)
{
throw new Error ("Not implemented");
}
public Iterator getCurrentServiceClasses ()
{
throw new Error ("Not implemented");
}
public Iterator getCurrentServiceSelectors (Class serviceClass)
{
throw new Error ("Not implemented");
}
public Object getService (BeanContextChild child, Object requestor,
Class serviceClass, Object serviceSelector,
BeanContextServiceRevokedListener bcsrl)
throws TooManyListenersException
{
throw new Error ("Not implemented");
}
public boolean hasService (Class serviceClass)
{
throw new Error ("Not implemented");
}
public void initialize ()
{
super.initialize();
bcsListeners = new ArrayList();
services = new HashMap();
}
protected void initializeBeanContextResources ()
{
throw new Error ("Not implemented");
}
protected void releaseBeanContextResources ()
{
throw new Error ("Not implemented");
}
public void releaseService (BeanContextChild child, Object requestor,
Object service)
{
throw new Error ("Not implemented");
}
public void removeBeanContextServicesListener
(BeanContextServicesListener listener)
{
int index = bcsListeners.indexOf(listener);
if (index > -1)
bcsListeners.remove(index);
}
public void revokeService (Class serviceClass, BeanContextServiceProvider bcsp,
boolean revokeCurrentServicesNow)
{
throw new Error ("Not implemented");
}
public void serviceAvailable (BeanContextServiceAvailableEvent bcssae)
{
throw new Error ("Not implemented");
}
public void serviceRevoked (BeanContextServiceRevokedEvent bcssre)
{
throw new Error ("Not implemented");
}
}
@@ -0,0 +1,460 @@
/* BeanContextSupport.java --
Copyright (C) 2003, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.beans.beancontext;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.Visibility;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
/**
* @author Michael Koch
* @since 1.2
*/
public class BeanContextSupport extends BeanContextChildSupport
implements BeanContext, Serializable, PropertyChangeListener,
VetoableChangeListener
{
private static final long serialVersionUID = -4879613978649577204L;
private void readObject (ObjectInputStream s)
throws ClassNotFoundException, IOException
{
throw new Error ("Not implemented");
}
private void writeObject (ObjectOutputStream s)
throws ClassNotFoundException, IOException
{
throw new Error ("Not implemented");
}
protected class BCSChild implements Serializable
{
private static final long serialVersionUID = 3289144128843950629L;
}
protected static final class BCSIterator implements Iterator
{
public boolean hasNext ()
{
throw new Error ("Not implemented");
}
public Object next ()
{
throw new Error ("Not implemented");
}
public void remove ()
{
// This must be a noop remove operation.
}
}
protected transient ArrayList bcmListeners;
protected transient HashMap children;
protected transient boolean designTime;
protected transient Locale locale;
protected transient boolean okToUseGui;
/**
* Construct a BeanContextSupport instance.
*/
public BeanContextSupport ()
{
this (null, null, true, true);
}
/**
* Construct a BeanContextSupport instance.
*/
public BeanContextSupport (BeanContext peer)
{
this (peer, null, true, true);
}
/**
* Construct a BeanContextSupport instance.
*/
public BeanContextSupport (BeanContext peer, Locale lcle)
{
this (peer, lcle, true, true);
}
/**
* Construct a BeanContextSupport instance.
*/
public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime)
{
this (peer, lcle, dtime, true);
}
/**
* Construct a BeanContextSupport instance.
*/
public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime,
boolean visible)
{
locale = lcle;
designTime = dtime;
okToUseGui = visible;
initialize ();
}
public boolean add (Object targetChild)
{
if (targetChild == null)
throw new IllegalArgumentException();
if (children.containsKey(targetChild))
return false;
// FIXME: The second argument is surely wrong.
children.put(targetChild, targetChild);
return true;
}
public boolean addAll (Collection c)
{
throw new UnsupportedOperationException();
}
public void addBeanContextMembershipListener
(BeanContextMembershipListener listener)
{
if (! bcmListeners.contains(listener))
bcmListeners.add(listener);
}
public boolean avoidingGui ()
{
throw new Error ("Not implemented");
}
protected Iterator bcsChildren ()
{
throw new Error ("Not implemented");
}
protected void bcsPreDeserializationHook (ObjectInputStream ois)
throws ClassNotFoundException, IOException
{
throw new Error ("Not implemented");
}
protected void bcsPreSerializationHook (ObjectOutputStream oos)
throws IOException
{
throw new Error ("Not implemented");
}
protected void childDeserializedHook (Object child, BeanContextSupport.BCSChild bcsc)
{
throw new Error ("Not implemented");
}
protected void childJustAddedHook (Object child, BeanContextSupport.BCSChild bcsc)
{
throw new Error ("Not implemented");
}
protected void childJustRemovedHook (Object child, BeanContextSupport.BCSChild bcsc)
{
throw new Error ("Not implemented");
}
protected static final boolean classEquals (Class first, Class second)
{
throw new Error ("Not implemented");
}
public void clear ()
{
throw new UnsupportedOperationException();
}
public boolean contains (Object o)
{
throw new Error ("Not implemented");
}
public boolean containsAll (Collection c)
{
throw new Error ("Not implemented");
}
public boolean containsKey (Object o)
{
throw new Error ("Not implemented");
}
protected final Object[] copyChildren ()
{
throw new Error ("Not implemented");
}
protected BeanContextSupport.BCSChild createBCSChild (Object targetChild, Object peer)
{
throw new Error ("Not implemented");
}
protected final void deserialize (ObjectInputStream ois, Collection coll)
throws ClassNotFoundException, IOException
{
throw new Error ("Not implemented");
}
public void dontUseGui ()
{
throw new Error ("Not implemented");
}
protected final void fireChildrenAdded (BeanContextMembershipEvent bcme)
{
throw new Error ("Not implemented");
}
protected final void fireChildrenRemoved (BeanContextMembershipEvent bcme)
{
throw new Error ("Not implemented");
}
public BeanContext getBeanContextPeer ()
{
throw new Error ("Not implemented");
}
protected static final BeanContextChild getChildBeanContextChild (Object child)
{
throw new Error ("Not implemented");
}
protected static final BeanContextMembershipListener getChildBeanContextMembershipListener (Object child)
{
throw new Error ("Not implemented");
}
protected static final PropertyChangeListener getChildPropertyChangeListener (Object child)
{
throw new Error ("Not implemented");
}
protected static final Serializable getChildSerializable (Object child)
{
throw new Error ("Not implemented");
}
protected static final VetoableChangeListener getChildVetoableChangeListener (Object child)
{
throw new Error ("Not implemented");
}
protected static final Visibility getChildVisibility (Object child)
{
throw new Error ("Not implemented");
}
public Locale getLocale ()
{
return locale;
}
public URL getResource (String name, BeanContextChild bcc)
{
throw new Error ("Not implemented");
}
public InputStream getResourceAsStream (String name, BeanContextChild bcc)
{
throw new Error ("Not implemented");
}
protected void initialize ()
{
bcmListeners = new ArrayList();
children = new HashMap();
}
public Object instantiateChild (String beanName)
throws IOException, ClassNotFoundException
{
throw new Error ("Not implemented");
}
public boolean isDesignTime ()
{
throw new Error ("Not implemented");
}
public boolean isEmpty ()
{
throw new Error ("Not implemented");
}
public boolean isSerializing ()
{
throw new Error ("Not implemented");
}
public Iterator iterator ()
{
return children.keySet().iterator();
}
public boolean needsGui ()
{
throw new Error ("Not implemented");
}
public void okToUseGui ()
{
throw new Error ("Not implemented");
}
public void propertyChange (PropertyChangeEvent pce)
{
throw new Error ("Not implemented");
}
public final void readChildren (ObjectInputStream ois)
throws IOException, ClassNotFoundException
{
throw new Error ("Not implemented");
}
public boolean remove (Object targetChild)
{
return remove(targetChild, true);
}
protected boolean remove (Object targetChild, boolean callChildSetBC)
{
if (targetChild == null)
throw new IllegalArgumentException();
throw new Error ("Not implemented");
}
public boolean removeAll (Collection c)
{
throw new UnsupportedOperationException();
}
public void removeBeanContextMembershipListener (BeanContextMembershipListener bcml)
{
throw new Error ("Not implemented");
}
public boolean retainAll (Collection c)
{
throw new UnsupportedOperationException();
}
protected final void serialize (ObjectOutputStream oos, Collection coll)
throws IOException
{
throw new Error ("Not implemented");
}
public void setDesignTime (boolean dtime)
{
throw new Error ("Not implemented");
}
public void setLocale (Locale newLocale)
throws PropertyVetoException
{
throw new Error ("Not implemented");
}
public int size ()
{
throw new Error ("Not implemented");
}
public Object[] toArray ()
{
return children.keySet().toArray();
}
public Object[] toArray(Object[] array)
{
return children.keySet().toArray(array);
}
protected boolean validatePendingAdd (Object targetChild)
{
throw new Error ("Not implemented");
}
protected boolean validatePendingRemove (Object targetChild)
{
throw new Error ("Not implemented");
}
public void vetoableChange (PropertyChangeEvent pce)
throws PropertyVetoException
{
throw new Error ("Not implemented");
}
public final void writeChildren (ObjectOutputStream oos)
throws IOException
{
throw new Error ("Not implemented");
}
}
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in java.beans.beancontext package.
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - java.beans.beancontext</title></head>
<body>
<p>Containers and execution environments for beans.</p>
</body>
</html>
+46
View File
@@ -0,0 +1,46 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in java.beans package.
Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - java.beans</title></head>
<body>
<p>Listeners and descriptors for managing beans.</p>
</body>
</html>