Initial revision
From-SVN: r102074
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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><Bean Class Name>BeanInfo</CODE> and place it in
|
||||
** the same package as the Bean, or in the bean info search path
|
||||
** (see Introspector for information on search paths).<P>
|
||||
**
|
||||
** A simple note about the way the Introspector interacts with
|
||||
** BeanInfo. Introspectors look at a Bean class and determine
|
||||
** if there is a BeanInfo class with it. If there is not a
|
||||
** BeanInfo class, it will behave as if the BeanInfo class
|
||||
** provided was a SimpleBeanInfo class (i.e. it will determine
|
||||
** all information automatically).<P>If there is a BeanInfo
|
||||
** class, then any methods that do *not* return null are
|
||||
** regarded as providing definitive information about the class
|
||||
** and all of its superclasses for those information types.
|
||||
** Even if a parent BeanInfo class explicitly returns that
|
||||
** information, it will not be used.
|
||||
**
|
||||
** @author John Keiser
|
||||
** @since JDK1.1
|
||||
** @version 1.1.0, 28 Jul 1998
|
||||
**/
|
||||
|
||||
public interface BeanInfo {
|
||||
/** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
|
||||
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);
|
||||
}
|
||||
@@ -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 <listenerMethodName>(<eventSetName>Event)</CODE>
|
||||
** (where <CODE><eventSetName></CODE> has its first character capitalized
|
||||
** by the constructor and the Event is a descendant of
|
||||
** <CODE>java.util.EventObject</CODE>) in class <CODE>listenerType</CODE>
|
||||
** (any exceptions may be thrown).
|
||||
** <B>Implementation note:</B> Note that there could conceivably be multiple
|
||||
** methods with this type of signature (example: java.util.MouseEvent vs.
|
||||
** my.very.own.MouseEvent). In this implementation, all methods fitting the
|
||||
** description will be put into the <CODE>EventSetDescriptor</CODE>, even
|
||||
** though the spec says only one should be chosen (they probably weren't thinking as
|
||||
** pathologically as I was). I don't like arbitrarily choosing things.
|
||||
** If your class has only one such signature, as most do, you'll have no problems.</LI>
|
||||
** <LI>The add and remove methods must be public and named
|
||||
** <CODE>void add<eventSetName>Listener(<listenerType>)</CODE> and
|
||||
** <CODE>void remove<eventSetName>Listener(<listenerType>)</CODE> in
|
||||
** in class <CODE>eventSourceClass</CODE>, where
|
||||
** <CODE><eventSetName></CODE> will have its first letter capitalized.
|
||||
** Standard exception rules (see class description) apply.</LI>
|
||||
** </OL>
|
||||
** @param eventSourceClass the class containing the add/remove listener methods.
|
||||
** @param eventSetName the programmatic name of the event set, generally starting
|
||||
** with a lowercase letter (i.e. fooManChu instead of FooManChu). This will be used
|
||||
** to generate the name of the event object as well as the names of the add and
|
||||
** remove methods.
|
||||
** @param listenerType the class containing the event firing method.
|
||||
** @param listenerMethodName the name of the event firing method.
|
||||
** @exception IntrospectionException if listenerType is not an EventListener,
|
||||
** or if methods are not found or are invalid.
|
||||
**/
|
||||
public EventSetDescriptor(Class eventSourceClass,
|
||||
String eventSetName,
|
||||
Class listenerType,
|
||||
String listenerMethodName) throws IntrospectionException {
|
||||
setName(eventSetName);
|
||||
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
|
||||
throw new IntrospectionException("Listener type is not an EventListener.");
|
||||
}
|
||||
|
||||
String[] names = new String[1];
|
||||
names[0] = listenerMethodName;
|
||||
|
||||
try {
|
||||
eventSetName = Character.toUpperCase(eventSetName.charAt(0)) + eventSetName.substring(1);
|
||||
} catch(StringIndexOutOfBoundsException e) {
|
||||
eventSetName = "";
|
||||
}
|
||||
|
||||
findMethods(eventSourceClass,listenerType,names,"add"+eventSetName+"Listener","remove"+eventSetName+"Listener",eventSetName+"Event");
|
||||
this.listenerType = listenerType;
|
||||
checkAddListenerUnicast();
|
||||
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
|
||||
throw new IntrospectionException("Listener remove method throws exceptions.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a new EventSetDescriptor.
|
||||
** This form of the constructor allows you to specify the names of the methods and adds
|
||||
** no new constraints on top of the rules already described at the top of the class.<P>
|
||||
**
|
||||
** @param eventSourceClass the class containing the add and remove listener methods.
|
||||
** @param eventSetName the programmatic name of the event set, generally starting
|
||||
** with a lowercase letter (i.e. fooManChu instead of FooManChu).
|
||||
** @param listenerType the class containing the event firing methods.
|
||||
** @param listenerMethodNames the names of the even firing methods.
|
||||
** @param addListenerMethodName the name of the add listener method.
|
||||
** @param removeListenerMethodName the name of the remove listener method.
|
||||
** @exception IntrospectionException if listenerType is not an EventListener
|
||||
** or if methods are not found or are invalid.
|
||||
**/
|
||||
public EventSetDescriptor(Class eventSourceClass,
|
||||
String eventSetName,
|
||||
Class listenerType,
|
||||
String[] listenerMethodNames,
|
||||
String addListenerMethodName,
|
||||
String removeListenerMethodName) throws IntrospectionException {
|
||||
setName(eventSetName);
|
||||
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
|
||||
throw new IntrospectionException("Listener type is not an EventListener.");
|
||||
}
|
||||
|
||||
findMethods(eventSourceClass,listenerType,listenerMethodNames,addListenerMethodName,removeListenerMethodName,null);
|
||||
this.listenerType = listenerType;
|
||||
checkAddListenerUnicast();
|
||||
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
|
||||
throw new IntrospectionException("Listener remove method throws exceptions.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a new EventSetDescriptor.
|
||||
** This form of constructor allows you to explicitly say which methods do what, and
|
||||
** no reflection is done by the EventSetDescriptor. The methods are, however,
|
||||
** checked to ensure that they follow the rules set forth at the top of the class.
|
||||
** @param eventSetName the programmatic name of the event set, generally starting
|
||||
** with a lowercase letter (i.e. fooManChu instead of FooManChu).
|
||||
** @param listenerType the class containing the listenerMethods.
|
||||
** @param listenerMethods the event firing methods.
|
||||
** @param addListenerMethod the add listener method.
|
||||
** @param removeListenerMethod the remove listener method.
|
||||
** @exception IntrospectionException if the listenerType is not an EventListener,
|
||||
** or any of the methods are invalid.
|
||||
**/
|
||||
public EventSetDescriptor(String eventSetName,
|
||||
Class listenerType,
|
||||
Method[] listenerMethods,
|
||||
Method addListenerMethod,
|
||||
Method removeListenerMethod) throws IntrospectionException {
|
||||
setName(eventSetName);
|
||||
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
|
||||
throw new IntrospectionException("Listener type is not an EventListener.");
|
||||
}
|
||||
|
||||
this.listenerMethods = listenerMethods;
|
||||
this.addListenerMethod = addListenerMethod;
|
||||
this.removeListenerMethod = removeListenerMethod;
|
||||
this.listenerType = listenerType;
|
||||
checkMethods();
|
||||
checkAddListenerUnicast();
|
||||
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
|
||||
throw new IntrospectionException("Listener remove method throws exceptions.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Create a new EventSetDescriptor.
|
||||
** This form of constructor allows you to explicitly say which methods do what, and
|
||||
** no reflection is done by the EventSetDescriptor. The methods are, however,
|
||||
** checked to ensure that they follow the rules set forth at the top of the class.
|
||||
** @param eventSetName the programmatic name of the event set, generally starting
|
||||
** with a lowercase letter (i.e. fooManChu instead of FooManChu).
|
||||
** @param listenerType the class containing the listenerMethods.
|
||||
** @param listenerMethodDescriptors the event firing methods.
|
||||
** @param addListenerMethod the add listener method.
|
||||
** @param removeListenerMethod the remove listener method.
|
||||
** @exception IntrospectionException if the listenerType is not an EventListener,
|
||||
** or any of the methods are invalid.
|
||||
**/
|
||||
public EventSetDescriptor(String eventSetName,
|
||||
Class listenerType,
|
||||
MethodDescriptor[] listenerMethodDescriptors,
|
||||
Method addListenerMethod,
|
||||
Method removeListenerMethod) throws IntrospectionException {
|
||||
setName(eventSetName);
|
||||
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
|
||||
throw new IntrospectionException("Listener type is not an EventListener.");
|
||||
}
|
||||
|
||||
this.listenerMethodDescriptors = listenerMethodDescriptors;
|
||||
this.listenerMethods = new Method[listenerMethodDescriptors.length];
|
||||
for(int i=0;i<this.listenerMethodDescriptors.length;i++) {
|
||||
this.listenerMethods[i] = this.listenerMethodDescriptors[i].getMethod();
|
||||
}
|
||||
|
||||
this.addListenerMethod = addListenerMethod;
|
||||
this.removeListenerMethod = removeListenerMethod;
|
||||
this.listenerType = listenerType;
|
||||
checkMethods();
|
||||
checkAddListenerUnicast();
|
||||
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
|
||||
throw new IntrospectionException("Listener remove method throws exceptions.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the class that contains the event firing methods. **/
|
||||
public Class getListenerType() {
|
||||
return listenerType;
|
||||
}
|
||||
|
||||
/** Get the event firing methods. **/
|
||||
public Method[] getListenerMethods() {
|
||||
return listenerMethods;
|
||||
}
|
||||
|
||||
/** Get the event firing methods as MethodDescriptors. **/
|
||||
public MethodDescriptor[] getListenerMethodDescriptors() {
|
||||
if(listenerMethodDescriptors == null) {
|
||||
listenerMethodDescriptors = new MethodDescriptor[listenerMethods.length];
|
||||
for(int i=0;i<listenerMethods.length;i++) {
|
||||
listenerMethodDescriptors[i] = new MethodDescriptor(listenerMethods[i]);
|
||||
}
|
||||
}
|
||||
return listenerMethodDescriptors;
|
||||
}
|
||||
|
||||
/** Get the add listener method. **/
|
||||
public Method getAddListenerMethod() {
|
||||
return addListenerMethod;
|
||||
}
|
||||
|
||||
/** Get the remove listener method. **/
|
||||
public Method getRemoveListenerMethod() {
|
||||
return removeListenerMethod;
|
||||
}
|
||||
|
||||
/** Set whether or not multiple listeners may be added.
|
||||
** @param unicast whether or not multiple listeners may be added.
|
||||
**/
|
||||
public void setUnicast(boolean unicast) {
|
||||
this.unicast = unicast;
|
||||
}
|
||||
|
||||
/** Get whether or not multiple listeners may be added. (Defaults to false.) **/
|
||||
public boolean isUnicast() {
|
||||
return unicast;
|
||||
}
|
||||
|
||||
/** Set whether or not this is in the default event set.
|
||||
** @param inDefaultEventSet whether this is in the default event set.
|
||||
**/
|
||||
public void setInDefaultEventSet(boolean inDefaultEventSet) {
|
||||
this.inDefaultEventSet = inDefaultEventSet;
|
||||
}
|
||||
|
||||
/** Get whether or not this is in the default event set. (Defaults to true.)**/
|
||||
public boolean isInDefaultEventSet() {
|
||||
return inDefaultEventSet;
|
||||
}
|
||||
|
||||
private void checkAddListenerUnicast() throws IntrospectionException {
|
||||
Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
|
||||
if(addListenerExceptions.length > 1) {
|
||||
throw new IntrospectionException("Listener add method throws too many exceptions.");
|
||||
} else if(addListenerExceptions.length == 1
|
||||
&& !java.util.TooManyListenersException.class.isAssignableFrom(addListenerExceptions[0])) {
|
||||
throw new IntrospectionException("Listener add method throws too many exceptions.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkMethods() throws IntrospectionException {
|
||||
if(!addListenerMethod.getDeclaringClass().isAssignableFrom(removeListenerMethod.getDeclaringClass())
|
||||
&& !removeListenerMethod.getDeclaringClass().isAssignableFrom(addListenerMethod.getDeclaringClass())) {
|
||||
throw new IntrospectionException("add and remove listener methods do not come from the same class. This is bad.");
|
||||
}
|
||||
if(!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
|
||||
|| addListenerMethod.getParameterTypes().length != 1
|
||||
|| !listenerType.equals(addListenerMethod.getParameterTypes()[0])
|
||||
|| !Modifier.isPublic(addListenerMethod.getModifiers())) {
|
||||
throw new IntrospectionException("Add Listener Method invalid.");
|
||||
}
|
||||
if(!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
|
||||
|| removeListenerMethod.getParameterTypes().length != 1
|
||||
|| !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
|
||||
|| removeListenerMethod.getExceptionTypes().length > 0
|
||||
|| !Modifier.isPublic(removeListenerMethod.getModifiers())) {
|
||||
throw new IntrospectionException("Remove Listener Method invalid.");
|
||||
}
|
||||
|
||||
for(int i=0;i<listenerMethods.length;i++) {
|
||||
if(!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
|
||||
|| Modifier.isPrivate(listenerMethods[i].getModifiers())) {
|
||||
throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " non-void or private.");
|
||||
}
|
||||
if(!listenerMethods[i].getDeclaringClass().isAssignableFrom(listenerType)) {
|
||||
throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " not from class " + listenerType.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void findMethods(Class eventSourceClass,
|
||||
Class listenerType,
|
||||
String listenerMethodNames[],
|
||||
String addListenerMethodName,
|
||||
String removeListenerMethodName,
|
||||
String absurdEventClassCheckName) throws IntrospectionException {
|
||||
|
||||
/* Find add listener method and remove listener method. */
|
||||
Class[] listenerArgList = new Class[1];
|
||||
listenerArgList[0] = listenerType;
|
||||
try {
|
||||
this.addListenerMethod = eventSourceClass.getMethod(addListenerMethodName,listenerArgList);
|
||||
} catch(SecurityException E) {
|
||||
throw new IntrospectionException("SecurityException trying to access method " + addListenerMethodName + ".");
|
||||
} catch(NoSuchMethodException E) {
|
||||
throw new IntrospectionException("Could not find method " + addListenerMethodName + ".");
|
||||
}
|
||||
|
||||
if(this.addListenerMethod == null || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
|
||||
throw new IntrospectionException("Add listener method does not exist, is not public, or is not void.");
|
||||
}
|
||||
|
||||
try {
|
||||
this.removeListenerMethod = eventSourceClass.getMethod(removeListenerMethodName,listenerArgList);
|
||||
} catch(SecurityException E) {
|
||||
throw new IntrospectionException("SecurityException trying to access method " + removeListenerMethodName + ".");
|
||||
} catch(NoSuchMethodException E) {
|
||||
throw new IntrospectionException("Could not find method " + removeListenerMethodName + ".");
|
||||
}
|
||||
if(this.removeListenerMethod == null || !this.removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
|
||||
throw new IntrospectionException("Remove listener method does not exist, is not public, or is not void.");
|
||||
}
|
||||
|
||||
/* Find the listener methods. */
|
||||
Method[] methods;
|
||||
try {
|
||||
methods = ClassHelper.getAllMethods(listenerType);
|
||||
} catch(SecurityException E) {
|
||||
throw new IntrospectionException("Security: You cannot access fields in this class.");
|
||||
}
|
||||
|
||||
Vector chosenMethods = new Vector();
|
||||
boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
|
||||
for(int i=0;i<methods.length;i++) {
|
||||
if(Modifier.isPrivate(methods[i].getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
Method currentMethod = methods[i];
|
||||
Class retval = currentMethod.getReturnType();
|
||||
if(retval.equals(java.lang.Void.TYPE)) {
|
||||
for(int j=0;j<listenerMethodNames.length;j++) {
|
||||
if(currentMethod.getName().equals(listenerMethodNames[j])
|
||||
&& (absurdEventClassCheckName == null
|
||||
|| (currentMethod.getParameterTypes().length == 1
|
||||
&& ((currentMethod.getParameterTypes()[0]).getName().equals(absurdEventClassCheckName)
|
||||
|| (currentMethod.getParameterTypes()[0]).getName().endsWith("."+absurdEventClassCheckName)
|
||||
)
|
||||
)
|
||||
)
|
||||
) {
|
||||
chosenMethods.addElement(currentMethod);
|
||||
listenerMethodFound[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure we found all the methods we were looking for. */
|
||||
for(int i=0;i<listenerMethodFound.length;i++) {
|
||||
if(!listenerMethodFound[i]) {
|
||||
throw new IntrospectionException("Could not find event method " + listenerMethodNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that we've chosen the listener methods we want, store them. */
|
||||
this.listenerMethods = new Method[chosenMethods.size()];
|
||||
for(int i=0;i<chosenMethods.size();i++) {
|
||||
this.listenerMethods[i] = (Method)chosenMethods.elementAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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><propertyType>[] <getMethodName>()</CODE></LI>
|
||||
** <LI>A set array method must have signature
|
||||
** <CODE>void <setMethodName>(<propertyType>[])</CODE></LI>
|
||||
** <LI>A get index method must have signature
|
||||
** <CODE><propertyType> <getMethodName>(int)</CODE></LI>
|
||||
** <LI>A set index method must have signature
|
||||
** <CODE>void <setMethodName>(int,<propertyType>)</CODE></LI>
|
||||
** <LI>All these methods may throw any exception.</LI>
|
||||
** <LI>All these methods must be public.</LI>
|
||||
** </OL>
|
||||
**
|
||||
** @author John Keiser
|
||||
** @since JDK1.1
|
||||
** @version 1.1.0, 26 Jul 1998
|
||||
**/
|
||||
|
||||
public class IndexedPropertyDescriptor extends PropertyDescriptor {
|
||||
private Class indexedPropertyType;
|
||||
private Method setIndex;
|
||||
private Method getIndex;
|
||||
|
||||
/** Create a new IndexedPropertyDescriptor by introspection.
|
||||
** This form of constructor creates the PropertyDescriptor by
|
||||
** looking for getter methods named <CODE>get<name>()</CODE>
|
||||
** and setter methods named
|
||||
** <CODE>set<name>()</CODE> in class
|
||||
** <CODE><beanClass></CODE>, where <name> has its
|
||||
** first letter capitalized by the constructor.<P>
|
||||
**
|
||||
** <B>Implementation note:</B> If there is a get(int) method,
|
||||
** then the return type of that method is used to find the
|
||||
** remaining methods. If there is no get method, then the
|
||||
** set(int) method is searched for exhaustively and that type
|
||||
** is used to find the others.<P>
|
||||
**
|
||||
** <B>Spec note:</B>
|
||||
** If there is no get(int) method and multiple set(int) methods with
|
||||
** the same name and the correct parameters (different type of course),
|
||||
** then an IntrospectionException is thrown. While Sun's spec
|
||||
** does not state this, it can make Bean behavior different on
|
||||
** different systems (since method order is not guaranteed) and as
|
||||
** such, can be treated as a bug in the spec. I am not aware of
|
||||
** whether Sun's implementation catches this.
|
||||
**
|
||||
** @param name the programmatic name of the property, usually
|
||||
** starting with a lowercase letter (e.g. fooManChu
|
||||
** instead of FooManChu).
|
||||
** @param beanClass the class the get and set methods live in.
|
||||
** @exception IntrospectionException if the methods are not found or invalid.
|
||||
**/
|
||||
public IndexedPropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
|
||||
super(name);
|
||||
String capitalized;
|
||||
try {
|
||||
capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
|
||||
} catch(StringIndexOutOfBoundsException e) {
|
||||
capitalized = "";
|
||||
}
|
||||
findMethods(beanClass, "get" + capitalized, "set" + capitalized, "get" + capitalized, "set" + capitalized);
|
||||
}
|
||||
|
||||
/** Create a new IndexedPropertyDescriptor by introspection.
|
||||
** This form of constructor allows you to specify the
|
||||
** names of the get and set methods to search for.<P>
|
||||
**
|
||||
** <B>Implementation note:</B> If there is a get(int) method,
|
||||
** then the return type of that method is used to find the
|
||||
** remaining methods. If there is no get method, then the
|
||||
** set(int) method is searched for exhaustively and that type
|
||||
** is used to find the others.<P>
|
||||
**
|
||||
** <B>Spec note:</B>
|
||||
** If there is no get(int) method and multiple set(int) methods with
|
||||
** the same name and the correct parameters (different type of course),
|
||||
** then an IntrospectionException is thrown. While Sun's spec
|
||||
** does not state this, it can make Bean behavior different on
|
||||
** different systems (since method order is not guaranteed) and as
|
||||
** such, can be treated as a bug in the spec. I am not aware of
|
||||
** whether Sun's implementation catches this.
|
||||
**
|
||||
** @param name the programmatic name of the property, usually
|
||||
** starting with a lowercase letter (e.g. fooManChu
|
||||
** instead of FooManChu).
|
||||
** @param beanClass the class the get and set methods live in.
|
||||
** @param getMethodName the name of the get array method.
|
||||
** @param setMethodName the name of the set array method.
|
||||
** @param getIndexName the name of the get index method.
|
||||
** @param setIndexName the name of the set index method.
|
||||
** @exception IntrospectionException if the methods are not found or invalid.
|
||||
**/
|
||||
public IndexedPropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName, String getIndexName, String setIndexName) throws IntrospectionException {
|
||||
super(name);
|
||||
findMethods(beanClass, getMethodName, setMethodName, getIndexName, setIndexName);
|
||||
}
|
||||
|
||||
/** Create a new PropertyDescriptor using explicit Methods.
|
||||
** Note that the methods will be checked for conformance to standard
|
||||
** Property method rules, as described above at the top of this class.
|
||||
**
|
||||
** @param name the programmatic name of the property, usually
|
||||
** starting with a lowercase letter (e.g. fooManChu
|
||||
** instead of FooManChu).
|
||||
** @param getMethod the get array method.
|
||||
** @param setMethod the set array method.
|
||||
** @param getIndex the get index method.
|
||||
** @param setIndex the set index method.
|
||||
** @exception IntrospectionException if the methods are not found or invalid.
|
||||
**/
|
||||
public IndexedPropertyDescriptor(String name, Method getMethod, Method setMethod, Method getIndex, Method setIndex) throws IntrospectionException {
|
||||
super(name);
|
||||
if(getMethod != null && getMethod.getParameterTypes().length > 0) {
|
||||
throw new IntrospectionException("get method has parameters");
|
||||
}
|
||||
if(getMethod != null && setMethod.getParameterTypes().length != 1) {
|
||||
throw new IntrospectionException("set method does not have exactly one parameter");
|
||||
}
|
||||
if(getMethod != null && setMethod != null) {
|
||||
if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
|
||||
throw new IntrospectionException("set and get methods do not share the same type");
|
||||
}
|
||||
if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
|
||||
&& !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
|
||||
throw new IntrospectionException("set and get methods are not in the same class.");
|
||||
}
|
||||
}
|
||||
|
||||
if(getIndex != null && (getIndex.getParameterTypes().length != 1
|
||||
|| !(getIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
|
||||
throw new IntrospectionException("get index method has wrong parameters");
|
||||
}
|
||||
if(setIndex != null && (setIndex.getParameterTypes().length != 2
|
||||
|| !(setIndex.getParameterTypes()[0]).equals(java.lang.Integer.TYPE))) {
|
||||
throw new IntrospectionException("set index method has wrong parameters");
|
||||
}
|
||||
if(getIndex != null && setIndex != null) {
|
||||
if(!getIndex.getReturnType().equals(setIndex.getParameterTypes()[1])) {
|
||||
throw new IntrospectionException("set index methods do not share the same type");
|
||||
}
|
||||
if(!getIndex.getDeclaringClass().isAssignableFrom(setIndex.getDeclaringClass())
|
||||
&& !setIndex.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
|
||||
throw new IntrospectionException("get and set index methods are not in the same class.");
|
||||
}
|
||||
}
|
||||
|
||||
if(getIndex != null && getMethod != null && !getIndex.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())
|
||||
&& !getMethod.getDeclaringClass().isAssignableFrom(getIndex.getDeclaringClass())) {
|
||||
throw new IntrospectionException("methods are not in the same class.");
|
||||
}
|
||||
|
||||
if(getIndex != null && getMethod != null && !Array.newInstance(getIndex.getReturnType(),0).getClass().equals(getMethod.getReturnType())) {
|
||||
throw new IntrospectionException("array methods do not match index methods.");
|
||||
}
|
||||
|
||||
this.getMethod = getMethod;
|
||||
this.setMethod = setMethod;
|
||||
this.getIndex = getIndex;
|
||||
this.setIndex = 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 <bean class name>BeanInfo in different
|
||||
* packages, first searching the bean class's package
|
||||
* and then moving on to search the beanInfoSearchPath.<P>
|
||||
*
|
||||
* If it does not find a BeanInfo class, it acts as though
|
||||
* it had found a BeanInfo class returning null from all
|
||||
* methods (meaning it should discover everything through
|
||||
* Introspection). If it does, then it takes the
|
||||
* information it finds in the BeanInfo class to be
|
||||
* canonical (that is, the information speaks for its
|
||||
* class as well as all superclasses).<P>
|
||||
*
|
||||
* When it has introspected the class, calls
|
||||
* getBeanInfo(c.getSuperclass) and adds that information
|
||||
* to the information it has, not adding to any information
|
||||
* it already has that is canonical.<P>
|
||||
*
|
||||
* <STRONG>Introspection Design Patterns</STRONG><P>
|
||||
*
|
||||
* When the Introspector goes in to read the class, it
|
||||
* follows a well-defined order in order to not leave any
|
||||
* methods unaccounted for. Its job is to step over all
|
||||
* of the public methods in a class and determine whether
|
||||
* they are part of a property, an event, or a method (in
|
||||
* that order).
|
||||
*
|
||||
*
|
||||
* <STRONG>Properties:</STRONG><P>
|
||||
*
|
||||
* <OL>
|
||||
* <LI>If there is a <CODE>public boolean isXXX()</CODE>
|
||||
* method, then XXX is a read-only boolean property.
|
||||
* <CODE>boolean getXXX()</CODE> may be supplied in
|
||||
* addition to this method, although isXXX() is the
|
||||
* one that will be used in this case and getXXX()
|
||||
* will be ignored. If there is a
|
||||
* <CODE>public void setXXX(boolean)</CODE> method,
|
||||
* it is part of this group and makes it a read-write
|
||||
* property.</LI>
|
||||
* <LI>If there is a
|
||||
* <CODE>public <type> getXXX(int)</CODE>
|
||||
* method, then XXX is a read-only indexed property of
|
||||
* type <type>. If there is a
|
||||
* <CODE>public void setXXX(int,<type>)</CODE>
|
||||
* method, then it is a read-write indexed property of
|
||||
* type <type>. There may also be a
|
||||
* <CODE>public <type>[] getXXX()</CODE> and a
|
||||
* <CODE>public void setXXX(<type>)</CODE>
|
||||
* method as well.</LI>
|
||||
* <LI>If there is a
|
||||
* <CODE>public void setXXX(int,<type>)</CODE>
|
||||
* method, then it is a write-only indexed property of
|
||||
* type <type>. There may also be a
|
||||
* <CODE>public <type>[] getXXX()</CODE> and a
|
||||
* <CODE>public void setXXX(<type>)</CODE>
|
||||
* method as well.</LI>
|
||||
* <LI>If there is a
|
||||
* <CODE>public <type> getXXX()</CODE> method,
|
||||
* then XXX is a read-only property of type
|
||||
* <type>. If there is a
|
||||
* <CODE>public void setXXX(<type>)</CODE>
|
||||
* method, then it will be used for the property and
|
||||
* the property will be considered read-write.</LI>
|
||||
* <LI>If there is a
|
||||
* <CODE>public void setXXX(<type>)</CODE>
|
||||
* method, then as long as XXX is not already used as
|
||||
* the name of a property, XXX is assumed to be a
|
||||
* write-only property of type <type>.</LI>
|
||||
* <LI>In all of the above cases, if the setXXX() method
|
||||
* throws <CODE>PropertyVetoException</CODE>, then the
|
||||
* property in question is assumed to be constrained.
|
||||
* No properties are ever assumed to be bound
|
||||
* (<STRONG>Spec Note:</STRONG> this is not in the
|
||||
* spec, it just makes sense). See PropertyDescriptor
|
||||
* for a description of bound and constrained
|
||||
* properties.</LI>
|
||||
* </OL>
|
||||
*
|
||||
* <STRONG>Events:</STRONG><P>
|
||||
*
|
||||
* If there is a pair of methods,
|
||||
* <CODE>public void addXXX(<type>)</CODE> and
|
||||
* <CODE>public void removeXXX(<type>)</CODE>, where
|
||||
* <type> is a descendant of
|
||||
* <CODE>java.util.EventListener</CODE>, then the pair of
|
||||
* methods imply that this Bean will fire events to
|
||||
* listeners of type <type>.<P>
|
||||
*
|
||||
* If the addXXX() method throws
|
||||
* <CODE>java.util.TooManyListenersException</CODE>, then
|
||||
* the event set is assumed to be <EM>unicast</EM>. See
|
||||
* EventSetDescriptor for a discussion of unicast event
|
||||
* sets.<P>
|
||||
*
|
||||
* <STRONG>Spec Note:</STRONG> the spec seems to say that
|
||||
* the listener type's classname must be equal to the XXX
|
||||
* part of addXXX() and removeXXX(), but that is not the
|
||||
* case in Sun's implementation, so I am assuming it is
|
||||
* not the case in general.<P>
|
||||
*
|
||||
* <STRONG>Methods:</STRONG><P>
|
||||
*
|
||||
* Any public methods (including those which were used
|
||||
* for Properties or Events) are used as Methods.
|
||||
*
|
||||
* @author John Keiser
|
||||
* @since JDK1.1
|
||||
* @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><propertyType> <getMethodName>()</CODE></LI>
|
||||
** <LI>A set method must have signature
|
||||
** <CODE>void <setMethodName>(<propertyType>)</CODE></LI>
|
||||
** <LI>Either method type may throw any exception.</LI>
|
||||
** <LI>Both methods must be public.</LI>
|
||||
** </OL>
|
||||
**
|
||||
** @author John Keiser
|
||||
** @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<name>()</CODE>
|
||||
** (or, optionally, if the property is boolean,
|
||||
** <CODE>is<name>()</CODE>) and
|
||||
** <CODE>set<name>()</CODE> in class
|
||||
** <CODE><beanClass></CODE>, where <name> has its
|
||||
** first letter capitalized by the constructor.<P>
|
||||
**
|
||||
** 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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
* <java>
|
||||
* <string>Hello World</string>
|
||||
* <int>200</int>
|
||||
* </java>
|
||||
* </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>
|
||||
* <java>
|
||||
* <void method="getOwner">
|
||||
* <void method="setVisible">
|
||||
* <boolean>true<boolean>
|
||||
* </void>
|
||||
* </void>
|
||||
* </java>
|
||||
* </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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user