mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			764 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			764 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Java
		
	
	
	
/* java.beans.EventSetDescriptor
 | 
						|
 Copyright (C) 1998, 2006 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.
 | 
						|
 *
 | 
						|
 * <p>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>
 | 
						|
 *
 | 
						|
 * <p>
 | 
						|
 * The methods have these constraints on them:
 | 
						|
 * <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>
 | 
						|
 *
 | 
						|
 * <p>
 | 
						|
 * A final constraint is that event listener classes must extend from
 | 
						|
 * EventListener.
 | 
						|
 * </p>
 | 
						|
 *
 | 
						|
 * <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>
 | 
						|
 *
 | 
						|
 * <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
 | 
						|
 * @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 <code>EventSetDescriptor</code<.
 | 
						|
   *
 | 
						|
   * <p>
 | 
						|
   * 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
 | 
						|
   * {@link java.util.EventObject}) 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: <code>java.util.MouseEvent</code> vs.
 | 
						|
   * <code>my.very.own.MouseEvent</code>). 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.");
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>EventSetDescriptor</code>.
 | 
						|
   *
 | 
						|
   * <p>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.");
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>EventSetDescriptor</code>.
 | 
						|
   *
 | 
						|
   * <p>
 | 
						|
   * 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.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * A valid GetListener method is public, flags no exceptions and has one
 | 
						|
   * argument which is of type <code>Class</code>
 | 
						|
   * {@link java.awt.Component#getListeners(Class)} is such a method.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * Note: The validity of the return value of the GetListener method is not
 | 
						|
   * checked.
 | 
						|
   * </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.
 | 
						|
   * @param getListenerMethodName
 | 
						|
   *          Name of a method which returns the array of listeners.
 | 
						|
   * @exception IntrospectionException
 | 
						|
   *              if listenerType is not an EventListener or if methods are not
 | 
						|
   *              found or are invalid.
 | 
						|
   * @since 1.4
 | 
						|
   */
 | 
						|
  public EventSetDescriptor(Class<?> eventSourceClass, String eventSetName,
 | 
						|
                            Class<?> listenerType, String[] listenerMethodNames,
 | 
						|
                            String addListenerMethodName,
 | 
						|
                            String removeListenerMethodName,
 | 
						|
                            String getListenerMethodName)
 | 
						|
      throws IntrospectionException
 | 
						|
  {
 | 
						|
    this(eventSourceClass, eventSetName, listenerType, listenerMethodNames,
 | 
						|
         addListenerMethodName, removeListenerMethodName);
 | 
						|
 | 
						|
    Method newGetListenerMethod = null;
 | 
						|
 | 
						|
    try
 | 
						|
      {
 | 
						|
        newGetListenerMethod
 | 
						|
          = eventSourceClass.getMethod(getListenerMethodName,
 | 
						|
                                       new Class[] { Class.class });
 | 
						|
      }
 | 
						|
    catch (NoSuchMethodException nsme)
 | 
						|
      {
 | 
						|
        throw (IntrospectionException)
 | 
						|
          new IntrospectionException("No method named " + getListenerMethodName
 | 
						|
                                      + " in class " + listenerType
 | 
						|
                                      + " which can be used as"
 | 
						|
                                      + " getListenerMethod.").initCause(nsme);
 | 
						|
      }
 | 
						|
 | 
						|
    // Note: This does not check the return value (which
 | 
						|
    // should be EventListener[]) but the JDK does not either.
 | 
						|
 | 
						|
    getListenerMethod = newGetListenerMethod;
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>EventSetDescriptor.</code>
 | 
						|
   *
 | 
						|
   * <p>
 | 
						|
   * 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.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * A valid GetListener method is public, flags no exceptions and has one
 | 
						|
   * argument which is of type <code>Class</code>
 | 
						|
   * {@link java.awt.Component#getListeners(Class)} is such a method.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * Note: The validity of the return value of the GetListener method is not
 | 
						|
   * checked.
 | 
						|
   * </p>
 | 
						|
   *
 | 
						|
   * @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.
 | 
						|
   * @param getListenerMethod
 | 
						|
   *          The method which returns an array of the listeners.
 | 
						|
   * @exception IntrospectionException
 | 
						|
   *              if the listenerType is not an EventListener, or any of the
 | 
						|
   *              methods are invalid.
 | 
						|
   * @since 1.4
 | 
						|
   */
 | 
						|
  public EventSetDescriptor(String eventSetName, Class<?> listenerType,
 | 
						|
                            Method[] listenerMethods, Method addListenerMethod,
 | 
						|
                            Method removeListenerMethod,
 | 
						|
                            Method getListenerMethod)
 | 
						|
      throws IntrospectionException
 | 
						|
  {
 | 
						|
    this(eventSetName, listenerType, listenerMethods, addListenerMethod,
 | 
						|
         removeListenerMethod);
 | 
						|
 | 
						|
    // Do no checks if the getListenerMethod is null.
 | 
						|
    if (getListenerMethod.getParameterTypes().length != 1
 | 
						|
        || getListenerMethod.getParameterTypes()[0] != Class.class
 | 
						|
        || getListenerMethod.getExceptionTypes().length > 0
 | 
						|
        || !Modifier.isPublic(getListenerMethod.getModifiers()))
 | 
						|
      throw new IntrospectionException("GetListener method is invalid.");
 | 
						|
 | 
						|
    // Note: This does not check the return value (which
 | 
						|
    // should be EventListener[]) but the JDK does not either.
 | 
						|
 | 
						|
    this.getListenerMethod = getListenerMethod;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new <code>EventSetDescriptor</code>.
 | 
						|
   *
 | 
						|
   * <p>This form of constructor allows you to explicitly say which methods
 | 
						|
   * do what, and no reflection is done by the <code>EventSetDescriptor</code>.
 | 
						|
   * 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 <code>EventSetDescriptor</code>.
 | 
						|
   *
 | 
						|
   * <p>This form of constructor allows you to explicitly say which methods do
 | 
						|
   * what, and no reflection is done by the <code>EventSetDescriptor</code>.
 | 
						|
   * 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 <code>null</code> 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);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
}
 |