src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java
changeset 47216 71c04702a3d5
parent 35667 ed476aba94de
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package java.awt;
       
    26 
       
    27 import java.awt.event.*;
       
    28 import java.lang.reflect.Array;
       
    29 import java.util.EventListener;
       
    30 import java.io.Serializable;
       
    31 import java.io.ObjectOutputStream;
       
    32 import java.io.IOException;
       
    33 import java.util.EventListener;
       
    34 
       
    35 
       
    36 /**
       
    37  * {@code AWTEventMulticaster} implements efficient and thread-safe multi-cast
       
    38  * event dispatching for the AWT events defined in the {@code java.awt.event}
       
    39  * package.
       
    40  * <p>
       
    41  * The following example illustrates how to use this class:
       
    42  *
       
    43  * <pre><code>
       
    44  * public myComponent extends Component {
       
    45  *     ActionListener actionListener = null;
       
    46  *
       
    47  *     public synchronized void addActionListener(ActionListener l) {
       
    48  *         actionListener = AWTEventMulticaster.add(actionListener, l);
       
    49  *     }
       
    50  *     public synchronized void removeActionListener(ActionListener l) {
       
    51  *         actionListener = AWTEventMulticaster.remove(actionListener, l);
       
    52  *     }
       
    53  *     public void processEvent(AWTEvent e) {
       
    54  *         // when event occurs which causes "action" semantic
       
    55  *         ActionListener listener = actionListener;
       
    56  *         if (listener != null) {
       
    57  *             listener.actionPerformed(new ActionEvent());
       
    58  *         }
       
    59  *     }
       
    60  * }
       
    61  * </code></pre>
       
    62  * The important point to note is the first argument to the {@code
       
    63  * add} and {@code remove} methods is the field maintaining the
       
    64  * listeners. In addition you must assign the result of the {@code add}
       
    65  * and {@code remove} methods to the field maintaining the listeners.
       
    66  * <p>
       
    67  * {@code AWTEventMulticaster} is implemented as a pair of {@code
       
    68  * EventListeners} that are set at construction time. {@code
       
    69  * AWTEventMulticaster} is immutable. The {@code add} and {@code
       
    70  * remove} methods do not alter {@code AWTEventMulticaster} in
       
    71  * anyway. If necessary, a new {@code AWTEventMulticaster} is
       
    72  * created. In this way it is safe to add and remove listeners during
       
    73  * the process of an event dispatching.  However, event listeners
       
    74  * added during the process of an event dispatch operation are not
       
    75  * notified of the event currently being dispatched.
       
    76  * <p>
       
    77  * All of the {@code add} methods allow {@code null} arguments. If the
       
    78  * first argument is {@code null}, the second argument is returned. If
       
    79  * the first argument is not {@code null} and the second argument is
       
    80  * {@code null}, the first argument is returned. If both arguments are
       
    81  * {@code non-null}, a new {@code AWTEventMulticaster} is created using
       
    82  * the two arguments and returned.
       
    83  * <p>
       
    84  * For the {@code remove} methods that take two arguments, the following is
       
    85  * returned:
       
    86  * <ul>
       
    87  *   <li>{@code null}, if the first argument is {@code null}, or
       
    88  *       the arguments are equal, by way of {@code ==}.
       
    89  *   <li>the first argument, if the first argument is not an instance of
       
    90  *       {@code AWTEventMulticaster}.
       
    91  *   <li>result of invoking {@code remove(EventListener)} on the
       
    92  *       first argument, supplying the second argument to the
       
    93  *       {@code remove(EventListener)} method.
       
    94  * </ul>
       
    95  * <p>Swing makes use of
       
    96  * {@link javax.swing.event.EventListenerList EventListenerList} for
       
    97  * similar logic. Refer to it for details.
       
    98  *
       
    99  * @see javax.swing.event.EventListenerList
       
   100  *
       
   101  * @author      John Rose
       
   102  * @author      Amy Fowler
       
   103  * @since       1.1
       
   104  */
       
   105 
       
   106 public class AWTEventMulticaster implements
       
   107     ComponentListener, ContainerListener, FocusListener, KeyListener,
       
   108     MouseListener, MouseMotionListener, WindowListener, WindowFocusListener,
       
   109     WindowStateListener, ActionListener, ItemListener, AdjustmentListener,
       
   110     TextListener, InputMethodListener, HierarchyListener,
       
   111     HierarchyBoundsListener, MouseWheelListener {
       
   112 
       
   113     /**
       
   114      * A variable in the event chain (listener-a)
       
   115      */
       
   116     protected final EventListener a;
       
   117 
       
   118     /**
       
   119      * A variable in the event chain (listener-b)
       
   120      */
       
   121     protected final EventListener b;
       
   122 
       
   123     /**
       
   124      * Creates an event multicaster instance which chains listener-a
       
   125      * with listener-b. Input parameters {@code a} and {@code b}
       
   126      * should not be {@code null}, though implementations may vary in
       
   127      * choosing whether or not to throw {@code NullPointerException}
       
   128      * in that case.
       
   129      * @param a listener-a
       
   130      * @param b listener-b
       
   131      */
       
   132     protected AWTEventMulticaster(EventListener a, EventListener b) {
       
   133         this.a = a; this.b = b;
       
   134     }
       
   135 
       
   136     /**
       
   137      * Removes a listener from this multicaster.
       
   138      * <p>
       
   139      * The returned multicaster contains all the listeners in this
       
   140      * multicaster with the exception of all occurrences of {@code oldl}.
       
   141      * If the resulting multicaster contains only one regular listener
       
   142      * the regular listener may be returned.  If the resulting multicaster
       
   143      * is empty, then {@code null} may be returned instead.
       
   144      * <p>
       
   145      * No exception is thrown if {@code oldl} is {@code null}.
       
   146      *
       
   147      * @param oldl the listener to be removed
       
   148      * @return resulting listener
       
   149      */
       
   150     protected EventListener remove(EventListener oldl) {
       
   151         if (oldl == a)  return b;
       
   152         if (oldl == b)  return a;
       
   153         EventListener a2 = removeInternal(a, oldl);
       
   154         EventListener b2 = removeInternal(b, oldl);
       
   155         if (a2 == a && b2 == b) {
       
   156             return this;        // it's not here
       
   157         }
       
   158         return addInternal(a2, b2);
       
   159     }
       
   160 
       
   161     /**
       
   162      * Handles the componentResized event by invoking the
       
   163      * componentResized methods on listener-a and listener-b.
       
   164      * @param e the component event
       
   165      */
       
   166     public void componentResized(ComponentEvent e) {
       
   167         ((ComponentListener)a).componentResized(e);
       
   168         ((ComponentListener)b).componentResized(e);
       
   169     }
       
   170 
       
   171     /**
       
   172      * Handles the componentMoved event by invoking the
       
   173      * componentMoved methods on listener-a and listener-b.
       
   174      * @param e the component event
       
   175      */
       
   176     public void componentMoved(ComponentEvent e) {
       
   177         ((ComponentListener)a).componentMoved(e);
       
   178         ((ComponentListener)b).componentMoved(e);
       
   179     }
       
   180 
       
   181     /**
       
   182      * Handles the componentShown event by invoking the
       
   183      * componentShown methods on listener-a and listener-b.
       
   184      * @param e the component event
       
   185      */
       
   186     public void componentShown(ComponentEvent e) {
       
   187         ((ComponentListener)a).componentShown(e);
       
   188         ((ComponentListener)b).componentShown(e);
       
   189     }
       
   190 
       
   191     /**
       
   192      * Handles the componentHidden event by invoking the
       
   193      * componentHidden methods on listener-a and listener-b.
       
   194      * @param e the component event
       
   195      */
       
   196     public void componentHidden(ComponentEvent e) {
       
   197         ((ComponentListener)a).componentHidden(e);
       
   198         ((ComponentListener)b).componentHidden(e);
       
   199     }
       
   200 
       
   201     /**
       
   202      * Handles the componentAdded container event by invoking the
       
   203      * componentAdded methods on listener-a and listener-b.
       
   204      * @param e the component event
       
   205      */
       
   206     public void componentAdded(ContainerEvent e) {
       
   207         ((ContainerListener)a).componentAdded(e);
       
   208         ((ContainerListener)b).componentAdded(e);
       
   209     }
       
   210 
       
   211     /**
       
   212      * Handles the componentRemoved container event by invoking the
       
   213      * componentRemoved methods on listener-a and listener-b.
       
   214      * @param e the component event
       
   215      */
       
   216     public void componentRemoved(ContainerEvent e) {
       
   217         ((ContainerListener)a).componentRemoved(e);
       
   218         ((ContainerListener)b).componentRemoved(e);
       
   219     }
       
   220 
       
   221     /**
       
   222      * Handles the focusGained event by invoking the
       
   223      * focusGained methods on listener-a and listener-b.
       
   224      * @param e the focus event
       
   225      */
       
   226     public void focusGained(FocusEvent e) {
       
   227         ((FocusListener)a).focusGained(e);
       
   228         ((FocusListener)b).focusGained(e);
       
   229     }
       
   230 
       
   231     /**
       
   232      * Handles the focusLost event by invoking the
       
   233      * focusLost methods on listener-a and listener-b.
       
   234      * @param e the focus event
       
   235      */
       
   236     public void focusLost(FocusEvent e) {
       
   237         ((FocusListener)a).focusLost(e);
       
   238         ((FocusListener)b).focusLost(e);
       
   239     }
       
   240 
       
   241     /**
       
   242      * Handles the keyTyped event by invoking the
       
   243      * keyTyped methods on listener-a and listener-b.
       
   244      * @param e the key event
       
   245      */
       
   246     public void keyTyped(KeyEvent e) {
       
   247         ((KeyListener)a).keyTyped(e);
       
   248         ((KeyListener)b).keyTyped(e);
       
   249     }
       
   250 
       
   251     /**
       
   252      * Handles the keyPressed event by invoking the
       
   253      * keyPressed methods on listener-a and listener-b.
       
   254      * @param e the key event
       
   255      */
       
   256     public void keyPressed(KeyEvent e) {
       
   257         ((KeyListener)a).keyPressed(e);
       
   258         ((KeyListener)b).keyPressed(e);
       
   259     }
       
   260 
       
   261     /**
       
   262      * Handles the keyReleased event by invoking the
       
   263      * keyReleased methods on listener-a and listener-b.
       
   264      * @param e the key event
       
   265      */
       
   266     public void keyReleased(KeyEvent e) {
       
   267         ((KeyListener)a).keyReleased(e);
       
   268         ((KeyListener)b).keyReleased(e);
       
   269     }
       
   270 
       
   271     /**
       
   272      * Handles the mouseClicked event by invoking the
       
   273      * mouseClicked methods on listener-a and listener-b.
       
   274      * @param e the mouse event
       
   275      */
       
   276     public void mouseClicked(MouseEvent e) {
       
   277         ((MouseListener)a).mouseClicked(e);
       
   278         ((MouseListener)b).mouseClicked(e);
       
   279     }
       
   280 
       
   281     /**
       
   282      * Handles the mousePressed event by invoking the
       
   283      * mousePressed methods on listener-a and listener-b.
       
   284      * @param e the mouse event
       
   285      */
       
   286     public void mousePressed(MouseEvent e) {
       
   287         ((MouseListener)a).mousePressed(e);
       
   288         ((MouseListener)b).mousePressed(e);
       
   289     }
       
   290 
       
   291     /**
       
   292      * Handles the mouseReleased event by invoking the
       
   293      * mouseReleased methods on listener-a and listener-b.
       
   294      * @param e the mouse event
       
   295      */
       
   296     public void mouseReleased(MouseEvent e) {
       
   297         ((MouseListener)a).mouseReleased(e);
       
   298         ((MouseListener)b).mouseReleased(e);
       
   299     }
       
   300 
       
   301     /**
       
   302      * Handles the mouseEntered event by invoking the
       
   303      * mouseEntered methods on listener-a and listener-b.
       
   304      * @param e the mouse event
       
   305      */
       
   306     public void mouseEntered(MouseEvent e) {
       
   307         ((MouseListener)a).mouseEntered(e);
       
   308         ((MouseListener)b).mouseEntered(e);
       
   309     }
       
   310 
       
   311     /**
       
   312      * Handles the mouseExited event by invoking the
       
   313      * mouseExited methods on listener-a and listener-b.
       
   314      * @param e the mouse event
       
   315      */
       
   316     public void mouseExited(MouseEvent e) {
       
   317         ((MouseListener)a).mouseExited(e);
       
   318         ((MouseListener)b).mouseExited(e);
       
   319     }
       
   320 
       
   321     /**
       
   322      * Handles the mouseDragged event by invoking the
       
   323      * mouseDragged methods on listener-a and listener-b.
       
   324      * @param e the mouse event
       
   325      */
       
   326     public void mouseDragged(MouseEvent e) {
       
   327         ((MouseMotionListener)a).mouseDragged(e);
       
   328         ((MouseMotionListener)b).mouseDragged(e);
       
   329     }
       
   330 
       
   331     /**
       
   332      * Handles the mouseMoved event by invoking the
       
   333      * mouseMoved methods on listener-a and listener-b.
       
   334      * @param e the mouse event
       
   335      */
       
   336     public void mouseMoved(MouseEvent e) {
       
   337         ((MouseMotionListener)a).mouseMoved(e);
       
   338         ((MouseMotionListener)b).mouseMoved(e);
       
   339     }
       
   340 
       
   341     /**
       
   342      * Handles the windowOpened event by invoking the
       
   343      * windowOpened methods on listener-a and listener-b.
       
   344      * @param e the window event
       
   345      */
       
   346     public void windowOpened(WindowEvent e) {
       
   347         ((WindowListener)a).windowOpened(e);
       
   348         ((WindowListener)b).windowOpened(e);
       
   349     }
       
   350 
       
   351     /**
       
   352      * Handles the windowClosing event by invoking the
       
   353      * windowClosing methods on listener-a and listener-b.
       
   354      * @param e the window event
       
   355      */
       
   356     public void windowClosing(WindowEvent e) {
       
   357         ((WindowListener)a).windowClosing(e);
       
   358         ((WindowListener)b).windowClosing(e);
       
   359     }
       
   360 
       
   361     /**
       
   362      * Handles the windowClosed event by invoking the
       
   363      * windowClosed methods on listener-a and listener-b.
       
   364      * @param e the window event
       
   365      */
       
   366     public void windowClosed(WindowEvent e) {
       
   367         ((WindowListener)a).windowClosed(e);
       
   368         ((WindowListener)b).windowClosed(e);
       
   369     }
       
   370 
       
   371     /**
       
   372      * Handles the windowIconified event by invoking the
       
   373      * windowIconified methods on listener-a and listener-b.
       
   374      * @param e the window event
       
   375      */
       
   376     public void windowIconified(WindowEvent e) {
       
   377         ((WindowListener)a).windowIconified(e);
       
   378         ((WindowListener)b).windowIconified(e);
       
   379     }
       
   380 
       
   381     /**
       
   382      * Handles the windowDeiconified event by invoking the
       
   383      * windowDeiconified methods on listener-a and listener-b.
       
   384      * @param e the window event
       
   385      */
       
   386     public void windowDeiconified(WindowEvent e) {
       
   387         ((WindowListener)a).windowDeiconified(e);
       
   388         ((WindowListener)b).windowDeiconified(e);
       
   389     }
       
   390 
       
   391     /**
       
   392      * Handles the windowActivated event by invoking the
       
   393      * windowActivated methods on listener-a and listener-b.
       
   394      * @param e the window event
       
   395      */
       
   396     public void windowActivated(WindowEvent e) {
       
   397         ((WindowListener)a).windowActivated(e);
       
   398         ((WindowListener)b).windowActivated(e);
       
   399     }
       
   400 
       
   401     /**
       
   402      * Handles the windowDeactivated event by invoking the
       
   403      * windowDeactivated methods on listener-a and listener-b.
       
   404      * @param e the window event
       
   405      */
       
   406     public void windowDeactivated(WindowEvent e) {
       
   407         ((WindowListener)a).windowDeactivated(e);
       
   408         ((WindowListener)b).windowDeactivated(e);
       
   409     }
       
   410 
       
   411     /**
       
   412      * Handles the windowStateChanged event by invoking the
       
   413      * windowStateChanged methods on listener-a and listener-b.
       
   414      * @param e the window event
       
   415      * @since 1.4
       
   416      */
       
   417     public void windowStateChanged(WindowEvent e) {
       
   418         ((WindowStateListener)a).windowStateChanged(e);
       
   419         ((WindowStateListener)b).windowStateChanged(e);
       
   420     }
       
   421 
       
   422 
       
   423     /**
       
   424      * Handles the windowGainedFocus event by invoking the windowGainedFocus
       
   425      * methods on listener-a and listener-b.
       
   426      * @param e the window event
       
   427      * @since 1.4
       
   428      */
       
   429     public void windowGainedFocus(WindowEvent e) {
       
   430         ((WindowFocusListener)a).windowGainedFocus(e);
       
   431         ((WindowFocusListener)b).windowGainedFocus(e);
       
   432     }
       
   433 
       
   434     /**
       
   435      * Handles the windowLostFocus event by invoking the windowLostFocus
       
   436      * methods on listener-a and listener-b.
       
   437      * @param e the window event
       
   438      * @since 1.4
       
   439      */
       
   440     public void windowLostFocus(WindowEvent e) {
       
   441         ((WindowFocusListener)a).windowLostFocus(e);
       
   442         ((WindowFocusListener)b).windowLostFocus(e);
       
   443     }
       
   444 
       
   445     /**
       
   446      * Handles the actionPerformed event by invoking the
       
   447      * actionPerformed methods on listener-a and listener-b.
       
   448      * @param e the action event
       
   449      */
       
   450     public void actionPerformed(ActionEvent e) {
       
   451         ((ActionListener)a).actionPerformed(e);
       
   452         ((ActionListener)b).actionPerformed(e);
       
   453     }
       
   454 
       
   455     /**
       
   456      * Handles the itemStateChanged event by invoking the
       
   457      * itemStateChanged methods on listener-a and listener-b.
       
   458      * @param e the item event
       
   459      */
       
   460     public void itemStateChanged(ItemEvent e) {
       
   461         ((ItemListener)a).itemStateChanged(e);
       
   462         ((ItemListener)b).itemStateChanged(e);
       
   463     }
       
   464 
       
   465     /**
       
   466      * Handles the adjustmentValueChanged event by invoking the
       
   467      * adjustmentValueChanged methods on listener-a and listener-b.
       
   468      * @param e the adjustment event
       
   469      */
       
   470     public void adjustmentValueChanged(AdjustmentEvent e) {
       
   471         ((AdjustmentListener)a).adjustmentValueChanged(e);
       
   472         ((AdjustmentListener)b).adjustmentValueChanged(e);
       
   473     }
       
   474     public void textValueChanged(TextEvent e) {
       
   475         ((TextListener)a).textValueChanged(e);
       
   476         ((TextListener)b).textValueChanged(e);
       
   477     }
       
   478 
       
   479     /**
       
   480      * Handles the inputMethodTextChanged event by invoking the
       
   481      * inputMethodTextChanged methods on listener-a and listener-b.
       
   482      * @param e the item event
       
   483      */
       
   484     public void inputMethodTextChanged(InputMethodEvent e) {
       
   485        ((InputMethodListener)a).inputMethodTextChanged(e);
       
   486        ((InputMethodListener)b).inputMethodTextChanged(e);
       
   487     }
       
   488 
       
   489     /**
       
   490      * Handles the caretPositionChanged event by invoking the
       
   491      * caretPositionChanged methods on listener-a and listener-b.
       
   492      * @param e the item event
       
   493      */
       
   494     public void caretPositionChanged(InputMethodEvent e) {
       
   495        ((InputMethodListener)a).caretPositionChanged(e);
       
   496        ((InputMethodListener)b).caretPositionChanged(e);
       
   497     }
       
   498 
       
   499     /**
       
   500      * Handles the hierarchyChanged event by invoking the
       
   501      * hierarchyChanged methods on listener-a and listener-b.
       
   502      * @param e the item event
       
   503      * @since 1.3
       
   504      */
       
   505     public void hierarchyChanged(HierarchyEvent e) {
       
   506         ((HierarchyListener)a).hierarchyChanged(e);
       
   507         ((HierarchyListener)b).hierarchyChanged(e);
       
   508     }
       
   509 
       
   510     /**
       
   511      * Handles the ancestorMoved event by invoking the
       
   512      * ancestorMoved methods on listener-a and listener-b.
       
   513      * @param e the item event
       
   514      * @since 1.3
       
   515      */
       
   516     public void ancestorMoved(HierarchyEvent e) {
       
   517         ((HierarchyBoundsListener)a).ancestorMoved(e);
       
   518         ((HierarchyBoundsListener)b).ancestorMoved(e);
       
   519     }
       
   520 
       
   521     /**
       
   522      * Handles the ancestorResized event by invoking the
       
   523      * ancestorResized methods on listener-a and listener-b.
       
   524      * @param e the item event
       
   525      * @since 1.3
       
   526      */
       
   527     public void ancestorResized(HierarchyEvent e) {
       
   528         ((HierarchyBoundsListener)a).ancestorResized(e);
       
   529         ((HierarchyBoundsListener)b).ancestorResized(e);
       
   530     }
       
   531 
       
   532     /**
       
   533      * Handles the mouseWheelMoved event by invoking the
       
   534      * mouseWheelMoved methods on listener-a and listener-b.
       
   535      * @param e the mouse event
       
   536      * @since 1.4
       
   537      */
       
   538     public void mouseWheelMoved(MouseWheelEvent e) {
       
   539         ((MouseWheelListener)a).mouseWheelMoved(e);
       
   540         ((MouseWheelListener)b).mouseWheelMoved(e);
       
   541     }
       
   542 
       
   543     /**
       
   544      * Adds component-listener-a with component-listener-b and
       
   545      * returns the resulting multicast listener.
       
   546      * @param a component-listener-a
       
   547      * @param b component-listener-b
       
   548      * @return the resulting listener
       
   549      */
       
   550     public static ComponentListener add(ComponentListener a, ComponentListener b) {
       
   551         return (ComponentListener)addInternal(a, b);
       
   552     }
       
   553 
       
   554     /**
       
   555      * Adds container-listener-a with container-listener-b and
       
   556      * returns the resulting multicast listener.
       
   557      * @param a container-listener-a
       
   558      * @param b container-listener-b
       
   559      * @return the resulting listener
       
   560      */
       
   561     public static ContainerListener add(ContainerListener a, ContainerListener b) {
       
   562         return (ContainerListener)addInternal(a, b);
       
   563     }
       
   564 
       
   565     /**
       
   566      * Adds focus-listener-a with focus-listener-b and
       
   567      * returns the resulting multicast listener.
       
   568      * @param a focus-listener-a
       
   569      * @param b focus-listener-b
       
   570      * @return the resulting listener
       
   571      */
       
   572     public static FocusListener add(FocusListener a, FocusListener b) {
       
   573         return (FocusListener)addInternal(a, b);
       
   574     }
       
   575 
       
   576     /**
       
   577      * Adds key-listener-a with key-listener-b and
       
   578      * returns the resulting multicast listener.
       
   579      * @param a key-listener-a
       
   580      * @param b key-listener-b
       
   581      * @return the resulting listener
       
   582      */
       
   583     public static KeyListener add(KeyListener a, KeyListener b) {
       
   584         return (KeyListener)addInternal(a, b);
       
   585     }
       
   586 
       
   587     /**
       
   588      * Adds mouse-listener-a with mouse-listener-b and
       
   589      * returns the resulting multicast listener.
       
   590      * @param a mouse-listener-a
       
   591      * @param b mouse-listener-b
       
   592      * @return the resulting listener
       
   593      */
       
   594     public static MouseListener add(MouseListener a, MouseListener b) {
       
   595         return (MouseListener)addInternal(a, b);
       
   596     }
       
   597 
       
   598     /**
       
   599      * Adds mouse-motion-listener-a with mouse-motion-listener-b and
       
   600      * returns the resulting multicast listener.
       
   601      * @param a mouse-motion-listener-a
       
   602      * @param b mouse-motion-listener-b
       
   603      * @return the resulting listener
       
   604      */
       
   605     public static MouseMotionListener add(MouseMotionListener a, MouseMotionListener b) {
       
   606         return (MouseMotionListener)addInternal(a, b);
       
   607     }
       
   608 
       
   609     /**
       
   610      * Adds window-listener-a with window-listener-b and
       
   611      * returns the resulting multicast listener.
       
   612      * @param a window-listener-a
       
   613      * @param b window-listener-b
       
   614      * @return the resulting listener
       
   615      */
       
   616     public static WindowListener add(WindowListener a, WindowListener b) {
       
   617         return (WindowListener)addInternal(a, b);
       
   618     }
       
   619 
       
   620     /**
       
   621      * Adds window-state-listener-a with window-state-listener-b
       
   622      * and returns the resulting multicast listener.
       
   623      * @param a window-state-listener-a
       
   624      * @param b window-state-listener-b
       
   625      * @return the resulting listener
       
   626      * @since 1.4
       
   627      */
       
   628     @SuppressWarnings("overloads")
       
   629     public static WindowStateListener add(WindowStateListener a,
       
   630                                           WindowStateListener b) {
       
   631         return (WindowStateListener)addInternal(a, b);
       
   632     }
       
   633 
       
   634     /**
       
   635      * Adds window-focus-listener-a with window-focus-listener-b
       
   636      * and returns the resulting multicast listener.
       
   637      * @param a window-focus-listener-a
       
   638      * @param b window-focus-listener-b
       
   639      * @return the resulting listener
       
   640      * @since 1.4
       
   641      */
       
   642     public static WindowFocusListener add(WindowFocusListener a,
       
   643                                           WindowFocusListener b) {
       
   644         return (WindowFocusListener)addInternal(a, b);
       
   645     }
       
   646 
       
   647     /**
       
   648      * Adds action-listener-a with action-listener-b and
       
   649      * returns the resulting multicast listener.
       
   650      * @param a action-listener-a
       
   651      * @param b action-listener-b
       
   652      * @return the resulting listener
       
   653      */
       
   654     @SuppressWarnings("overloads")
       
   655     public static ActionListener add(ActionListener a, ActionListener b) {
       
   656         return (ActionListener)addInternal(a, b);
       
   657     }
       
   658 
       
   659     /**
       
   660      * Adds item-listener-a with item-listener-b and
       
   661      * returns the resulting multicast listener.
       
   662      * @param a item-listener-a
       
   663      * @param b item-listener-b
       
   664      * @return the resulting listener
       
   665      */
       
   666     @SuppressWarnings("overloads")
       
   667     public static ItemListener add(ItemListener a, ItemListener b) {
       
   668         return (ItemListener)addInternal(a, b);
       
   669     }
       
   670 
       
   671     /**
       
   672      * Adds adjustment-listener-a with adjustment-listener-b and
       
   673      * returns the resulting multicast listener.
       
   674      * @param a adjustment-listener-a
       
   675      * @param b adjustment-listener-b
       
   676      * @return the resulting listener
       
   677      */
       
   678     @SuppressWarnings("overloads")
       
   679     public static AdjustmentListener add(AdjustmentListener a, AdjustmentListener b) {
       
   680         return (AdjustmentListener)addInternal(a, b);
       
   681     }
       
   682 
       
   683     /**
       
   684      * Adds text-listener-a with text-listener-b and
       
   685      * returns the resulting multicast listener.
       
   686      *
       
   687      * @param  a text-listener-a
       
   688      * @param  b text-listener-b
       
   689      * @return the resulting listener
       
   690      */
       
   691     @SuppressWarnings("overloads")
       
   692     public static TextListener add(TextListener a, TextListener b) {
       
   693         return (TextListener)addInternal(a, b);
       
   694     }
       
   695 
       
   696     /**
       
   697      * Adds input-method-listener-a with input-method-listener-b and
       
   698      * returns the resulting multicast listener.
       
   699      * @param a input-method-listener-a
       
   700      * @param b input-method-listener-b
       
   701      * @return the resulting listener
       
   702      */
       
   703      public static InputMethodListener add(InputMethodListener a, InputMethodListener b) {
       
   704         return (InputMethodListener)addInternal(a, b);
       
   705      }
       
   706 
       
   707     /**
       
   708      * Adds hierarchy-listener-a with hierarchy-listener-b and
       
   709      * returns the resulting multicast listener.
       
   710      * @param a hierarchy-listener-a
       
   711      * @param b hierarchy-listener-b
       
   712      * @return the resulting listener
       
   713      * @since 1.3
       
   714      */
       
   715     @SuppressWarnings("overloads")
       
   716      public static HierarchyListener add(HierarchyListener a, HierarchyListener b) {
       
   717         return (HierarchyListener)addInternal(a, b);
       
   718      }
       
   719 
       
   720     /**
       
   721      * Adds hierarchy-bounds-listener-a with hierarchy-bounds-listener-b and
       
   722      * returns the resulting multicast listener.
       
   723      * @param a hierarchy-bounds-listener-a
       
   724      * @param b hierarchy-bounds-listener-b
       
   725      * @return the resulting listener
       
   726      * @since 1.3
       
   727      */
       
   728      public static HierarchyBoundsListener add(HierarchyBoundsListener a, HierarchyBoundsListener b) {
       
   729         return (HierarchyBoundsListener)addInternal(a, b);
       
   730      }
       
   731 
       
   732     /**
       
   733      * Adds mouse-wheel-listener-a with mouse-wheel-listener-b and
       
   734      * returns the resulting multicast listener.
       
   735      * @param a mouse-wheel-listener-a
       
   736      * @param b mouse-wheel-listener-b
       
   737      * @return the resulting listener
       
   738      * @since 1.4
       
   739      */
       
   740     @SuppressWarnings("overloads")
       
   741     public static MouseWheelListener add(MouseWheelListener a,
       
   742                                          MouseWheelListener b) {
       
   743         return (MouseWheelListener)addInternal(a, b);
       
   744     }
       
   745 
       
   746     /**
       
   747      * Removes the old component-listener from component-listener-l and
       
   748      * returns the resulting multicast listener.
       
   749      * @param l component-listener-l
       
   750      * @param oldl the component-listener being removed
       
   751      * @return the resulting listener
       
   752      */
       
   753     public static ComponentListener remove(ComponentListener l, ComponentListener oldl) {
       
   754         return (ComponentListener) removeInternal(l, oldl);
       
   755     }
       
   756 
       
   757     /**
       
   758      * Removes the old container-listener from container-listener-l and
       
   759      * returns the resulting multicast listener.
       
   760      * @param l container-listener-l
       
   761      * @param oldl the container-listener being removed
       
   762      * @return the resulting listener
       
   763      */
       
   764     public static ContainerListener remove(ContainerListener l, ContainerListener oldl) {
       
   765         return (ContainerListener) removeInternal(l, oldl);
       
   766     }
       
   767 
       
   768     /**
       
   769      * Removes the old focus-listener from focus-listener-l and
       
   770      * returns the resulting multicast listener.
       
   771      * @param l focus-listener-l
       
   772      * @param oldl the focus-listener being removed
       
   773      * @return the resulting listener
       
   774      */
       
   775     public static FocusListener remove(FocusListener l, FocusListener oldl) {
       
   776         return (FocusListener) removeInternal(l, oldl);
       
   777     }
       
   778 
       
   779     /**
       
   780      * Removes the old key-listener from key-listener-l and
       
   781      * returns the resulting multicast listener.
       
   782      * @param l key-listener-l
       
   783      * @param oldl the key-listener being removed
       
   784      * @return the resulting listener
       
   785      */
       
   786     public static KeyListener remove(KeyListener l, KeyListener oldl) {
       
   787         return (KeyListener) removeInternal(l, oldl);
       
   788     }
       
   789 
       
   790     /**
       
   791      * Removes the old mouse-listener from mouse-listener-l and
       
   792      * returns the resulting multicast listener.
       
   793      * @param l mouse-listener-l
       
   794      * @param oldl the mouse-listener being removed
       
   795      * @return the resulting listener
       
   796      */
       
   797     public static MouseListener remove(MouseListener l, MouseListener oldl) {
       
   798         return (MouseListener) removeInternal(l, oldl);
       
   799     }
       
   800 
       
   801     /**
       
   802      * Removes the old mouse-motion-listener from mouse-motion-listener-l
       
   803      * and returns the resulting multicast listener.
       
   804      * @param l mouse-motion-listener-l
       
   805      * @param oldl the mouse-motion-listener being removed
       
   806      * @return the resulting listener
       
   807      */
       
   808     public static MouseMotionListener remove(MouseMotionListener l, MouseMotionListener oldl) {
       
   809         return (MouseMotionListener) removeInternal(l, oldl);
       
   810     }
       
   811 
       
   812     /**
       
   813      * Removes the old window-listener from window-listener-l and
       
   814      * returns the resulting multicast listener.
       
   815      * @param l window-listener-l
       
   816      * @param oldl the window-listener being removed
       
   817      * @return the resulting listener
       
   818      */
       
   819     public static WindowListener remove(WindowListener l, WindowListener oldl) {
       
   820         return (WindowListener) removeInternal(l, oldl);
       
   821     }
       
   822 
       
   823     /**
       
   824      * Removes the old window-state-listener from window-state-listener-l
       
   825      * and returns the resulting multicast listener.
       
   826      * @param l window-state-listener-l
       
   827      * @param oldl the window-state-listener being removed
       
   828      * @return the resulting listener
       
   829      * @since 1.4
       
   830      */
       
   831     @SuppressWarnings("overloads")
       
   832     public static WindowStateListener remove(WindowStateListener l,
       
   833                                              WindowStateListener oldl) {
       
   834         return (WindowStateListener) removeInternal(l, oldl);
       
   835     }
       
   836 
       
   837     /**
       
   838      * Removes the old window-focus-listener from window-focus-listener-l
       
   839      * and returns the resulting multicast listener.
       
   840      * @param l window-focus-listener-l
       
   841      * @param oldl the window-focus-listener being removed
       
   842      * @return the resulting listener
       
   843      * @since 1.4
       
   844      */
       
   845     public static WindowFocusListener remove(WindowFocusListener l,
       
   846                                              WindowFocusListener oldl) {
       
   847         return (WindowFocusListener) removeInternal(l, oldl);
       
   848     }
       
   849 
       
   850     /**
       
   851      * Removes the old action-listener from action-listener-l and
       
   852      * returns the resulting multicast listener.
       
   853      * @param l action-listener-l
       
   854      * @param oldl the action-listener being removed
       
   855      * @return the resulting listener
       
   856      */
       
   857     @SuppressWarnings("overloads")
       
   858     public static ActionListener remove(ActionListener l, ActionListener oldl) {
       
   859         return (ActionListener) removeInternal(l, oldl);
       
   860     }
       
   861 
       
   862     /**
       
   863      * Removes the old item-listener from item-listener-l and
       
   864      * returns the resulting multicast listener.
       
   865      * @param l item-listener-l
       
   866      * @param oldl the item-listener being removed
       
   867      * @return the resulting listener
       
   868      */
       
   869     @SuppressWarnings("overloads")
       
   870     public static ItemListener remove(ItemListener l, ItemListener oldl) {
       
   871         return (ItemListener) removeInternal(l, oldl);
       
   872     }
       
   873 
       
   874     /**
       
   875      * Removes the old adjustment-listener from adjustment-listener-l and
       
   876      * returns the resulting multicast listener.
       
   877      * @param l adjustment-listener-l
       
   878      * @param oldl the adjustment-listener being removed
       
   879      * @return the resulting listener
       
   880      */
       
   881     @SuppressWarnings("overloads")
       
   882     public static AdjustmentListener remove(AdjustmentListener l, AdjustmentListener oldl) {
       
   883         return (AdjustmentListener) removeInternal(l, oldl);
       
   884     }
       
   885 
       
   886     /**
       
   887      * Removes the old text-listener from text-listener-l and
       
   888      * returns the resulting multicast listener.
       
   889      *
       
   890      * @param  l text-listener-l
       
   891      * @param  oldl the text-listener being removed
       
   892      * @return the resulting listener
       
   893      */
       
   894     @SuppressWarnings("overloads")
       
   895     public static TextListener remove(TextListener l, TextListener oldl) {
       
   896         return (TextListener) removeInternal(l, oldl);
       
   897     }
       
   898 
       
   899     /**
       
   900      * Removes the old input-method-listener from input-method-listener-l and
       
   901      * returns the resulting multicast listener.
       
   902      * @param l input-method-listener-l
       
   903      * @param oldl the input-method-listener being removed
       
   904      * @return the resulting listener
       
   905      */
       
   906     public static InputMethodListener remove(InputMethodListener l, InputMethodListener oldl) {
       
   907         return (InputMethodListener) removeInternal(l, oldl);
       
   908     }
       
   909 
       
   910     /**
       
   911      * Removes the old hierarchy-listener from hierarchy-listener-l and
       
   912      * returns the resulting multicast listener.
       
   913      * @param l hierarchy-listener-l
       
   914      * @param oldl the hierarchy-listener being removed
       
   915      * @return the resulting listener
       
   916      * @since 1.3
       
   917      */
       
   918     @SuppressWarnings("overloads")
       
   919     public static HierarchyListener remove(HierarchyListener l, HierarchyListener oldl) {
       
   920         return (HierarchyListener) removeInternal(l, oldl);
       
   921     }
       
   922 
       
   923     /**
       
   924      * Removes the old hierarchy-bounds-listener from
       
   925      * hierarchy-bounds-listener-l and returns the resulting multicast
       
   926      * listener.
       
   927      * @param l hierarchy-bounds-listener-l
       
   928      * @param oldl the hierarchy-bounds-listener being removed
       
   929      * @return the resulting listener
       
   930      * @since 1.3
       
   931      */
       
   932     public static HierarchyBoundsListener remove(HierarchyBoundsListener l, HierarchyBoundsListener oldl) {
       
   933         return (HierarchyBoundsListener) removeInternal(l, oldl);
       
   934     }
       
   935 
       
   936     /**
       
   937      * Removes the old mouse-wheel-listener from mouse-wheel-listener-l
       
   938      * and returns the resulting multicast listener.
       
   939      * @param l mouse-wheel-listener-l
       
   940      * @param oldl the mouse-wheel-listener being removed
       
   941      * @return the resulting listener
       
   942      * @since 1.4
       
   943      */
       
   944     @SuppressWarnings("overloads")
       
   945     public static MouseWheelListener remove(MouseWheelListener l,
       
   946                                             MouseWheelListener oldl) {
       
   947       return (MouseWheelListener) removeInternal(l, oldl);
       
   948     }
       
   949 
       
   950     /**
       
   951      * Returns the resulting multicast listener from adding listener-a
       
   952      * and listener-b together.
       
   953      * If listener-a is null, it returns listener-b;
       
   954      * If listener-b is null, it returns listener-a
       
   955      * If neither are null, then it creates and returns
       
   956      * a new AWTEventMulticaster instance which chains a with b.
       
   957      * @param a event listener-a
       
   958      * @param b event listener-b
       
   959      * @return the resulting listener
       
   960      */
       
   961     protected static EventListener addInternal(EventListener a, EventListener b) {
       
   962         if (a == null)  return b;
       
   963         if (b == null)  return a;
       
   964         return new AWTEventMulticaster(a, b);
       
   965     }
       
   966 
       
   967     /**
       
   968      * Returns the resulting multicast listener after removing the
       
   969      * old listener from listener-l.
       
   970      * If listener-l equals the old listener OR listener-l is null,
       
   971      * returns null.
       
   972      * Else if listener-l is an instance of AWTEventMulticaster,
       
   973      * then it removes the old listener from it.
       
   974      * Else, returns listener l.
       
   975      * @param l the listener being removed from
       
   976      * @param oldl the listener being removed
       
   977      * @return the resulting listener
       
   978      */
       
   979     protected static EventListener removeInternal(EventListener l, EventListener oldl) {
       
   980         if (l == oldl || l == null) {
       
   981             return null;
       
   982         } else if (l instanceof AWTEventMulticaster) {
       
   983             return ((AWTEventMulticaster)l).remove(oldl);
       
   984         } else {
       
   985             return l;           // it's not here
       
   986         }
       
   987     }
       
   988 
       
   989 
       
   990    /**
       
   991     * Serialization support. Saves all Serializable listeners
       
   992     * to a serialization stream.
       
   993     *
       
   994     * @param  s the stream to save to
       
   995     * @param  k a prefix stream to put before each serializable listener
       
   996     * @throws IOException if serialization fails
       
   997     */
       
   998     protected void saveInternal(ObjectOutputStream s, String k) throws IOException {
       
   999         if (a instanceof AWTEventMulticaster) {
       
  1000             ((AWTEventMulticaster)a).saveInternal(s, k);
       
  1001         }
       
  1002         else if (a instanceof Serializable) {
       
  1003             s.writeObject(k);
       
  1004             s.writeObject(a);
       
  1005         }
       
  1006 
       
  1007         if (b instanceof AWTEventMulticaster) {
       
  1008             ((AWTEventMulticaster)b).saveInternal(s, k);
       
  1009         }
       
  1010         else if (b instanceof Serializable) {
       
  1011             s.writeObject(k);
       
  1012             s.writeObject(b);
       
  1013         }
       
  1014     }
       
  1015 
       
  1016    /**
       
  1017     * Saves a Serializable listener chain to a serialization stream.
       
  1018     *
       
  1019     * @param  s the stream to save to
       
  1020     * @param  k a prefix stream to put before each serializable listener
       
  1021     * @param  l the listener chain to save
       
  1022     * @throws IOException if serialization fails
       
  1023     */
       
  1024     protected static void save(ObjectOutputStream s, String k, EventListener l) throws IOException {
       
  1025       if (l == null) {
       
  1026           return;
       
  1027       }
       
  1028       else if (l instanceof AWTEventMulticaster) {
       
  1029           ((AWTEventMulticaster)l).saveInternal(s, k);
       
  1030       }
       
  1031       else if (l instanceof Serializable) {
       
  1032            s.writeObject(k);
       
  1033            s.writeObject(l);
       
  1034       }
       
  1035     }
       
  1036 
       
  1037     /*
       
  1038      * Recursive method which returns a count of the number of listeners in
       
  1039      * EventListener, handling the (common) case of l actually being an
       
  1040      * AWTEventMulticaster.  Additionally, only listeners of type listenerType
       
  1041      * are counted.  Method modified to fix bug 4513402.  -bchristi
       
  1042      */
       
  1043     private static int getListenerCount(EventListener l, Class<?> listenerType) {
       
  1044         if (l instanceof AWTEventMulticaster) {
       
  1045             AWTEventMulticaster mc = (AWTEventMulticaster)l;
       
  1046             return getListenerCount(mc.a, listenerType) +
       
  1047              getListenerCount(mc.b, listenerType);
       
  1048         }
       
  1049         else {
       
  1050             // Only count listeners of correct type
       
  1051             return listenerType.isInstance(l) ? 1 : 0;
       
  1052         }
       
  1053     }
       
  1054 
       
  1055     /*
       
  1056      * Recursive method which populates EventListener array a with EventListeners
       
  1057      * from l.  l is usually an AWTEventMulticaster.  Bug 4513402 revealed that
       
  1058      * if l differed in type from the element type of a, an ArrayStoreException
       
  1059      * would occur.  Now l is only inserted into a if it's of the appropriate
       
  1060      * type.  -bchristi
       
  1061      */
       
  1062     private static int populateListenerArray(EventListener[] a, EventListener l, int index) {
       
  1063         if (l instanceof AWTEventMulticaster) {
       
  1064             AWTEventMulticaster mc = (AWTEventMulticaster)l;
       
  1065             int lhs = populateListenerArray(a, mc.a, index);
       
  1066             return populateListenerArray(a, mc.b, lhs);
       
  1067         }
       
  1068         else if (a.getClass().getComponentType().isInstance(l)) {
       
  1069             a[index] = l;
       
  1070             return index + 1;
       
  1071         }
       
  1072         // Skip nulls, instances of wrong class
       
  1073         else {
       
  1074             return index;
       
  1075         }
       
  1076     }
       
  1077 
       
  1078     /**
       
  1079      * Returns an array of all the objects chained as
       
  1080      * <code><em>Foo</em>Listener</code>s by the specified
       
  1081      * {@code java.util.EventListener}.
       
  1082      * <code><em>Foo</em>Listener</code>s are chained by the
       
  1083      * {@code AWTEventMulticaster} using the
       
  1084      * <code>add<em>Foo</em>Listener</code> method.
       
  1085      * If a {@code null} listener is specified, this method returns an
       
  1086      * empty array. If the specified listener is not an instance of
       
  1087      * {@code AWTEventMulticaster}, this method returns an array which
       
  1088      * contains only the specified listener. If no such listeners are chained,
       
  1089      * this method returns an empty array.
       
  1090      *
       
  1091      * @param <T> the listener type
       
  1092      * @param l the specified {@code java.util.EventListener}
       
  1093      * @param listenerType the type of listeners requested; this parameter
       
  1094      *          should specify an interface that descends from
       
  1095      *          {@code java.util.EventListener}
       
  1096      * @return an array of all objects chained as
       
  1097      *          <code><em>Foo</em>Listener</code>s by the specified multicast
       
  1098      *          listener, or an empty array if no such listeners have been
       
  1099      *          chained by the specified multicast listener
       
  1100      * @exception NullPointerException if the specified
       
  1101      *             {@code listenertype} parameter is {@code null}
       
  1102      * @exception ClassCastException if {@code listenerType}
       
  1103      *          doesn't specify a class or interface that implements
       
  1104      *          {@code java.util.EventListener}
       
  1105      *
       
  1106      * @since 1.4
       
  1107      */
       
  1108     @SuppressWarnings("unchecked")
       
  1109     public static <T extends EventListener> T[]
       
  1110         getListeners(EventListener l, Class<T> listenerType)
       
  1111     {
       
  1112         if (listenerType == null) {
       
  1113             throw new NullPointerException ("Listener type should not be null");
       
  1114         }
       
  1115 
       
  1116         int n = getListenerCount(l, listenerType);
       
  1117         T[] result = (T[])Array.newInstance(listenerType, n);
       
  1118         populateListenerArray(result, l, 0);
       
  1119         return result;
       
  1120     }
       
  1121 }