From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- .../classpath/java/beans/EventSetDescriptor.java | 763 +++++++++++++++++++++ 1 file changed, 763 insertions(+) create mode 100644 libjava/classpath/java/beans/EventSetDescriptor.java (limited to 'libjava/classpath/java/beans/EventSetDescriptor.java') diff --git a/libjava/classpath/java/beans/EventSetDescriptor.java b/libjava/classpath/java/beans/EventSetDescriptor.java new file mode 100644 index 000000000..3f537c743 --- /dev/null +++ b/libjava/classpath/java/beans/EventSetDescriptor.java @@ -0,0 +1,763 @@ +/* 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. + * + *

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. + *

+ * + *

+ * 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 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: + *

+ * + *
    + *
  1. + * The event-firing method must be non-private with signature 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.
  2. + * + *
  3. The add and remove methods must be public and named 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.
  4. + *
+ * + * @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 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. + *

+ * + * @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 EventSetDescriptor. + * + *

+ * 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 Class + * {@link java.awt.Component#getListeners(Class)} is such a method. + *

+ *

+ * Note: The validity of the return value of the GetListener method is not + * checked. + *

+ * + * @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 EventSetDescriptor. + * + *

+ * 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 Class + * {@link java.awt.Component#getListeners(Class)} is such a method. + *

+ *

+ * Note: The validity of the return value of the GetListener method is not + * checked. + *

+ * + * @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 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."); + } + } + + /** Creates 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."); + } + } + + /** 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); + } + } + +} -- cgit v1.2.3