001 /* java.beans.EventSetDescriptor
002 Copyright (C) 1998, 2006 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.beans;
040
041 import gnu.java.lang.ClassHelper;
042
043 import java.lang.reflect.Method;
044 import java.lang.reflect.Modifier;
045 import java.util.Vector;
046
047 /**
048 * EventSetDescriptor describes the hookup between an event source class and
049 * an event listener class.
050 *
051 * <p>EventSets have several attributes: the listener class,
052 * the events that can be fired to the listener (methods in the listener
053 * class), and an add and remove listener method from the event firer's
054 * class.
055 * </p>
056 *
057 * <p>
058 * The methods have these constraints on them:
059 * <ul>
060 * <li>event firing methods: must have <code>void</code> return value. Any
061 * parameters and exceptions are allowed. May be public, protected or
062 * package-protected. (Don't ask me why that is, I'm just following the spec.
063 * The only place it is even mentioned is in the Java Beans white paper, and
064 * there it is only implied.)</li>
065 *
066 * <li>add listener method: must have <code>void</code> return value. Must
067 * take exactly one argument, of the listener class's type. May fire either
068 * zero exceptions, or one exception of type
069 * <code>java.util.TooManyListenersException</code>.
070 * Must be public.</li>
071 *
072 * <li>remove listener method: must have <code>void</code> return value. Must
073 * take exactly one argument, of the listener class's type. May not fire any
074 * exceptions. Must be public.</li>
075 * </ul>
076 *
077 * <p>
078 * A final constraint is that event listener classes must extend from
079 * EventListener.
080 * </p>
081 *
082 * <p>
083 * There are also various design patterns associated with some of the methods
084 * of construction. Those are explained in more detail in the appropriate
085 * constructors.
086 * </p>
087 *
088 * <p>
089 * <strong>Documentation Convention:</strong> for proper Internalization of
090 * Beans inside an RAD tool, sometimes there are two names for a property or
091 * method: a programmatic, or locale-independent name, which can be used
092 * anywhere, and a localized, display name, for ease of use. In the
093 * documentation I will specify different String values as either
094 * <em>programmatic</em> or <em>localized</em> to make this distinction clear.
095 *
096 * @author John Keiser
097 * @author Robert Schuster (robertschuster@fsfe.org)
098 * @since 1.1
099 */
100
101 public class EventSetDescriptor extends FeatureDescriptor
102 {
103 private Method addListenerMethod;
104
105 private Method removeListenerMethod;
106
107 private Class listenerType;
108
109 private MethodDescriptor[] listenerMethodDescriptors;
110
111 private Method[] listenerMethods;
112
113 private Method getListenerMethod;
114
115 private boolean unicast;
116
117 private boolean inDefaultEventSet = true;
118
119 /**
120 * Creates a new <code>EventSetDescriptor</code<.
121 *
122 * <p>
123 * This version of the constructor enforces the rules imposed on the methods
124 * described at the top of this class, as well as searching for:
125 * </p>
126 *
127 * <ol>
128 * <li>
129 * The event-firing method must be non-private with signature <code>void
130 * <listenerMethodName>(<eventSetName>Event)</code> (where
131 * <code><eventSetName></code> has its first character capitalized
132 * by the constructor and the Event is a descendant of
133 * {@link java.util.EventObject}) in class <code>listenerType</code>
134 * (any exceptions may be thrown). <b>Implementation note:</b> Note that
135 * there could conceivably be multiple methods with this type of signature
136 * (example: <code>java.util.MouseEvent</code> vs.
137 * <code>my.very.own.MouseEvent</code>). In this implementation, all
138 * methods fitting the description will be put into the
139 * <code>EventSetDescriptor</code>, even though the spec says only one
140 * should be chosen (they probably weren't thinking as pathologically as I
141 * was). I don't like arbitrarily choosing things. If your class has only one
142 * such signature, as most do, you'll have no problems.</li>
143 *
144 * <li>The add and remove methods must be public and named <code>void
145 * add<eventSetName>Listener(<listenerType>)</code> and
146 * <code>void remove<eventSetName>Listener(<listenerType>)</code>
147 * in in class <code>eventSourceClass</code>, where
148 * <code><eventSetName></code> will have its first letter capitalized.
149 * Standard exception rules (see class description) apply.</li>
150 * </ol>
151 *
152 * @param eventSourceClass
153 * the class containing the add/remove listener methods.
154 * @param eventSetName
155 * the programmatic name of the event set, generally starting with a
156 * lowercase letter (i.e. fooManChu instead of FooManChu). This will
157 * be used to generate the name of the event object as well as the
158 * names of the add and remove methods.
159 * @param listenerType
160 * the class containing the event firing method.
161 * @param listenerMethodName
162 * the name of the event firing method.
163 * @exception IntrospectionException
164 * if listenerType is not an EventListener, or if methods are not
165 * found or are invalid.
166 */
167 public EventSetDescriptor(Class<?> eventSourceClass, String eventSetName,
168 Class<?> listenerType, String listenerMethodName)
169 throws IntrospectionException
170 {
171 setName(eventSetName);
172 if (!java.util.EventListener.class.isAssignableFrom(listenerType))
173 {
174 throw new IntrospectionException(
175 "Listener type is not an EventListener.");
176 }
177
178 String[] names = new String[1];
179 names[0] = listenerMethodName;
180
181 try
182 {
183 eventSetName = Character.toUpperCase(eventSetName.charAt(0))
184 + eventSetName.substring(1);
185 }
186 catch (StringIndexOutOfBoundsException e)
187 {
188 eventSetName = "";
189 }
190
191 findMethods(eventSourceClass, listenerType, names,
192 "add" + eventSetName + "Listener",
193 "remove" + eventSetName + "Listener", eventSetName + "Event");
194 this.listenerType = listenerType;
195 checkAddListenerUnicast();
196 if (this.removeListenerMethod.getExceptionTypes().length > 0)
197 {
198 throw new IntrospectionException(
199 "Listener remove method throws exceptions.");
200 }
201 }
202
203 /**
204 * Creates a new <code>EventSetDescriptor</code>.
205 *
206 * <p>This form of the constructor allows you to specify the names of the
207 * methods and adds no new constraints on top of the rules already described
208 * at the top of the class.
209 * </p>
210 *
211 * @param eventSourceClass
212 * the class containing the add and remove listener methods.
213 * @param eventSetName
214 * the programmatic name of the event set, generally starting with a
215 * lowercase letter (i.e. fooManChu instead of FooManChu).
216 * @param listenerType
217 * the class containing the event firing methods.
218 * @param listenerMethodNames
219 * the names of the even firing methods.
220 * @param addListenerMethodName
221 * the name of the add listener method.
222 * @param removeListenerMethodName
223 * the name of the remove listener method.
224 * @exception IntrospectionException
225 * if listenerType is not an EventListener or if methods are not
226 * found or are invalid.
227 */
228 public EventSetDescriptor(Class<?> eventSourceClass, String eventSetName,
229 Class<?> listenerType, String[] listenerMethodNames,
230 String addListenerMethodName,
231 String removeListenerMethodName)
232 throws IntrospectionException
233 {
234 setName(eventSetName);
235 if (!java.util.EventListener.class.isAssignableFrom(listenerType))
236 {
237 throw new IntrospectionException(
238 "Listener type is not an EventListener.");
239 }
240
241 findMethods(eventSourceClass, listenerType, listenerMethodNames,
242 addListenerMethodName, removeListenerMethodName, null);
243 this.listenerType = listenerType;
244 checkAddListenerUnicast();
245 if (this.removeListenerMethod.getExceptionTypes().length > 0)
246 {
247 throw new IntrospectionException(
248 "Listener remove method throws exceptions.");
249 }
250 }
251
252 /**
253 * Creates a new <code>EventSetDescriptor</code>.
254 *
255 * <p>
256 * This variant of the constructor allows you to specify the names of the
257 * methods and adds no new constraints on top of the rules already described
258 * at the top of the class.
259 * </p>
260 * <p>
261 * A valid GetListener method is public, flags no exceptions and has one
262 * argument which is of type <code>Class</code>
263 * {@link java.awt.Component#getListeners(Class)} is such a method.
264 * </p>
265 * <p>
266 * Note: The validity of the return value of the GetListener method is not
267 * checked.
268 * </p>
269 *
270 * @param eventSourceClass
271 * the class containing the add and remove listener methods.
272 * @param eventSetName
273 * the programmatic name of the event set, generally starting with a
274 * lowercase letter (i.e. fooManChu instead of FooManChu).
275 * @param listenerType
276 * the class containing the event firing methods.
277 * @param listenerMethodNames
278 * the names of the even firing methods.
279 * @param addListenerMethodName
280 * the name of the add listener method.
281 * @param removeListenerMethodName
282 * the name of the remove listener method.
283 * @param getListenerMethodName
284 * Name of a method which returns the array of listeners.
285 * @exception IntrospectionException
286 * if listenerType is not an EventListener or if methods are not
287 * found or are invalid.
288 * @since 1.4
289 */
290 public EventSetDescriptor(Class<?> eventSourceClass, String eventSetName,
291 Class<?> listenerType, String[] listenerMethodNames,
292 String addListenerMethodName,
293 String removeListenerMethodName,
294 String getListenerMethodName)
295 throws IntrospectionException
296 {
297 this(eventSourceClass, eventSetName, listenerType, listenerMethodNames,
298 addListenerMethodName, removeListenerMethodName);
299
300 Method newGetListenerMethod = null;
301
302 try
303 {
304 newGetListenerMethod
305 = eventSourceClass.getMethod(getListenerMethodName,
306 new Class[] { Class.class });
307 }
308 catch (NoSuchMethodException nsme)
309 {
310 throw (IntrospectionException)
311 new IntrospectionException("No method named " + getListenerMethodName
312 + " in class " + listenerType
313 + " which can be used as"
314 + " getListenerMethod.").initCause(nsme);
315 }
316
317 // Note: This does not check the return value (which
318 // should be EventListener[]) but the JDK does not either.
319
320 getListenerMethod = newGetListenerMethod;
321
322 }
323
324 /**
325 * Creates a new <code>EventSetDescriptor.</code>
326 *
327 * <p>
328 * This variant of the constructor allows you to specify the names of the
329 * methods and adds no new constraints on top of the rules already described
330 * at the top of the class.
331 * </p>
332 * <p>
333 * A valid GetListener method is public, flags no exceptions and has one
334 * argument which is of type <code>Class</code>
335 * {@link java.awt.Component#getListeners(Class)} is such a method.
336 * </p>
337 * <p>
338 * Note: The validity of the return value of the GetListener method is not
339 * checked.
340 * </p>
341 *
342 * @param eventSetName
343 * the programmatic name of the event set, generally starting with a
344 * lowercase letter (i.e. fooManChu instead of FooManChu).
345 * @param listenerType
346 * the class containing the listenerMethods.
347 * @param listenerMethods
348 * the event firing methods.
349 * @param addListenerMethod
350 * the add listener method.
351 * @param removeListenerMethod
352 * the remove listener method.
353 * @param getListenerMethod
354 * The method which returns an array of the listeners.
355 * @exception IntrospectionException
356 * if the listenerType is not an EventListener, or any of the
357 * methods are invalid.
358 * @since 1.4
359 */
360 public EventSetDescriptor(String eventSetName, Class<?> listenerType,
361 Method[] listenerMethods, Method addListenerMethod,
362 Method removeListenerMethod,
363 Method getListenerMethod)
364 throws IntrospectionException
365 {
366 this(eventSetName, listenerType, listenerMethods, addListenerMethod,
367 removeListenerMethod);
368
369 // Do no checks if the getListenerMethod is null.
370 if (getListenerMethod.getParameterTypes().length != 1
371 || getListenerMethod.getParameterTypes()[0] != Class.class
372 || getListenerMethod.getExceptionTypes().length > 0
373 || !Modifier.isPublic(getListenerMethod.getModifiers()))
374 throw new IntrospectionException("GetListener method is invalid.");
375
376 // Note: This does not check the return value (which
377 // should be EventListener[]) but the JDK does not either.
378
379 this.getListenerMethod = getListenerMethod;
380 }
381
382 /**
383 * Creates a new <code>EventSetDescriptor</code>.
384 *
385 * <p>This form of constructor allows you to explicitly say which methods
386 * do what, and no reflection is done by the <code>EventSetDescriptor</code>.
387 * The methods are, however, checked to ensure that they follow the rules
388 * set forth at the top of the class.
389 *
390 * @param eventSetName
391 * the programmatic name of the event set, generally starting with a
392 * lowercase letter (i.e. fooManChu instead of FooManChu).
393 * @param listenerType
394 * the class containing the listenerMethods.
395 * @param listenerMethods
396 * the event firing methods.
397 * @param addListenerMethod
398 * the add listener method.
399 * @param removeListenerMethod
400 * the remove listener method.
401 * @exception IntrospectionException
402 * if the listenerType is not an EventListener, or any of the
403 * methods are invalid.
404 */
405 public EventSetDescriptor(String eventSetName, Class<?> listenerType,
406 Method[] listenerMethods, Method addListenerMethod,
407 Method removeListenerMethod)
408 throws IntrospectionException
409 {
410 setName(eventSetName);
411 if (!java.util.EventListener.class.isAssignableFrom(listenerType))
412 {
413 throw new IntrospectionException(
414 "Listener type is not an EventListener.");
415 }
416
417 this.listenerMethods = listenerMethods;
418 this.addListenerMethod = addListenerMethod;
419 this.removeListenerMethod = removeListenerMethod;
420 this.listenerType = listenerType;
421 checkMethods();
422 checkAddListenerUnicast();
423 if (this.removeListenerMethod.getExceptionTypes().length > 0)
424 {
425 throw new IntrospectionException(
426 "Listener remove method throws exceptions.");
427 }
428 }
429
430 /** Creates a new <code>EventSetDescriptor</code>.
431 *
432 * <p>This form of constructor allows you to explicitly say which methods do
433 * what, and no reflection is done by the <code>EventSetDescriptor</code>.
434 * The methods are, however, checked to ensure that they follow the rules
435 * set forth at the top of the class.
436 *
437 * @param eventSetName
438 * the programmatic name of the event set, generally starting with a
439 * lowercase letter (i.e. fooManChu instead of FooManChu).
440 * @param listenerType
441 * the class containing the listenerMethods.
442 * @param listenerMethodDescriptors
443 * the event firing methods.
444 * @param addListenerMethod
445 * the add listener method.
446 * @param removeListenerMethod
447 * the remove listener method.
448 * @exception IntrospectionException
449 * if the listenerType is not an EventListener, or any of the
450 * methods are invalid.
451 */
452 public EventSetDescriptor(String eventSetName, Class<?> listenerType,
453 MethodDescriptor[] listenerMethodDescriptors,
454 Method addListenerMethod,
455 Method removeListenerMethod)
456 throws IntrospectionException
457 {
458 setName(eventSetName);
459 if (!java.util.EventListener.class.isAssignableFrom(listenerType))
460 {
461 throw new IntrospectionException(
462 "Listener type is not an EventListener.");
463 }
464
465 this.listenerMethodDescriptors = listenerMethodDescriptors;
466 this.listenerMethods = new Method[listenerMethodDescriptors.length];
467 for (int i = 0; i < this.listenerMethodDescriptors.length; i++)
468 {
469 this.listenerMethods[i]
470 = this.listenerMethodDescriptors[i].getMethod();
471 }
472
473 this.addListenerMethod = addListenerMethod;
474 this.removeListenerMethod = removeListenerMethod;
475 this.listenerType = listenerType;
476 checkMethods();
477 checkAddListenerUnicast();
478 if (this.removeListenerMethod.getExceptionTypes().length > 0)
479 {
480 throw new IntrospectionException(
481 "Listener remove method throws exceptions.");
482 }
483 }
484
485 /** Returns the class that contains the event firing methods.
486 */
487 public Class<?> getListenerType()
488 {
489 return listenerType;
490 }
491
492 /** Returns the event firing methods.
493 */
494 public Method[] getListenerMethods()
495 {
496 return listenerMethods;
497 }
498
499 /** Returns the event firing methods as {@link MethodDescriptor}.
500 */
501 public MethodDescriptor[] getListenerMethodDescriptors()
502 {
503 if (listenerMethodDescriptors == null)
504 {
505 listenerMethodDescriptors
506 = new MethodDescriptor[listenerMethods.length];
507
508 for (int i = 0; i < listenerMethods.length; i++)
509 {
510 listenerMethodDescriptors[i]
511 = new MethodDescriptor(listenerMethods[i]);
512 }
513 }
514
515 return listenerMethodDescriptors;
516 }
517
518 /** Returns the add listener method.
519 */
520 public Method getAddListenerMethod()
521 {
522 return addListenerMethod;
523 }
524
525 /* Returns the remove listener method.
526 */
527 public Method getRemoveListenerMethod()
528 {
529 return removeListenerMethod;
530 }
531
532 /**
533 * Returns the method that retrieves the listeners or <code>null</code> if
534 * it does not exist.
535 */
536 public Method getGetListenerMethod()
537 {
538 return getListenerMethod;
539 }
540
541 /** Sets whether or not multiple listeners may be added.
542 *
543 * @param unicast
544 * whether or not multiple listeners may be added.
545 */
546 public void setUnicast(boolean unicast)
547 {
548 this.unicast = unicast;
549 }
550
551 /** Returns whether or not multiple listeners may be added.
552 * (Defaults to false.)
553 */
554 public boolean isUnicast()
555 {
556 return unicast;
557 }
558
559 /** Sets whether or not this is in the default event set.
560 *
561 * @param inDefaultEventSet
562 * whether this is in the default event set.
563 */
564 public void setInDefaultEventSet(boolean inDefaultEventSet)
565 {
566 this.inDefaultEventSet = inDefaultEventSet;
567 }
568
569 /** Returns whether or not this is in the default event set.
570 * (Defaults to true.)
571 */
572 public boolean isInDefaultEventSet()
573 {
574 return inDefaultEventSet;
575 }
576
577 private void checkAddListenerUnicast() throws IntrospectionException
578 {
579 Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
580 if (addListenerExceptions.length > 1)
581 {
582 throw new IntrospectionException(
583 "Listener add method throws too many exceptions.");
584 }
585 else if (addListenerExceptions.length == 1
586 && !java.util.TooManyListenersException.class
587 .isAssignableFrom(addListenerExceptions[0]))
588 {
589 throw new IntrospectionException(
590 "Listener add method throws too many exceptions.");
591 }
592 }
593
594 private void checkMethods() throws IntrospectionException
595 {
596 if (!addListenerMethod.getDeclaringClass()
597 .isAssignableFrom(removeListenerMethod.getDeclaringClass())
598 && !removeListenerMethod.getDeclaringClass()
599 .isAssignableFrom(addListenerMethod.getDeclaringClass()))
600 {
601 throw new IntrospectionException(
602 "add and remove listener methods do not come from the"
603 + " same class. This is bad.");
604 }
605 if (!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
606 || addListenerMethod.getParameterTypes().length != 1
607 || !listenerType.equals(addListenerMethod.getParameterTypes()[0])
608 || !Modifier.isPublic(addListenerMethod.getModifiers()))
609 {
610 throw new IntrospectionException("Add Listener Method invalid.");
611 }
612 if (!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
613 || removeListenerMethod.getParameterTypes().length != 1
614 || !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
615 || removeListenerMethod.getExceptionTypes().length > 0
616 || !Modifier.isPublic(removeListenerMethod.getModifiers()))
617 {
618 throw new IntrospectionException("Remove Listener Method invalid.");
619 }
620
621 for (int i = 0; i < listenerMethods.length; i++)
622 {
623 if (!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
624 || Modifier.isPrivate(listenerMethods[i].getModifiers()))
625 {
626 throw new IntrospectionException("Event Method "
627 + listenerMethods[i].getName()
628 + " non-void or private.");
629 }
630 if (!listenerMethods[i].getDeclaringClass()
631 .isAssignableFrom(listenerType))
632 {
633 throw new IntrospectionException("Event Method "
634 + listenerMethods[i].getName()
635 + " not from class "
636 + listenerType.getName());
637 }
638 }
639 }
640
641 private void findMethods(Class eventSourceClass, Class listenerType,
642 String listenerMethodNames[],
643 String addListenerMethodName,
644 String removeListenerMethodName,
645 String absurdEventClassCheckName)
646 throws IntrospectionException
647 {
648
649 /* Find add listener method and remove listener method. */
650 Class[] listenerArgList = new Class[1];
651 listenerArgList[0] = listenerType;
652 try
653 {
654 this.addListenerMethod
655 = eventSourceClass.getMethod(addListenerMethodName,
656 listenerArgList);
657 }
658 catch (SecurityException E)
659 {
660 throw new IntrospectionException(
661 "SecurityException trying to access method "
662 + addListenerMethodName + ".");
663 }
664 catch (NoSuchMethodException E)
665 {
666 throw new IntrospectionException("Could not find method "
667 + addListenerMethodName + ".");
668 }
669
670 if (this.addListenerMethod == null
671 || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE))
672 {
673 throw new IntrospectionException(
674 "Add listener method does not exist, is not public,"
675 + " or is not void.");
676 }
677
678 try
679 {
680 this.removeListenerMethod
681 = eventSourceClass.getMethod(removeListenerMethodName,
682 listenerArgList);
683 }
684 catch (SecurityException E)
685 {
686 throw new IntrospectionException(
687 "SecurityException trying to access method "
688 + removeListenerMethodName + ".");
689 }
690 catch (NoSuchMethodException E)
691 {
692 throw new IntrospectionException("Could not find method "
693 + removeListenerMethodName + ".");
694 }
695 if (this.removeListenerMethod == null
696 || !this.removeListenerMethod.getReturnType()
697 .equals(java.lang.Void.TYPE))
698 {
699 throw new IntrospectionException(
700 "Remove listener method does not exist, is not public,"
701 + " or is not void.");
702 }
703
704 /* Find the listener methods. */
705 Method[] methods;
706 try
707 {
708 methods = ClassHelper.getAllMethods(listenerType);
709 }
710 catch (SecurityException E)
711 {
712 throw new IntrospectionException(
713 "Security: You cannot access fields in this class.");
714 }
715
716 Vector chosenMethods = new Vector();
717 boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
718 for (int i = 0; i < methods.length; i++)
719 {
720 if (Modifier.isPrivate(methods[i].getModifiers()))
721 {
722 continue;
723 }
724 Method currentMethod = methods[i];
725 Class retval = currentMethod.getReturnType();
726 if (retval.equals(java.lang.Void.TYPE))
727 {
728 for (int j = 0; j < listenerMethodNames.length; j++)
729 {
730 if (currentMethod.getName().equals(listenerMethodNames[j])
731 && (absurdEventClassCheckName == null
732 || (currentMethod.getParameterTypes().length == 1
733 && ((currentMethod.getParameterTypes()[0])
734 .getName().equals(absurdEventClassCheckName)
735 || (currentMethod.getParameterTypes()[0])
736 .getName().endsWith("." + absurdEventClassCheckName)))))
737 {
738 chosenMethods.addElement(currentMethod);
739 listenerMethodFound[j] = true;
740 }
741 }
742 }
743 }
744
745 /* Make sure we found all the methods we were looking for. */
746 for (int i = 0; i < listenerMethodFound.length; i++)
747 {
748 if (!listenerMethodFound[i])
749 {
750 throw new IntrospectionException("Could not find event method "
751 + listenerMethodNames[i]);
752 }
753 }
754
755 /* Now that we've chosen the listener methods we want, store them. */
756 this.listenerMethods = new Method[chosenMethods.size()];
757 for (int i = 0; i < chosenMethods.size(); i++)
758 {
759 this.listenerMethods[i] = (Method) chosenMethods.elementAt(i);
760 }
761 }
762
763 }