From 2d8cf20d0d5ca6b1fbdefc22229d4b7cf1497ede Mon Sep 17 00:00:00 2001
From: mark
Date: Tue, 17 Jan 2006 18:09:40 +0000
Subject: Imported GNU Classpath 0.20 * Makefile.am
(AM_CPPFLAGS): Add classpath/include. *
java/nio/charset/spi/CharsetProvider.java: New override file. *
java/security/Security.java: Likewise. * sources.am: Regenerated.
* Makefile.in: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109831 138bc75d-0d04-0410-961f-82ee72b054a4
---
.../java/beans/DefaultPersistenceDelegate.java | 194 ++++
libjava/classpath/java/beans/Encoder.java | 463 ++++++++
.../classpath/java/beans/EventSetDescriptor.java | 1173 +++++++++++++-------
libjava/classpath/java/beans/Expression.java | 81 +-
.../java/beans/IndexedPropertyChangeEvent.java | 81 ++
libjava/classpath/java/beans/Introspector.java | 204 +++-
.../classpath/java/beans/PersistenceDelegate.java | 91 ++
.../java/beans/PropertyChangeSupport.java | 52 +
libjava/classpath/java/beans/Statement.java | 165 +--
libjava/classpath/java/beans/XMLEncoder.java | 265 +++++
10 files changed, 2172 insertions(+), 597 deletions(-)
create mode 100644 libjava/classpath/java/beans/DefaultPersistenceDelegate.java
create mode 100644 libjava/classpath/java/beans/Encoder.java
create mode 100644 libjava/classpath/java/beans/IndexedPropertyChangeEvent.java
create mode 100644 libjava/classpath/java/beans/PersistenceDelegate.java
create mode 100644 libjava/classpath/java/beans/XMLEncoder.java
(limited to 'libjava/classpath/java/beans')
diff --git a/libjava/classpath/java/beans/DefaultPersistenceDelegate.java b/libjava/classpath/java/beans/DefaultPersistenceDelegate.java
new file mode 100644
index 00000000000..9dd1ae564f7
--- /dev/null
+++ b/libjava/classpath/java/beans/DefaultPersistenceDelegate.java
@@ -0,0 +1,194 @@
+/* DefaultPersistenceDelegate.java
+ Copyright (C) 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.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/** The implementation reads the mentioned properties from the Bean
+ * instance and applies it in the given order to a corresponding
+ * constructor.
+ * Note: Throws a
+ * Note: Silently ignores PersistenceDelegates for Array types and primitive
+ * wrapper classes.
+ *
+ * Note: Although this method is not declared
+ * Note: The Note: If
+ * Note: If you call this method not from within an object instantiation and
+ * initialization sequence it will be silently ignored.
+ *
+ * Note: If you call this method not from within an object instantiation and
+ * initialization sequence it will be silently ignored.
+ * Immutable objects always have to be instantiated instead of
+ * modifying an existing instance.
- **
- ** The methods have these constraints on them:
- **
- **
- ** There are also various design patterns associated with some of the methods
- ** of construction. Those are explained in more detail in the appropriate
- ** constructors.
- **
- ** Documentation Convention: 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 programmatic or localized 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:
- **
- **
- ** @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
+ * The methods have these constraints on them:
+ *
+ * A final constraint is that event listener classes must extend from
+ * EventListener.
+ *
+ * There are also various design patterns associated with some of the methods
+ * of construction. Those are explained in more detail in the appropriate
+ * constructors.
+ *
+ * Documentation Convention: 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
+ * programmatic or localized to make this distinction clear.
+ *
+ * @author John Keiser
+ * @author Robert Schuster (robertschuster@fsfe.org)
+ * @since 1.1
+ */
+
+public class EventSetDescriptor extends FeatureDescriptor
+{
+ private Method addListenerMethod;
+
+ private Method removeListenerMethod;
+
+ private Class listenerType;
+
+ private MethodDescriptor[] listenerMethodDescriptors;
+
+ private Method[] listenerMethods;
+
+ private Method getListenerMethod;
+
+ private boolean unicast;
+
+ private boolean inDefaultEventSet = true;
+
+ /**
+ * Creates a new 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.
+ *
+ * This variant 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.
+ *
+ * A valid GetListener method is public, flags no exceptions and has one
+ * argument which is of type
+ * Note: The validity of the return value of the GetListener method is not
+ * checked.
+ *
+ * This variant 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.
+ *
+ * A valid GetListener method is public, flags no exceptions and has one
+ * argument which is of type
+ * Note: The validity of the return value of the GetListener method is not
+ * checked.
+ * This form of constructor allows you to explicitly say which methods
+ * do what, and no reflection is done by the This form of constructor allows you to explicitly say which methods do
+ * what, and no reflection is done by the 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. While this class can generally be used to describe method calls it is
+ * part of the XML serialization API. You have three options: With {@link #USE_ALL_BEANINFO} the result is the same as
+ * {@link #getBeanInfo(Class)}. Calling the method with When the method is called with Note: Any unknown value for DefaultPersistenceDelegate is a {@link PersistenceDelegate}
+ * implementation that can be used to serialize objects which adhere to the
+ * Java Beans naming convention.null a default instance will be used that
+ * prints the thrown exception to System.err.
+ */
+ public void setExceptionListener(ExceptionListener listener)
+ {
+ exceptionListener = (listener != null) ? listener : new ExceptionListener()
+ {
+ public void exceptionThrown(Exception e)
+ {
+ System.err.println("exception thrown: " + e);
+ e.printStackTrace();
+ }
+ };
+ }
+
+ /**
+ * Returns the currently active {@link ExceptionListener} instance.
+ */
+ public ExceptionListener getExceptionListener()
+ {
+ return exceptionListener;
+ }
+
+ public PersistenceDelegate getPersistenceDelegate(Class type)
+ {
+ // This is not specified but the JDK behaves like this.
+ if (type == null)
+ return fakePersistenceDelegate;
+
+ // Treats all array classes in the same way and assigns
+ // them a shared PersistenceDelegate implementation tailored
+ // for array instantation and initialization.
+ if (type.isArray())
+ return (PersistenceDelegate) delegates.get(Object[].class);
+
+ PersistenceDelegate pd = (PersistenceDelegate) delegates.get(type);
+
+ return (pd != null) ? pd : (PersistenceDelegate) defaultPersistenceDelegate;
+ }
+
+ /**
+ * Sets the {@link PersistenceDelegate} instance for the given class.
+ * NullPointerException if the argument is
+ * null.
+ * static changes to
+ * the {@link PersistenceDelegate}s affect all
+ * {@link Encoder} instances. In this implementation the
+ * access is thread safe.
+ * null if the object has not
+ * been processed yet.
+ * String class acts as an endpoint for the
+ * inherently recursive algorithm of the {@link Encoder}. Therefore instances
+ * of String will always be returned by this method. In other
+ * words the assertion:
+ * assert (anyEncoder.get(anyString) == anyString)
+ *
+ *
+ * null is requested, the result will
+ * always be null.
- **
- **
- ** A final constraint is that event listener classes must extend from EventListener.void 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.)void return value. Must
- ** take exactly one argument, of the listener class's type. May fire either
- ** zero exceptions, or one exception of type java.util.TooManyListenersException.
- ** Must be public.void return value.
- ** Must take exactly one argument, of the listener class's type. May not
- ** fire any exceptions. Must be public.
- **
- ** @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.void <listenerMethodName>(<eventSetName>Event)
- ** (where <eventSetName> has its first character capitalized
- ** by the constructor and the Event is a descendant of
- ** java.util.EventObject) in class listenerType
- ** (any exceptions may be thrown).
- ** Implementation note: 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 EventSetDescriptor, 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.void add<eventSetName>Listener(<listenerType>) and
- ** void remove<eventSetName>Listener(<listenerType>) in
- ** in class eventSourceClass, where
- ** <eventSetName> will have its first letter capitalized.
- ** Standard exception rules (see class description) apply.
+ *
+ *
+ * void 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.)void return value. Must
+ * take exactly one argument, of the listener class's type. May fire either
+ * zero exceptions, or one exception of type
+ * java.util.TooManyListenersException.
+ * Must be public.void return value. Must
+ * take exactly one argument, of the listener class's type. May not fire any
+ * exceptions. Must be public.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:
+ *
+ *
+ *
+ * @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.");
+ }
+ }
+
+ /**
+ * Creates a new void
+ * <listenerMethodName>(<eventSetName>Event) (where
+ * <eventSetName> has its first character capitalized
+ * by the constructor and the Event is a descendant of
+ * {@link java.util.EventObject}) in class listenerType
+ * (any exceptions may be thrown). Implementation note: 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
+ * EventSetDescriptor, 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.void
+ * add<eventSetName>Listener(<listenerType>) and
+ * void remove<eventSetName>Listener(<listenerType>)
+ * in in class eventSourceClass, where
+ * <eventSetName> will have its first letter capitalized.
+ * Standard exception rules (see class description) apply.EventSetDescriptor.
+ *
+ * EventSetDescriptor.
+ *
+ * Class
+ * {@link java.awt.Component#getListeners(Class)} is such a method.
+ * EventSetDescriptor.
+ *
+ * Class
+ * {@link java.awt.Component#getListeners(Class)} is such a method.
+ * EventSetDescriptor.
+ *
+ * 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.");
+ }
+ }
+
+ /** Creates a new EventSetDescriptor.
+ *
+ * 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.");
+ }
+ }
+
+ /** Returns the class that contains the event firing methods.
+ */
+ public Class getListenerType()
+ {
+ return listenerType;
+ }
+
+ /** Returns the event firing methods.
+ */
+ public Method[] getListenerMethods()
+ {
+ return listenerMethods;
+ }
+
+ /** Returns the event firing methods as {@link MethodDescriptor}.
+ */
+ 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;
+ }
+
+ /** Returns the add listener method.
+ */
+ public Method getAddListenerMethod()
+ {
+ return addListenerMethod;
+ }
+
+ /* Returns the remove listener method.
+ */
+ public Method getRemoveListenerMethod()
+ {
+ return removeListenerMethod;
+ }
+
+ /**
+ * Returns the method that retrieves the listeners or null if
+ * it does not exist.
+ */
+ public Method getGetListenerMethod()
+ {
+ return getListenerMethod;
+ }
+
+ /** Sets 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;
+ }
+
+ /** Returns whether or not multiple listeners may be added.
+ * (Defaults to false.)
+ */
+ public boolean isUnicast()
+ {
+ return unicast;
+ }
+
+ /** Sets 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;
+ }
+
+ /** Returns whether or not this is in the default event set.
+ * (Defaults to true.)
+ */
+ public boolean isInDefaultEventSet()
+ {
+ return inDefaultEventSet;
+ }
+
+ private void checkAddListenerUnicast() throws IntrospectionException
+ {
+ Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
+ if (addListenerExceptions.length > 1)
+ {
+ throw new IntrospectionException(
+ "Listener add method throws too many exceptions.");
+ }
+ else if (addListenerExceptions.length == 1
+ && !java.util.TooManyListenersException.class
+ .isAssignableFrom(addListenerExceptions[0]))
+ {
+ throw new IntrospectionException(
+ "Listener add method throws too many exceptions.");
+ }
+ }
+
+ private void checkMethods() throws IntrospectionException
+ {
+ if (!addListenerMethod.getDeclaringClass()
+ .isAssignableFrom(removeListenerMethod.getDeclaringClass())
+ && !removeListenerMethod.getDeclaringClass()
+ .isAssignableFrom(addListenerMethod.getDeclaringClass()))
+ {
+ throw new IntrospectionException(
+ "add and remove listener methods do not come from the"
+ + " same class. This is bad.");
+ }
+ if (!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
+ || addListenerMethod.getParameterTypes().length != 1
+ || !listenerType.equals(addListenerMethod.getParameterTypes()[0])
+ || !Modifier.isPublic(addListenerMethod.getModifiers()))
+ {
+ throw new IntrospectionException("Add Listener Method invalid.");
+ }
+ if (!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
+ || removeListenerMethod.getParameterTypes().length != 1
+ || !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
+ || removeListenerMethod.getExceptionTypes().length > 0
+ || !Modifier.isPublic(removeListenerMethod.getModifiers()))
+ {
+ throw new IntrospectionException("Remove Listener Method invalid.");
+ }
+
+ for (int i = 0; i < listenerMethods.length; i++)
+ {
+ if (!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
+ || Modifier.isPrivate(listenerMethods[i].getModifiers()))
+ {
+ throw new IntrospectionException("Event Method "
+ + listenerMethods[i].getName()
+ + " non-void or private.");
+ }
+ if (!listenerMethods[i].getDeclaringClass()
+ .isAssignableFrom(listenerType))
+ {
+ throw new IntrospectionException("Event Method "
+ + listenerMethods[i].getName()
+ + " not from class "
+ + listenerType.getName());
+ }
+ }
+ }
+
+ private void findMethods(Class eventSourceClass, Class listenerType,
+ String listenerMethodNames[],
+ String addListenerMethodName,
+ String removeListenerMethodName,
+ String absurdEventClassCheckName)
+ throws IntrospectionException
+ {
+
+ /* Find add listener method and remove listener method. */
+ Class[] listenerArgList = new Class[1];
+ listenerArgList[0] = listenerType;
+ try
+ {
+ this.addListenerMethod
+ = eventSourceClass.getMethod(addListenerMethodName,
+ listenerArgList);
+ }
+ catch (SecurityException E)
+ {
+ throw new IntrospectionException(
+ "SecurityException trying to access method "
+ + addListenerMethodName + ".");
+ }
+ catch (NoSuchMethodException E)
+ {
+ throw new IntrospectionException("Could not find method "
+ + addListenerMethodName + ".");
+ }
+
+ if (this.addListenerMethod == null
+ || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE))
+ {
+ throw new IntrospectionException(
+ "Add listener method does not exist, is not public,"
+ + " or is not void.");
+ }
+
+ try
+ {
+ this.removeListenerMethod
+ = eventSourceClass.getMethod(removeListenerMethodName,
+ listenerArgList);
+ }
+ catch (SecurityException E)
+ {
+ throw new IntrospectionException(
+ "SecurityException trying to access method "
+ + removeListenerMethodName + ".");
+ }
+ catch (NoSuchMethodException E)
+ {
+ throw new IntrospectionException("Could not find method "
+ + removeListenerMethodName + ".");
+ }
+ if (this.removeListenerMethod == null
+ || !this.removeListenerMethod.getReturnType()
+ .equals(java.lang.Void.TYPE))
+ {
+ throw new IntrospectionException(
+ "Remove listener method does not exist, is not public,"
+ + " or is not void.");
+ }
+
+ /* Find the listener methods. */
+ Method[] methods;
+ try
+ {
+ methods = ClassHelper.getAllMethods(listenerType);
+ }
+ catch (SecurityException E)
+ {
+ throw new IntrospectionException(
+ "Security: You cannot access fields in this class.");
+ }
+
+ Vector chosenMethods = new Vector();
+ boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
+ for (int i = 0; i < methods.length; i++)
+ {
+ if (Modifier.isPrivate(methods[i].getModifiers()))
+ {
+ continue;
+ }
+ Method currentMethod = methods[i];
+ Class retval = currentMethod.getReturnType();
+ if (retval.equals(java.lang.Void.TYPE))
+ {
+ for (int j = 0; j < listenerMethodNames.length; j++)
+ {
+ if (currentMethod.getName().equals(listenerMethodNames[j])
+ && (absurdEventClassCheckName == null
+ || (currentMethod.getParameterTypes().length == 1
+ && ((currentMethod.getParameterTypes()[0])
+ .getName().equals(absurdEventClassCheckName)
+ || (currentMethod.getParameterTypes()[0])
+ .getName().endsWith("." + absurdEventClassCheckName)))))
+ {
+ chosenMethods.addElement(currentMethod);
+ listenerMethodFound[j] = true;
+ }
+ }
+ }
+ }
+
+ /* Make sure we found all the methods we were looking for. */
+ for (int i = 0; i < listenerMethodFound.length; i++)
+ {
+ if (!listenerMethodFound[i])
+ {
+ throw new IntrospectionException("Could not find event method "
+ + listenerMethodNames[i]);
+ }
+ }
+
+ /* Now that we've chosen the listener methods we want, store them. */
+ this.listenerMethods = new Method[chosenMethods.size()];
+ for (int i = 0; i < chosenMethods.size(); i++)
+ {
+ this.listenerMethods[i] = (Method) chosenMethods.elementAt(i);
+ }
+ }
+
}
diff --git a/libjava/classpath/java/beans/Expression.java b/libjava/classpath/java/beans/Expression.java
index d92cb7284aa..b327864d95f 100644
--- a/libjava/classpath/java/beans/Expression.java
+++ b/libjava/classpath/java/beans/Expression.java
@@ -35,16 +35,19 @@ 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.
- *
+ * flag set to
+ * {@link #IGNORE_IMMEDIATE_BEANINFO} will let it use all
+ * explicit BeanInfo classes for the beans superclasses
+ * but not for the bean class itself. Furthermore eventset,
+ * property and method information is retrieved by introspection
+ * if the explicit BeanInfos did not provide such data
+ * (ie. return null on {@link BeanInfo.getMethodDescriptors},
+ * {@link BeanInfo.getEventSetDescriptors} and
+ * {@link BeanInfo.getPropertyDescriptors}.)
+ * flag
+ *
+ * flag is interpreted
+ * as {@link #IGNORE_ALL_BEANINFO}BeanInfo classes.
+ * @return A BeanInfo object describing the class.
+ * @throws IntrospectionException If something goes wrong while retrieving
+ * the bean data.
+ */
+ public static BeanInfo getBeanInfo(Class beanClass, int flag)
+ throws IntrospectionException
+ {
+ IntrospectionIncubator ii;
+ BeanInfoEmbryo infoEmbryo;
+
+ switch(flag)
+ {
+ case USE_ALL_BEANINFO:
+ return getBeanInfo(beanClass);
+ case IGNORE_IMMEDIATE_BEANINFO:
+ Class superclass = beanClass.getSuperclass();
+ ExplicitInfo explicit = new ExplicitInfo(superclass, null);
+
+ ii = new IntrospectionIncubator();
+ if (explicit.explicitEventSetDescriptors != null)
+ ii.setEventStopClass(superclass);
+
+ if (explicit.explicitMethodDescriptors != null)
+ ii.setMethodStopClass(superclass);
+
+ if (explicit.explicitPropertyDescriptors != null)
+ ii.setPropertyStopClass(superclass);
+
+ ii.addMethods(beanClass.getMethods());
+
+ infoEmbryo = ii.getBeanInfoEmbryo();
+ merge(infoEmbryo, explicit);
+
+ infoEmbryo.setBeanDescriptor(new BeanDescriptor(beanClass, null));
+
+ return infoEmbryo.getBeanInfo();
+ case IGNORE_ALL_BEANINFO:
+ default:
+ ii = new IntrospectionIncubator();
+ ii.addMethods(beanClass.getMethods());
+ infoEmbryo = ii.getBeanInfoEmbryo();
+ infoEmbryo.setBeanDescriptor(new BeanDescriptor(beanClass, null));
+
+ return infoEmbryo.getBeanInfo();
+ }
+ }
/**
* Flush all of the Introspector's internal caches.
@@ -244,6 +320,69 @@ public class Introspector {
}
}
+ /** Adds all explicity given bean info data to the introspected
+ * data.
+ *
+ * @param infoEmbryo Bean info data retrieved by introspection.
+ * @param explicit Bean info data retrieved by BeanInfo classes.
+ */
+ private static void merge(BeanInfoEmbryo infoEmbryo, ExplicitInfo explicit)
+ {
+ PropertyDescriptor[] p = explicit.explicitPropertyDescriptors;
+ if(p!=null)
+ {
+ for(int i=0;iPersistenceDelegate describes how a another object
+ * has to constructed and transformed in order to create a complete
+ * replicate.
For custom classes you will need to implement
+ * PersistenceDelegate in a way that is suitable for them.
+ * To make use of the implementation you have to register it with an
+ * {@link Encoder} using the {Encoder#setPersistenceDelegate} method.
true if there are listeners on all
diff --git a/libjava/classpath/java/beans/Statement.java b/libjava/classpath/java/beans/Statement.java
index 8e916a286be..62a5ad7b6f8 100644
--- a/libjava/classpath/java/beans/Statement.java
+++ b/libjava/classpath/java/beans/Statement.java
@@ -1,4 +1,4 @@
-/* java.beans.Statement
+/* Statement.java
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,32 +42,26 @@ import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.WeakHashMap;
-
/**
- * class Statement
- *
- * A Statement captures the execution of an object method. It stores
+ * 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. + * provided arguments.
* + * @author Jerry Quinn (jlquinn@optonline.net) + * @author Robert Schuster (robertschuster@fsfe.org) * @since 1.4 */ public class Statement { - /** Nested map for the relation between a class, its instances and their - * names. - */ - private static HashMap classMaps = new HashMap(); - 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. + /** + * 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; @@ -87,76 +81,44 @@ public class Statement this.target = target; this.methodName = methodName; this.arguments = (arguments != null) ? arguments : new Object[0]; - storeTargetName(target); - } - - /** Creates a name for the target instance or does nothing if the object's - * name is already known. This makes sure that there *is* a name for every - * target instance. - */ - private static synchronized void storeTargetName(Object obj) - { - Class klass = obj.getClass(); - WeakHashMap names = (WeakHashMap) classMaps.get(klass); - - if ( names == null ) - { - names = new WeakHashMap(); - - names.put(obj, - ( klass == String.class ? ("\"" + obj + "\"") : - (klass.getName() + names.size()) )); - - classMaps.put(klass, names); - - return; - } - - String targetName = (String) names.get(obj); - if ( targetName == null ) - { - names.put(obj, - ( klass == String.class ? ("\"" + obj + "\"") : - (klass.getName() + names.size()) )); - } - - // Nothing to do. The given object was already stored. } /** * Execute the statement. * - * Finds the specified method in the target object and calls it with - * the arguments given in the constructor. + *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. + *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 + *Execute performs some special handling for methods and * parameters: + *
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. + * declared in the source file.
* * @throws Exception if an exception occurs while locating or * invoking the method. @@ -178,8 +140,10 @@ public class Statement 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. + /** Given a wrapper class, return the native class for it. + *For example, if c is Integer,
+ * Integer.TYPE is returned.
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 + // Argument types are derived from argument values. If one of them was + // null then we cannot deduce its type. However null can be assigned to + // any type. + if (args[i] == null) + continue; + + // Treat Integer like int if appropriate Class nativeType = unwrap(args[i]); if (nativeType != null && params[i].isPrimitive() && params[i].isAssignableFrom(nativeType)) @@ -208,14 +181,15 @@ public class Statement } /** - * 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. + * Returnstrue if the method arguments in first are
+ * more specific than the method arguments in second, i.e. all
+ * arguments in first can be assigned to those in
+ * second.
*
- * A method is more specific if all parameters can also be fed to
+ * 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. + * specific one.
* * @param first aClass[] value
* @param second a Class[] value
@@ -238,8 +212,11 @@ public class Statement
? (Class) target : target.getClass();
Object args[] = (arguments == null) ? new Object[0] : arguments;
Class argTypes[] = new Class[args.length];
+
+ // Retrieve type or use null if the argument is null. The null argument
+ // type is later used in compatible().
for (int i = 0; i < args.length; i++)
- argTypes[i] = args[i].getClass();
+ argTypes[i] = (args[i] != null) ? args[i].getClass() : null;
if (target.getClass().isArray())
{
@@ -333,7 +310,29 @@ public class Statement
}
if (method == null)
throw new NoSuchMethodException("No matching method for statement " + toString());
+
+ // If we were calling Class.forName(String) we intercept and call the
+ // forName-variant that allows a ClassLoader argument. We take the
+ // system classloader (aka application classloader) here to make sure
+ // that application defined classes can be resolved. If we would not
+ // do that the Class.forName implementation would use the class loader
+ // of java.beans.Statement which is