Ignore:
Timestamp:
Apr 27, 2004, 8:39:34 PM (22 years ago)
Author:
bird
Message:

GCC v3.3.3 sources.

Location:
branches/GNU/src/gcc
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • branches/GNU/src/gcc

    • Property svn:ignore
      •  

        old new  
        2626configure.vr
        2727configure.vrs
         28
        2829Makefile
        29 dir.info
        3030lost+found
        3131update.out
  • branches/GNU/src/gcc/libjava/java/beans/BeanInfo.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    7575public interface BeanInfo {
    7676        /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
    77         public static int ICON_COLOR_16x16 = 1;
     77        public static int ICON_COLOR_16x16 = 1;
    7878        /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
    79         public static int ICON_COLOR_32x32 = 2;
     79        public static int ICON_COLOR_32x32 = 2;
    8080        /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
    81         public static int ICON_MONO_16x16 = 3;
     81        public static int ICON_MONO_16x16 = 3;
    8282        /** Use this as a parameter for the getIcon() command to retrieve a certain type of icon. **/
    83         public static int ICON_MONO_32x32 = 4;
     83        public static int ICON_MONO_32x32 = 4;
    8484
    8585        /** Get the general description of this Bean type.
  • branches/GNU/src/gcc/libjava/java/beans/Introspector.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    11/* java.beans.Introspector
    2    Copyright (C) 1998 Free Software Foundation, Inc.
     2   Copyright (C) 1998 Free Software Foundation, Inc.
    33
    44This file is part of GNU Classpath.
     
    210210  }
    211211
     212
     213
     214
     215
     216
     217
     218
     219
     220
     221
     222
     223
     224
     225
     226
     227
     228
     229
     230
     231
     232
     233
     234
     235
     236
     237
    212238  /**
    213239   * Get the BeanInfo for class <CODE>beanClass</CODE>,
  • branches/GNU/src/gcc/libjava/java/beans/PropertyChangeEvent.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    1 /* java.beans.PropertyChangeEvent
    2    Copyright (C) 1998, 2000 Free Software Foundation, Inc.
     1/*
     2   Copyright (C) 1998, 2000 Free Software Foundation, Inc.
    33
    44This file is part of GNU Classpath.
     
    88the Free Software Foundation; either version 2, or (at your option)
    99any later version.
    10  
     10
    1111GNU Classpath is distributed in the hope that it will be useful, but
    1212WITHOUT ANY WARRANTY; without even the implied warranty of
     
    3939package java.beans;
    4040
     41
     42
    4143/**
    42  ** PropertyChangeEvents are fired in the PropertyChange
    43  ** and VetoableChange event classes.  They represent the
    44  ** old and new values as well as the source Bean.<P>
    45  **
    46  ** If the old or new value is a primitive type, it must
    47  ** be wrapped in the appropriate wrapper type
    48  ** (java.lang.Integer for int, etc., etc.).<P>
    49  **
    50  ** If the old or new values are unknown (although why
    51  ** that would be I do not know), they may be null.<P>
    52  **
    53  ** Right now Sun put in a propagationId, reserved for
    54  ** future use.  Read the comments on the constructor
    55  ** and on setPropagationId for more information.
    56  **
    57  ** @author John Keiser
    58  ** @since JDK1.1
    59  ** @version 1.1.0, 29 Jul 1998
    60  **/
     44 * PropertyChangeEvents are fired in the PropertyChange and VetoableChange
     45 * event classes.  They represent the old and new values as well as the
     46 * source Bean. If the old or new value is a primitive type, it must be
     47 * wrapped in the appropriate wrapper type (java.lang.Integer for int, etc.,
     48 * etc.).
     49 *
     50 * <p>If the old or new values are unknown (although why that would be I do
     51 * not know), they may be null. Also, if the set of properties itself has
     52 * changed, the name should be null, and the old and new values may also be
     53 * null. Right now Sun put in a propagationId, reserved for future use. Read
     54 * the comments on the constructor and on setPropagationId for more
     55 * information.
     56 *
     57 * @author John Keiser
     58 * @author Eric Blake <[email protected]>
     59 * @since 1.1
     60 * @status udpated to 1.4
     61 */
     62public class PropertyChangeEvent extends EventObject
     63{
     64  /**
     65   * Compatible with JDK 1.1+.
     66   */
     67  private static final long serialVersionUID = 7042693688939648123L;
    6168
    62 public class PropertyChangeEvent extends java.util.EventObject {
    63         String propertyName;
    64         Object oldValue;
    65         Object newValue;
    66         Object propagationId;
     69  /**
     70   * The name of the property that changed, may be null. Package visible for
     71   * use by PropertyChangeSupport.
     72   *
     73   * @serial the changed property name
     74   */
     75  final String propertyName;
    6776
    68         private static final long serialVersionUID = 7042693688939648123L;
     77  /**
     78   * The new value of the property, may be null. Package visible for use by
     79   * PropertyChangeSupport.
     80   *
     81   * @serial the new property value
     82   */
     83  final Object newValue;
    6984
    70         /** Create a new PropertyChangeEvent.  Remember that if
    71          ** you received a PropertyChangeEvent and are sending
    72          ** a new one, you should also set the propagation ID
    73          ** from the old PropertyChangeEvent.
    74          ** @param source the Bean containing the property.
    75          ** @param propertyName the property's name.
    76          ** @param oldValue the old value of the property.
    77          ** @param newValue the new value of the property.
    78          **/
    79         public PropertyChangeEvent(Object source, String propertyName, Object oldVal, Object newVal) {
    80                 super(source);
    81                 this.propertyName = propertyName;
    82                 oldValue = oldVal;
    83                 newValue = newVal;
    84         }
     85  /**
     86   * The old value of the property, may be null. Package visible for use by
     87   * PropertyChangeSupport.
     88   *
     89   * @serial the old property value
     90   */
     91  final Object oldValue;
    8592
    86         /** Get the property name.
    87          ** @return the property name.
    88          **/
    89         public String getPropertyName() {
    90                 return propertyName;
    91         }
     93  /**
     94   * The propagation ID, reserved for future use. May be null.
     95   *
     96   * @see #getPropagationId()
     97   * @serial the Propagation ID
     98   */
     99  private Object propagationId;
    92100
    93         /** Get the property's old value.
    94          ** @return the property's old value.
    95          **/
    96         public Object getOldValue() {
    97                 return oldValue;
    98         }
     101  /**
     102   * Create a new PropertyChangeEvent. Remember that if you received a
     103   * PropertyChangeEvent and are sending a new one, you should also set the
     104   * propagation ID from the old PropertyChangeEvent.
     105   *
     106   * @param source the Bean containing the property
     107   * @param propertyName the property's name
     108   * @param oldValue the old value of the property
     109   * @param newValue the new value of the property
     110   * @throws IllegalArgumentException if source is null
     111   */
     112  public PropertyChangeEvent(Object source, String propertyName,
     113                             Object oldVal, Object newVal)
     114  {
     115    super(source);
     116    this.propertyName = propertyName;
     117    oldValue = oldVal;
     118    newValue = newVal;
     119  }
    99120
    100         /** Get the property's new value.
    101          ** @return the property's new value.
    102          **/
    103         public Object getNewValue() {
    104                 return newValue;
    105         }
     121  /**
     122   * Get the property name. May be null if multiple properties changed.
     123   *
     124   * @return the property name
     125   */
     126  public String getPropertyName()
     127  {
     128    return propertyName;
     129  }
    106130
    107         /** Set the propagation ID.  This is a way for the event
    108          ** to be passed from hand to hand and retain a little
    109          ** extra state.  Right now it is unused, but it should
    110          ** be propagated anyway so that future versions of
    111          ** JavaBeans can use it, for God knows what.
    112          ** @param propagationId the propagation ID.
    113          **/
    114         public void setPropagationId(Object propagationId) {
    115                 this.propagationId = propagationId;
    116         }
     131  /**
     132   * Get the property's new value. May be null if multiple properties changed.
     133   *
     134   * @return the property's new value
     135   */
     136  public Object getNewValue()
     137  {
     138    return newValue;
     139  }
    117140
    118         /** Get the propagation ID.
    119          ** @return the propagation ID.
    120          **/
    121         public Object getPropagationId() {
    122                 return propagationId;
    123         }
    124 }
     141  /**
     142   * Get the property's old value. May be null if multiple properties changed.
     143   *
     144   * @return the property's old value
     145   */
     146  public Object getOldValue()
     147  {
     148    return oldValue;
     149  }
     150
     151  /**
     152   * Set the propagation ID.  This is a way for the event to be passed from
     153   * hand to hand and retain a little extra state.  Right now it is unused,
     154   * but it should be propagated anyway so that future versions of JavaBeans
     155   * can use it, for God knows what.
     156   *
     157   * @param propagationId the propagation ID
     158   * @see #getPropagationId()
     159   */
     160  public void setPropagationId(Object propagationId)
     161  {
     162    this.propagationId = propagationId;
     163  }
     164
     165  /**
     166   * Get the propagation ID. Right now, it is not used for anything.
     167   *
     168   * @return the propagation ID
     169   * @see #setPropagationId(Object)
     170   */
     171  public Object getPropagationId()
     172  {
     173    return propagationId;
     174  }
     175
     176  /**
     177   * Utility method to rollback a change.
     178   *
     179   * @param event the event to rollback
     180   * @return a new event with old and new swapped
     181   */
     182  PropertyChangeEvent rollback()
     183  {
     184    PropertyChangeEvent result
     185      = new PropertyChangeEvent(source, propertyName, newValue, oldValue);
     186    result.propagationId = propagationId;
     187    return result;
     188  }
     189} // class PropertyChangeEvent
  • branches/GNU/src/gcc/libjava/java/beans/PropertyChangeListener.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    1 /* java.beans.PropertyChangeListener
    2    Copyright (C) 1998, 2000 Free Software Foundation, Inc.
     1/*
     2   Copyright (C) 1998, 2000 Free Software Foundation, Inc.
    33
    44This file is part of GNU Classpath.
     
    88the Free Software Foundation; either version 2, or (at your option)
    99any later version.
    10  
     10
    1111GNU Classpath is distributed in the hope that it will be useful, but
    1212WITHOUT ANY WARRANTY; without even the implied warranty of
     
    4242
    4343/**
    44  ** PropertyChangeListener allows a class to monitor
    45  ** properties of a Bean for changes.<P>
    46  **
    47  ** A propertyChange() event will only be fired
    48  ** <EM>after</EM> the property has changed.
    49  **
    50  ** @author John Keiser
    51  ** @since JDK1.1
    52  ** @version 1.1.0, 29 Jul 1998
    53  ** @see java.beans.PropertyChangeSupport
    54  **/
    55 
     44 * PropertyChangeListener allows a class to monitor properties of a Bean for
     45 * changes. A propertyChange() event will only be fired <em>after</em> the
     46 * property has changed.
     47 *
     48 * @author John Keiser
     49 * @see PropertyChangeSupport
     50 * @since 1.1
     51 * @status updated to 1.4
     52 */
    5653public interface PropertyChangeListener extends EventListener
    5754{
    58   /** Fired after a Bean's property has changed.
    59    ** @param e the change (containing the old and new values)
    60    **/
    61   public abstract void propertyChange(PropertyChangeEvent e);
    62 }
     55  /**
     56   * Fired after a Bean's property has changed.
     57   *
     58   * @param e the change (containing the old and new values)
     59   */
     60  void propertyChange(PropertyChangeEvent e);
     61} // interface PropertyChangeListener
  • branches/GNU/src/gcc/libjava/java/beans/PropertyChangeSupport.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    1 /* java.beans.PropertyChangeSupport
    2    Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
     1/*
     2   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
    33
    44This file is part of GNU Classpath.
     
    88the Free Software Foundation; either version 2, or (at your option)
    99any later version.
    10  
     10
    1111GNU Classpath is distributed in the hope that it will be useful, but
    1212WITHOUT ANY WARRANTY; without even the implied warranty of
     
    3838
    3939package java.beans;
    40 import java.util.Hashtable;
    41 import java.util.Vector;
    42 import java.util.Enumeration;
     40
     41import java.io.IOException;
    4342import java.io.ObjectInputStream;
    4443import java.io.ObjectOutputStream;
    45 import java.io.IOException;
    4644import java.io.Serializable;
     45
     46
     47
     48
     49
     50
    4751
    4852/**
    49  ** PropertyChangeSupport makes it easy to fire property
    50  ** change events and handle listeners.
    51  **
    52  ** @author John Keiser
    53  ** @since JDK1.1
    54  ** @version 1.2.0, 15 Mar 1999
    55  **/
    56 
    57 public class PropertyChangeSupport implements java.io.Serializable {
    58         transient Hashtable propertyListeners = new Hashtable();
    59         transient Vector listeners = new Vector();
    60         Hashtable children;
    61         Object source;
    62         int propertyChangeSupportSerializedDataVersion = 2;
    63         private static final long serialVersionUID = 6401253773779951803L;
    64 
    65         /**
    66          * Saves the state of the object to the stream. */
    67         private void writeObject(ObjectOutputStream stream) throws IOException {
    68                 children = propertyListeners.isEmpty() ? null : propertyListeners;
    69                 stream.defaultWriteObject();
    70                 for (Enumeration e = listeners.elements(); e.hasMoreElements(); ) {
    71                         PropertyChangeListener l = (PropertyChangeListener)e.nextElement();
    72                         if (l instanceof Serializable)
    73                           stream.writeObject(l);
    74                 }
    75                 stream.writeObject(null);
    76         }
    77 
    78         /**
    79          * Reads the object back from stream (deserialization).
    80          */
    81         private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
    82                 stream.defaultReadObject();
    83                 propertyListeners = (children == null) ? new Hashtable() : children;
    84                 PropertyChangeListener l;
    85                 while ((l = (PropertyChangeListener)stream.readObject()) != null) {
    86                         addPropertyChangeListener(l);
    87                 }
    88                 // FIXME: XXX: There is no spec for JDK 1.1 serialization
    89                 // so it is unclear what to do if the value of
    90                 // propertyChangeSupportSerializedDataVersion is 1.
    91         }
    92 
    93         /** Create PropertyChangeSupport to work with a specific
    94          ** source bean.
    95          ** @param source the source bean to use.
    96          **/
    97         public PropertyChangeSupport(Object source) {
    98                 this.source = source;
    99         }
    100 
    101         /** Adds a PropertyChangeListener to the list of listeners.
    102          ** All property change events will be sent to this listener.
    103          ** <P>
    104          **
    105          ** The listener add is not unique: that is, <em>n</em> adds with
    106          ** the same listener will result in <em>n</em> events being sent
    107          ** to that listener for every property change.
    108          ** <P>
    109          **
    110          ** Adding a null listener will cause undefined behavior.
    111          **
    112          ** @param l the listener to add.
    113          **/
    114         public void addPropertyChangeListener(PropertyChangeListener l) {
    115                 listeners.addElement(l);
    116         }
    117 
    118         /** Adds a PropertyChangeListener listening on the specified property.
    119          ** Events will be sent to the listener for that particular property.
    120          ** <P>
    121          **
    122          ** The listener add is not unique; that is, <em>n</em> adds on a
    123          ** particular property for a particular listener will result in
    124          ** <em>n</em> events being sent to that listener when that
    125          ** property is changed.
    126          ** <P>
    127          **
    128          ** The effect is cumulative, too; if you are registered to listen
    129          ** to receive events on all property changes, and then you
    130          ** register on a particular property, you will receive change
    131          ** events for that property twice.
    132          ** <P>
    133          **
    134          ** Adding a null listener will cause undefined behavior.
    135          **
    136          ** @param propertyName the name of the property to listen on.
    137          ** @param l the listener to add.
    138          **/
    139         public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
    140                 synchronized(propertyListeners) {
    141                         Vector v = (Vector)propertyListeners.get(propertyName);
    142                         try {
    143                                 v.addElement(l);
    144                         } catch(NullPointerException e) {
    145                                 /* If v is not found, create a new vector. */
    146                                 v = new Vector();
    147                                 v.addElement(l);
    148                                 propertyListeners.put(propertyName, v);
    149                         }
    150                 }
    151         }
    152 
    153         /** Removes a PropertyChangeListener from the list of listeners.
    154          ** If any specific properties are being listened on, they must
    155          ** be deregistered by themselves; this will only remove the
    156          ** general listener to all properties.
    157          ** <P>
    158          **
    159          ** If <code>add()</code> has been called multiple times for a
    160          ** particular listener, <code>remove()</code> will have to be
    161          ** called the same number of times to deregister it.
    162          **
    163          ** @param l the listener to remove.
    164          **/
    165         public void removePropertyChangeListener(PropertyChangeListener l) {
    166                 listeners.removeElement(l);
    167         }
    168 
    169         /** Removes a PropertyChangeListener from listening to a specific property.
    170          ** <P>
    171          **
    172          ** If <code>add()</code> has been called multiple times for a
    173          ** particular listener on a property, <code>remove()</code> will
    174          ** have to be called the same number of times to deregister it.
    175          **
    176          ** @param propertyName the property to stop listening on.
    177          ** @param l the listener to remove.
    178          **/
    179         public void removePropertyChangeListener(String propertyName, PropertyChangeListener l) {
    180                 synchronized(propertyListeners) {
    181                         Vector v = (Vector)propertyListeners.get(propertyName);
    182                         try {
    183                                 v.removeElement(l);
    184                                 if(v.size() == 0) {
    185                                         propertyListeners.remove(propertyName);
    186                                 }
    187                         } catch(NullPointerException e) {
    188                                 /* if v is not found, do nothing. */
    189                         }
    190                 }
    191         }
    192 
    193         /** Fire a PropertyChangeEvent to all the listeners.
    194          **
    195          ** @param event the event to fire.
    196          **/
    197         public void firePropertyChange(PropertyChangeEvent event) {
    198                 for(int i=0;i<listeners.size();i++) {
    199                         ((PropertyChangeListener)listeners.elementAt(i)).propertyChange(event);
    200                 }
    201                 Vector moreListeners = (Vector)propertyListeners.get(event.getPropertyName());
    202                 if(moreListeners != null) {
    203                         for(int i=0;i<moreListeners.size();i++) {
    204                                 ((PropertyChangeListener)moreListeners.elementAt(i)).propertyChange(event);
    205                         }
    206                 }
    207         }
    208 
    209         /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners.
    210          **
    211          ** @param propertyName the name of the property that changed.
    212          ** @param oldVal the old value.
    213          ** @param newVal the new value.
    214          **/
    215         public void firePropertyChange(String propertyName, Object oldVal, Object newVal) {
    216                 firePropertyChange(new PropertyChangeEvent(source,propertyName,oldVal,newVal));
    217         }
    218 
    219         /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners.
    220          **
    221          ** @param propertyName the name of the property that changed.
    222          ** @param oldVal the old value.
    223          ** @param newVal the new value.
    224          **/
    225         public void firePropertyChange(String propertyName, boolean oldVal, boolean newVal) {
    226                 firePropertyChange(new PropertyChangeEvent(source, propertyName, new Boolean(oldVal), new Boolean(newVal)));
    227         }
    228 
    229         /** Fire a PropertyChangeEvent containing the old and new values of the property to all the listeners.
    230          **
    231          ** @param propertyName the name of the property that changed.
    232          ** @param oldVal the old value.
    233          ** @param newVal the new value.
    234          **/
    235         public void firePropertyChange(String propertyName, int oldVal, int newVal) {
    236                 firePropertyChange(new PropertyChangeEvent(source, propertyName, new Integer(oldVal), new Integer(newVal)));
    237         }
    238 
    239         /** Tell whether the specified property is being listened on or not.
    240          ** This will only return <code>true</code> if there are listeners
    241          ** on all properties or if there is a listener specifically on this
    242          ** property.
    243          **
    244          ** @param propertyName the property that may be listened on
    245          ** @return whether the property is being listened on
    246          **/
    247          public boolean hasListeners(String propertyName) {
    248                 return listeners.size() > 0  || propertyListeners.get(propertyName) != null;
    249          }
    250 }
     53 * PropertyChangeSupport makes it easy to fire property change events and
     54 * handle listeners. It allows chaining of listeners, as well as filtering
     55 * by property name. In addition, it will serialize only those listeners
     56 * which are serializable, ignoring the others without problem. This class
     57 * is thread-safe.
     58 *
     59 * @author John Keiser
     60 * @author Eric Blake <[email protected]>
     61 * @since 1.1
     62 * @status updated to 1.4
     63 */
     64public class PropertyChangeSupport implements Serializable
     65{
     66  /**
     67   * Compatible with JDK 1.1+.
     68   */
     69  private static final long serialVersionUID = 6401253773779951803L;
     70
     71  /**
     72   * Maps property names (String) to named listeners (PropertyChangeSupport).
     73   * If this is a child instance, this field will be null.
     74   *
     75   * @serial the map of property names to named listener managers
     76   * @since 1.2
     77   */
     78  private Hashtable children;
     79
     80  /**
     81   * The non-null source object for any generated events.
     82   *
     83   * @serial the event source
     84   */
     85  private final Object source;
     86
     87  /**
     88   * A field to compare serialization versions - this class uses version 2.
     89   *
     90   * @serial the serialization format
     91   */
     92  private final int propertyChangeSupportSerializedDataVersion = 2;
     93
     94  /**
     95   * The list of all registered property listeners. If this instance was
     96   * created by user code, this only holds the global listeners (ie. not tied
     97   * to a name), and may be null. If it was created by this class, as a
     98   * helper for named properties, then this vector will be non-null, and this
     99   * instance appears as a value in the <code>children</code> hashtable of
     100   * another instance, so that the listeners are tied to the key of that
     101   * hashtable entry.
     102   */
     103  private transient Vector listeners;
     104
     105  /**
     106   * Create a PropertyChangeSupport to work with a specific source bean.
     107   *
     108   * @param source the source bean to use
     109   * @throws NullPointerException if source is null
     110   */
     111  public PropertyChangeSupport(Object source)
     112  {
     113    this.source = source;
     114    if (source == null)
     115      throw new NullPointerException();
     116  }
     117
     118  /**
     119   * Adds a PropertyChangeListener to the list of global listeners. All
     120   * property change events will be sent to this listener. The listener add
     121   * is not unique: that is, <em>n</em> adds with the same listener will
     122   * result in <em>n</em> events being sent to that listener for every
     123   * property change. Adding a null listener may cause a NullPointerException
     124   * down the road. This method will unwrap a PropertyChangeListenerProxy,
     125   * registering the underlying delegate to the named property list.
     126   *
     127   * @param l the listener to add
     128   */
     129  public synchronized void addPropertyChangeListener(PropertyChangeListener l)
     130  {
     131    if (l instanceof PropertyChangeListenerProxy)
     132      {
     133        PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
     134        addPropertyChangeListener(p.propertyName,
     135                                  (PropertyChangeListener) p.getListener());
     136      }
     137    else
     138      {
     139        if (listeners == null)
     140          listeners = new Vector();
     141        listeners.add(l);
     142      }
     143  }
     144
     145  /**
     146   * Removes a PropertyChangeListener from the list of global listeners. If
     147   * any specific properties are being listened on, they must be deregistered
     148   * by themselves; this will only remove the general listener to all
     149   * properties. If <code>add()</code> has been called multiple times for a
     150   * particular listener, <code>remove()</code> will have to be called the
     151   * same number of times to deregister it. This method will unwrap a
     152   * PropertyChangeListenerProxy, removing the underlying delegate from the
     153   * named property list.
     154   *
     155   * @param l the listener to remove
     156   */
     157  public synchronized void
     158    removePropertyChangeListener(PropertyChangeListener l)
     159  {
     160    if (l instanceof PropertyChangeListenerProxy)
     161      {
     162        PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
     163        removePropertyChangeListener(p.propertyName,
     164                                     (PropertyChangeListener) p.getListener());
     165      }
     166    else if (listeners != null)
     167      {
     168        listeners.remove(l);
     169        if (listeners.isEmpty())
     170          listeners = null;
     171      }
     172  }
     173
     174  /**
     175   * Returns an array of all registered property change listeners. Those that
     176   * were registered under a name will be wrapped in a
     177   * <code>PropertyChangeListenerProxy</code>, so you must check whether the
     178   * listener is an instance of the proxy class in order to see what name the
     179   * real listener is registered under. If there are no registered listeners,
     180   * this returns an empty array.
     181   *
     182   * @return the array of registered listeners
     183   * @see PropertyChangeListenerProxy
     184   * @since 1.4
     185   */
     186  public synchronized PropertyChangeListener[] getPropertyChangeListeners()
     187  {
     188    ArrayList list = new ArrayList();
     189    if (listeners != null)
     190      list.addAll(listeners);
     191    if (children != null)
     192      {
     193        int i = children.size();
     194        Iterator iter = children.entrySet().iterator();
     195        while (--i >= 0)
     196          {
     197            Entry e = (Entry) iter.next();
     198            String name = (String) e.getKey();
     199            Vector v = ((PropertyChangeSupport) e.getValue()).listeners;
     200            int j = v.size();
     201            while (--j >= 0)
     202              list.add(new PropertyChangeListenerProxy
     203                (name, (PropertyChangeListener) v.get(j)));
     204          }
     205      }
     206    return (PropertyChangeListener[])
     207      list.toArray(new PropertyChangeListener[list.size()]);
     208  }
     209
     210  /**
     211   * Adds a PropertyChangeListener listening on the specified property. Events
     212   * will be sent to the listener only if the property name matches. The
     213   * listener add is not unique; that is, <em>n</em> adds on a particular
     214   * property for a particular listener will result in <em>n</em> events
     215   * being sent to that listener when that property is changed. The effect is
     216   * cumulative, too; if you are registered to listen to receive events on
     217   * all property changes, and then you register on a particular property,
     218   * you will receive change events for that property twice. Adding a null
     219   * listener may cause a NullPointerException down the road. This method
     220   * will unwrap a PropertyChangeListenerProxy, registering the underlying
     221   * delegate to the named property list if the names match, and discarding
     222   * it otherwise.
     223   *
     224   * @param propertyName the name of the property to listen on
     225   * @param l the listener to add
     226   * @throws NullPointerException if propertyName is null
     227   */
     228  public synchronized void addPropertyChangeListener(String propertyName,
     229                                                     PropertyChangeListener l)
     230  {
     231    while (l instanceof PropertyChangeListenerProxy)
     232      {
     233        PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
     234        if (propertyName == null ? p.propertyName != null
     235            : ! propertyName.equals(p.propertyName))
     236          return;
     237        l = (PropertyChangeListener) p.getListener();
     238      }
     239    PropertyChangeSupport s = null;
     240    if (children == null)
     241      children = new Hashtable();
     242    else
     243      s = (PropertyChangeSupport) children.get(propertyName);
     244    if (s == null)
     245      {
     246        s = new PropertyChangeSupport(source);
     247        s.listeners = new Vector();
     248        children.put(propertyName, s);
     249      }
     250    s.listeners.add(l);
     251  }
     252
     253  /**
     254   * Removes a PropertyChangeListener from listening to a specific property.
     255   * If <code>add()</code> has been called multiple times for a particular
     256   * listener on a property, <code>remove()</code> will have to be called the
     257   * same number of times to deregister it. This method will unwrap a
     258   * PropertyChangeListenerProxy, removing the underlying delegate from the
     259   * named property list if the names match.
     260   *
     261   * @param propertyName the property to stop listening on
     262   * @param l the listener to remove
     263   * @throws NullPointerException if propertyName is null
     264   */
     265  public synchronized void
     266    removePropertyChangeListener(String propertyName, PropertyChangeListener l)
     267  {
     268    if (children == null)
     269      return;
     270    PropertyChangeSupport s
     271      = (PropertyChangeSupport) children.get(propertyName);
     272    if (s == null)
     273      return;
     274    while (l instanceof PropertyChangeListenerProxy)
     275      {
     276        PropertyChangeListenerProxy p = (PropertyChangeListenerProxy) l;
     277        if (propertyName == null ? p.propertyName != null
     278            : ! propertyName.equals(p.propertyName))
     279          return;
     280        l = (PropertyChangeListener) p.getListener();
     281      }
     282    s.listeners.remove(l);
     283    if (s.listeners.isEmpty())
     284      {
     285        children.remove(propertyName);
     286        if (children.isEmpty())
     287          children = null;
     288      }
     289  }
     290
     291  /**
     292   * Returns an array of all property change listeners registered under the
     293   * given property name. If there are no registered listeners, this returns
     294   * an empty array.
     295   *
     296   * @return the array of registered listeners
     297   * @throws NullPointerException if propertyName is null
     298   * @since 1.4
     299   */
     300  public synchronized PropertyChangeListener[]
     301    getPropertyChangeListeners(String propertyName)
     302  {
     303    if (children == null)
     304      return new PropertyChangeListener[0];
     305    PropertyChangeSupport s
     306      = (PropertyChangeSupport) children.get(propertyName);
     307    if (s == null)
     308      return new PropertyChangeListener[0];
     309    return (PropertyChangeListener[])
     310      s.listeners.toArray(new PropertyChangeListener[s.listeners.size()]);
     311  }
     312
     313  /**
     314   * Fire a PropertyChangeEvent containing the old and new values of the
     315   * property to all the global listeners, and to all the listeners for the
     316   * specified property name. This does nothing if old and new are non-null
     317   * and equal.
     318   *
     319   * @param propertyName the name of the property that changed
     320   * @param oldVal the old value
     321   * @param newVal the new value
     322   */
     323  public void firePropertyChange(String propertyName,
     324                                 Object oldVal, Object newVal)
     325  {
     326    firePropertyChange(new PropertyChangeEvent(source, propertyName,
     327                                               oldVal, newVal));
     328  }
     329
     330  /**
     331   * Fire a PropertyChangeEvent containing the old and new values of the
     332   * property to all the global listeners, and to all the listeners for the
     333   * specified property name. This does nothing if old and new are equal.
     334   *
     335   * @param propertyName the name of the property that changed
     336   * @param oldVal the old value
     337   * @param newVal the new value
     338   */
     339  public void firePropertyChange(String propertyName, int oldVal, int newVal)
     340  {
     341    if (oldVal != newVal)
     342      firePropertyChange(new PropertyChangeEvent(source, propertyName,
     343                                                 new Integer(oldVal),
     344                                                 new Integer(newVal)));
     345  }
     346
     347  /**
     348   * Fire a PropertyChangeEvent containing the old and new values of the
     349   * property to all the global listeners, and to all the listeners for the
     350   * specified property name. This does nothing if old and new are equal.
     351   *
     352   * @param propertyName the name of the property that changed
     353   * @param oldVal the old value
     354   * @param newVal the new value
     355   */
     356  public void firePropertyChange(String propertyName,
     357                                 boolean oldVal, boolean newVal)
     358  {
     359    if (oldVal != newVal)
     360      firePropertyChange(new PropertyChangeEvent(source, propertyName,
     361                                                 Boolean.valueOf(oldVal),
     362                                                 Boolean.valueOf(newVal)));
     363  }
     364
     365  /**
     366   * Fire a PropertyChangeEvent to all the global listeners, and to all the
     367   * listeners for the specified property name. This does nothing if old and
     368   * new values of the event are equal.
     369   *
     370   * @param event the event to fire
     371   * @throws NullPointerException if event is null
     372   */
     373  public void firePropertyChange(PropertyChangeEvent event)
     374  {
     375    if (event.oldValue != null && event.oldValue.equals(event.newValue))
     376      return;
     377    Vector v = listeners; // Be thread-safe.
     378    if (v != null)
     379      {
     380        int i = v.size();
     381        while (--i >= 0)
     382          ((PropertyChangeListener) v.get(i)).propertyChange(event);
     383      }
     384    Hashtable h = children; // Be thread-safe.
     385    if (h != null && event.propertyName != null)
     386      {
     387        PropertyChangeSupport s
     388          = (PropertyChangeSupport) h.get(event.propertyName);
     389        if (s != null)
     390          {
     391            v = s.listeners; // Be thread-safe.
     392            int i = v == null ? 0 : v.size();
     393            while (--i >= 0)
     394              ((PropertyChangeListener) v.get(i)).propertyChange(event);
     395          }
     396      }
     397  }
     398
     399  /**
     400   * Tell whether the specified property is being listened on or not. This
     401   * will only return <code>true</code> if there are listeners on all
     402   * properties or if there is a listener specifically on this property.
     403   *
     404   * @param propertyName the property that may be listened on
     405   * @return whether the property is being listened on
     406   * @throws NullPointerException if propertyName is null
     407   */
     408  public synchronized boolean hasListeners(String propertyName)
     409  {
     410    return listeners != null || (children != null
     411                                 && children.get(propertyName) != null);
     412  }
     413
     414  /**
     415   * Saves the state of the object to the stream.
     416   *
     417   * @param s the stream to write to
     418   * @throws IOException if anything goes wrong
     419   * @serialData this writes out a null-terminated list of serializable
     420   *             global property change listeners (the listeners for a named
     421   *             property are written out as the global listeners of the
     422   *             children, when the children hashtable is saved)
     423   */
     424  private synchronized void writeObject(ObjectOutputStream s)
     425    throws IOException
     426  {
     427    s.defaultWriteObject();
     428    if (listeners != null)
     429      {
     430        int i = listeners.size();
     431        while (--i >= 0)
     432          if (listeners.get(i) instanceof Serializable)
     433            s.writeObject(listeners.get(i));
     434      }
     435    s.writeObject(null);
     436  }
     437
     438  /**
     439   * Reads the object back from stream (deserialization).
     440   *
     441   * XXX Since serialization for 1.1 streams was not documented, this may
     442   * not work if propertyChangeSupportSerializedDataVersion is 1.
     443   *
     444   * @param s the stream to read from
     445   * @throws IOException if reading the stream fails
     446   * @throws ClassNotFoundException if deserialization fails
     447   * @serialData this reads in a null-terminated list of serializable
     448   *             global property change listeners (the listeners for a named
     449   *             property are written out as the global listeners of the
     450   *             children, when the children hashtable is saved)
     451   */
     452  private void readObject(ObjectInputStream s)
     453    throws IOException, ClassNotFoundException
     454  {
     455    s.defaultReadObject();
     456    PropertyChangeListener l = (PropertyChangeListener) s.readObject();
     457    while (l != null)
     458      {
     459        addPropertyChangeListener(l);
     460        l = (PropertyChangeListener) s.readObject();
     461      }
     462    // Sun is not as careful with children as we are, and lets some proxys
     463    // in that can never receive events. So, we clean up anything that got
     464    // serialized, to make sure our invariants hold.
     465    if (children != null)
     466      {
     467        int i = children.size();
     468        Iterator iter = children.entrySet().iterator();
     469        while (--i >= 0)
     470          {
     471            Entry e = (Entry) iter.next();
     472            String name = (String) e.getKey();
     473            PropertyChangeSupport pcs = (PropertyChangeSupport) e.getValue();
     474            if (pcs.listeners == null)
     475              pcs.listeners = new Vector();
     476            if (pcs.children != null)
     477              pcs.listeners.addAll
     478                (Arrays.asList(pcs.getPropertyChangeListeners(name)));
     479            if (pcs.listeners.size() == 0)
     480              iter.remove();
     481            else
     482              pcs.children = null;
     483          }
     484        if (children.size() == 0)
     485          children = null;
     486      }
     487  }
     488} // class PropertyChangeSupport
  • branches/GNU/src/gcc/libjava/java/beans/PropertyDescriptor.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    6666
    6767public class PropertyDescriptor extends FeatureDescriptor {
    68         Class propertyType;
    69         Method getMethod;
    70         Method setMethod;
    71 
    72         Class propertyEditorClass;
    73         boolean bound;
    74         boolean constrained;
    75 
    76         PropertyDescriptor(String name) {
    77                 setName(name);
    78         }
    79 
    80         /** Create a new PropertyDescriptor by introspection.
    81          ** This form of constructor creates the PropertyDescriptor by
    82          ** looking for a getter method named <CODE>get&lt;name&gt;()</CODE>
    83          ** (or, optionally, if the property is boolean,
    84          ** <CODE>is&lt;name&gt;()</CODE>) and
    85          ** <CODE>set&lt;name&gt;()</CODE> in class
    86          ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
    87          ** first letter capitalized by the constructor.<P>
    88          **
    89          ** <B>Implementation note:</B> If there is a get method (or
    90          ** boolean isXXX() method), then the return type of that method
    91          ** is used to find the set method.  If there is no get method,
    92          ** then the set method is searched for exhaustively.<P>
    93          **
    94          ** <B>Spec note:</B>
    95          ** If there is no get method and multiple set methods with
    96          ** the same name and a single parameter (different type of course),
    97          ** then an IntrospectionException is thrown.  While Sun's spec
    98          ** does not state this, it can make Bean behavior different on
    99          ** different systems (since method order is not guaranteed) and as
    100          ** such, can be treated as a bug in the spec.  I am not aware of
    101          ** whether Sun's implementation catches this.
    102          **
    103          ** @param name the programmatic name of the property, usually
    104          **             starting with a lowercase letter (e.g. fooManChu
    105          **             instead of FooManChu).
    106          ** @param beanClass the class the get and set methods live in.
    107          ** @exception IntrospectionException if the methods are not found or invalid.
    108          **/
    109         public PropertyDescriptor(String name, Class beanClass) throws IntrospectionException {
    110                 setName(name);
    111                 String capitalized;
    112                 try {
    113                         capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
    114                 } catch(StringIndexOutOfBoundsException e) {
    115                         capitalized = "";
    116                 }
    117                 findMethods(beanClass, "is" + capitalized, "get" + capitalized, "set" + capitalized);
    118         }
    119 
    120         /** Create a new PropertyDescriptor by introspection.
    121          ** This form of constructor allows you to specify the
    122          ** names of the get and set methods to search for.<P>
    123          **
    124          ** <B>Implementation note:</B> If there is a get method (or
    125          ** boolean isXXX() method), then the return type of that method
    126          ** is used to find the set method.  If there is no get method,
    127          ** then the set method is searched for exhaustively.<P>
    128          **
    129          ** <B>Spec note:</B>
    130          ** If there is no get method and multiple set methods with
    131          ** the same name and a single parameter (different type of course),
    132          ** then an IntrospectionException is thrown.  While Sun's spec
    133          ** does not state this, it can make Bean behavior different on
    134          ** different systems (since method order is not guaranteed) and as
    135          ** such, can be treated as a bug in the spec.  I am not aware of
    136          ** whether Sun's implementation catches this.
    137          **
    138          ** @param name the programmatic name of the property, usually
    139          **             starting with a lowercase letter (e.g. fooManChu
    140          **             instead of FooManChu).
    141          ** @param beanClass the class the get and set methods live in.
    142          ** @param getMethodName the name of the get method.
    143          ** @param setMethodName the name of the set method.
    144          ** @exception IntrospectionException if the methods are not found or invalid.
    145          **/
    146         public PropertyDescriptor(String name, Class beanClass, String getMethodName, String setMethodName) throws IntrospectionException {
    147                 setName(name);
    148                 findMethods(beanClass, getMethodName, null, setMethodName);
    149         }
    150 
    151         /** Create a new PropertyDescriptor using explicit Methods.
    152          ** Note that the methods will be checked for conformance to standard
    153          ** Property method rules, as described above at the top of this class.
    154          **
    155          ** @param name the programmatic name of the property, usually
    156          **             starting with a lowercase letter (e.g. fooManChu
    157          **             instead of FooManChu).
    158          ** @param getMethod the get method.
    159          ** @param setMethod the set method.
    160          ** @exception IntrospectionException if the methods are not found or invalid.
    161          **/
    162         public PropertyDescriptor(String name, Method getMethod, Method setMethod) throws IntrospectionException {
    163                 setName(name);
    164                 if(getMethod != null && getMethod.getParameterTypes().length > 0) {
    165                         throw new IntrospectionException("get method has parameters");
    166                 }
    167                 if(setMethod != null && setMethod.getParameterTypes().length != 1) {
    168                         throw new IntrospectionException("set method does not have exactly one parameter");
    169                 }
    170                 if(getMethod != null && setMethod != null) {
    171                         if(!getMethod.getReturnType().equals(setMethod.getParameterTypes()[0])) {
    172                                 throw new IntrospectionException("set and get methods do not share the same type");
    173                         }
    174                         if(!getMethod.getDeclaringClass().isAssignableFrom(setMethod.getDeclaringClass())
    175                            && !setMethod.getDeclaringClass().isAssignableFrom(getMethod.getDeclaringClass())) {
    176                                 throw new IntrospectionException("set and get methods are not in the same class.");
    177                         }
    178                 }
    179                 this.getMethod = getMethod;
    180                 this.setMethod = setMethod;
    181                 if(getMethod != null) {
    182                         this.propertyType = getMethod.getReturnType();
    183                 } else {
    184                         this.propertyType = setMethod.getParameterTypes()[0];
    185                 }
    186         }
    187 
    188         /** Get the property type.
    189          ** This is the type the get method returns and the set method
    190          ** takes in.
    191          **/
    192         public Class getPropertyType() {
    193                 return propertyType;
    194         }
    195 
    196         /** Get the get method.  Why they call it readMethod here and
    197          ** get everywhere else is beyond me.
    198          **/
    199         public Method getReadMethod() {
    200                 return getMethod;
    201         }
    202 
    203         /** Get the set method.  Why they call it writeMethod here and
    204          ** set everywhere else is beyond me.
    205          **/
    206         public Method getWriteMethod() {
    207                 return setMethod;
    208         }
    209 
    210         /** Get whether the property is bound.  Defaults to false. **/
    211         public boolean isBound() {
    212                 return bound;
    213         }
    214 
    215         /** Set whether the property is bound.
    216          ** As long as the the bean implements addPropertyChangeListener() and
    217          ** removePropertyChangeListener(), setBound(true) may safely be called.<P>
    218          ** If these things are not true, then the behavior of the system
    219          ** will be undefined.<P>
    220          **
    221          ** When a property is bound, its set method is required to fire the
    222          ** <CODE>PropertyChangeListener.propertyChange())</CODE> event
    223          ** after the value has changed.
    224          ** @param bound whether the property is bound or not.
    225          **/
    226         public void setBound(boolean bound) {
    227                 this.bound = bound;
    228         }
    229 
    230         /** Get whether the property is constrained.  Defaults to false. **/
    231         public boolean isConstrained() {
    232                 return constrained;
    233         }
    234 
    235         /** Set whether the property is constrained.
    236          ** If the set method throws <CODE>java.beans.PropertyVetoException</CODE>
    237          ** (or subclass thereof) and the bean implements addVetoableChangeListener()
    238          ** and removeVetoableChangeListener(), then setConstrained(true) may safely
    239          ** be called.  Otherwise, the system behavior is undefined.
    240          ** <B>Spec note:</B> given those strict parameters, it would be nice if it
    241          ** got set automatically by detection, but oh well.<P>
    242          ** When a property is constrained, its set method is required to:<P>
    243          ** <OL>
    244          ** <LI>Fire the <CODE>VetoableChangeListener.vetoableChange()</CODE>
    245          **     event notifying others of the change and allowing them a chance to
    246          **     say it is a bad thing.</LI>
    247          ** <LI>If any of the listeners throws a PropertyVetoException, then
    248          **     it must fire another vetoableChange() event notifying the others
    249          **     of a reversion to the old value (though, of course, the change
    250          **     was never made).  Then it rethrows the PropertyVetoException and
    251          **     exits.</LI>
    252          ** <LI>If all has gone well to this point, the value may be changed.</LI>
    253          ** </OL>
    254          ** @param constrained whether the property is constrained or not.
    255          **/
    256         public void setConstrained(boolean constrained) {
    257                 this.constrained = constrained;
    258         }
    259 
    260         /** Get the PropertyEditor class.  Defaults to null. **/
    261         public Class getPropertyEditorClass() {
    262                 return propertyEditorClass;
    263         }
    264 
    265         /** Set the PropertyEditor class.  If the class does not implement
    266          ** the PropertyEditor interface, you will likely get an exception
    267          ** late in the game.
    268          ** @param propertyEditorClass the PropertyEditor class for this class to use.
    269          **/
    270         public void setPropertyEditorClass(Class propertyEditorClass) {
    271                 this.propertyEditorClass = propertyEditorClass;
    272         }
    273 
    274         private void findMethods(Class beanClass, String getMethodName1, String getMethodName2, String setMethodName) throws IntrospectionException {
    275                 try {
    276                         if(getMethodName1 != null) {
    277                                 try {
    278                                         getMethod = beanClass.getMethod(getMethodName1, new Class[0]);
    279                                 } catch(NoSuchMethodException E) {
    280                                 }
    281                                 if(getMethodName2 != null) {
    282                                         if(getMethod != null && !getMethod.getReturnType().equals(java.lang.Boolean.TYPE)) {
    283                                                 // If the is() method exists but isn't boolean, we'll just go on and look for
    284                                                 // an ordinary get() method.
    285                                                 getMethod = null;
    286                                         }
    287 
    288                                         Method getMethod2;
    289                                         try {
    290                                                 getMethod2 = beanClass.getMethod(getMethodName2, new Class[0]);
    291                                         } catch(NoSuchMethodException E) {
    292                                                 getMethod2 = null;
    293                                         }
    294                                         if(getMethod2 != null) {
    295                                                 if(getMethod != null) {
    296                                                         if(!getMethod.getReturnType().equals(getMethod2.getReturnType())) {
    297                                                                 throw new IntrospectionException("Both " + getMethodName1 + " and " + getMethodName2 + " exist, and have contradictory return types.");
    298                                                         }
    299                                                 } else {
    300                                                         getMethod = getMethod2;
    301                                                 }
    302                                         }
    303                                 }
    304                         }
    305 
    306                         if(getMethod != null) {
    307                                 propertyType = getMethod.getReturnType();
    308                                 if(setMethodName != null) {
    309                                         Class[] setArgs = new Class[1];
    310                                         setArgs[0] = propertyType;
    311                                         try {
    312                                                 setMethod = beanClass.getMethod(setMethodName, setArgs);
    313                                                 if(!setMethod.getReturnType().equals(java.lang.Void.TYPE)) {
    314                                                         throw new IntrospectionException(setMethodName + " has non-void return type");
    315                                                 }
    316                                         } catch(NoSuchMethodException E) {
    317                                         }
    318                                 }
    319                         } else if(setMethodName != null) {
    320                                 Method[] m = beanClass.getMethods();
    321                                 for(int i=0;i<m.length;i++) {
    322                                         Method current = m[i];
    323                                         if(current.getName().equals(setMethodName)
    324                                            && current.getParameterTypes().length == 1
    325                                            && current.getReturnType().equals(java.lang.Void.TYPE)) {
    326                                                 if(setMethod != null) {
    327                                                         throw new IntrospectionException("Multiple, different set methods found that fit the bill!");
    328                                                 } else {
    329                                                         setMethod = current;
    330                                                         propertyType = current.getParameterTypes()[0];
    331                                                 }
    332                                         }
    333                                 }
    334                                 if(setMethod == null) {
    335                                         throw new IntrospectionException("Cannot find get or set methods.");
    336                                 }
    337                         } else {
    338                                 throw new IntrospectionException("Cannot find get or set methods.");
    339                         }
    340                 } catch(SecurityException E) {
    341                         throw new IntrospectionException("SecurityException thrown on attempt to access methods.");
    342                 }
    343         }
     68  Class propertyType;
     69  Method getMethod;
     70  Method setMethod;
     71 
     72  Class propertyEditorClass;
     73  boolean bound;
     74  boolean constrained;
     75 
     76  PropertyDescriptor(String name) {
     77    setName(name);
     78  }
     79 
     80  /** Create a new PropertyDescriptor by introspection.
     81   ** This form of constructor creates the PropertyDescriptor by
     82   ** looking for a getter method named <CODE>get&lt;name&gt;()</CODE>
     83   ** (or, optionally, if the property is boolean,
     84   ** <CODE>is&lt;name&gt;()</CODE>) and
     85   ** <CODE>set&lt;name&gt;()</CODE> in class
     86   ** <CODE>&lt;beanClass&gt;</CODE>, where &lt;name&gt; has its
     87   ** first letter capitalized by the constructor.<P>
     88   **
     89   ** <B>Implementation note:</B> If there is both are both isXXX and
     90   ** getXXX methods, the former is used in preference to the latter.
     91   ** We do not check that an isXXX method returns a boolean. In both
     92   ** cases, this matches the behaviour of JDK 1.4<P>
     93   **
     94   ** @param name the programmatic name of the property, usually
     95   **             starting with a lowercase letter (e.g. fooManChu
     96   **             instead of FooManChu).
     97   ** @param beanClass the class the get and set methods live in.
     98   ** @exception IntrospectionException if the methods are not found
     99   **            or invalid.
     100   **/
     101  public PropertyDescriptor(String name, Class beanClass)
     102    throws IntrospectionException
     103  {
     104    setName(name);
     105    if (name.length() == 0) {
     106      throw new IntrospectionException("empty property name");
     107    }
     108    String caps = Character.toUpperCase(name.charAt(0)) + name.substring(1);
     109    findMethods(beanClass, "is" + caps, "get" + caps, "set" + caps);
     110    if (getMethod == null) {
     111      throw new IntrospectionException("Cannot find an is" + caps +
     112                                       " or get" + caps + " method");
     113    }
     114    if (setMethod == null) {
     115      throw new IntrospectionException("Cannot find a " + caps + " method");
     116    }
     117    checkMethods();
     118  }
     119 
     120  /** Create a new PropertyDescriptor by introspection.
     121   ** This form of constructor allows you to specify the
     122   ** names of the get and set methods to search for.<P>
     123   **
     124   ** <B>Implementation note:</B> If there is a get method (or
     125   ** boolean isXXX() method), then the return type of that method
     126   ** is used to find the set method.  If there is no get method,
     127   ** then the set method is searched for exhaustively.<P>
     128   **
     129   ** <B>Spec note:</B>
     130   ** If there is no get method and multiple set methods with
     131   ** the same name and a single parameter (different type of course),
     132   ** then an IntrospectionException is thrown.  While Sun's spec
     133   ** does not state this, it can make Bean behavior different on
     134   ** different systems (since method order is not guaranteed) and as
     135   ** such, can be treated as a bug in the spec.  I am not aware of
     136   ** whether Sun's implementation catches this.
     137   **
     138   ** @param name the programmatic name of the property, usually
     139   **             starting with a lowercase letter (e.g. fooManChu
     140   **             instead of FooManChu).
     141   ** @param beanClass the class the get and set methods live in.
     142   ** @param getMethodName the name of the get method.
     143   ** @param setMethodName the name of the set method.
     144   ** @exception IntrospectionException if the methods are not found
     145   **            or invalid.
     146   **/
     147  public PropertyDescriptor(String name, Class beanClass,
     148                            String getMethodName, String setMethodName)
     149    throws IntrospectionException
     150  {
     151    setName(name);
     152    findMethods(beanClass, getMethodName, null, setMethodName);
     153    if (getMethod == null && getMethodName != null) {
     154      throw new IntrospectionException("Cannot find a getter method called " +
     155                                       getMethodName);
     156    }
     157    if (setMethod == null && setMethodName != null) {
     158      throw new IntrospectionException("Cannot find a setter method called " +
     159                                       setMethodName);
     160    }
     161    checkMethods();
     162  }
     163 
     164  /** Create a new PropertyDescriptor using explicit Methods.
     165   ** Note that the methods will be checked for conformance to standard
     166   ** Property method rules, as described above at the top of this class.
     167   **
     168   ** @param name the programmatic name of the property, usually
     169   **             starting with a lowercase letter (e.g. fooManChu
     170   **             instead of FooManChu).
     171   ** @param getMethod the get method.
     172   ** @param setMethod the set method.
     173   ** @exception IntrospectionException if the methods are not found
     174   **            or invalid.
     175   **/
     176  public PropertyDescriptor(String name, Method getMethod, Method setMethod)
     177    throws IntrospectionException
     178  {
     179    setName(name);
     180    this.getMethod = getMethod;
     181    this.setMethod = setMethod;
     182    if (getMethod != null) {
     183      this.propertyType = getMethod.getReturnType();
     184    }
     185    else if (setMethod != null) {
     186      this.propertyType = setMethod.getParameterTypes()[0];
     187    }
     188    checkMethods();
     189  }
     190 
     191  /** Get the property type.
     192   ** This is the type the get method returns and the set method
     193   ** takes in.
     194   **/
     195  public Class getPropertyType() {
     196    return propertyType;
     197  }
     198 
     199  /** Get the get method.  Why they call it readMethod here and
     200   ** get everywhere else is beyond me.
     201   **/
     202  public Method getReadMethod() {
     203    return getMethod;
     204  }
     205 
     206  /** Get the set method.  Why they call it writeMethod here and
     207   ** set everywhere else is beyond me.
     208   **/
     209  public Method getWriteMethod() {
     210    return setMethod;
     211  }
     212 
     213  /** Get whether the property is bound.  Defaults to false. **/
     214  public boolean isBound() {
     215    return bound;
     216  }
     217 
     218  /** Set whether the property is bound.
     219   ** As long as the the bean implements addPropertyChangeListener() and
     220   ** removePropertyChangeListener(), setBound(true) may safely be called.<P>
     221   ** If these things are not true, then the behavior of the system
     222   ** will be undefined.<P>
     223   **
     224   ** When a property is bound, its set method is required to fire the
     225   ** <CODE>PropertyChangeListener.propertyChange())</CODE> event
     226   ** after the value has changed.
     227   ** @param bound whether the property is bound or not.
     228   **/
     229  public void setBound(boolean bound) {
     230    this.bound = bound;
     231  }
     232 
     233  /** Get whether the property is constrained.  Defaults to false. **/
     234  public boolean isConstrained() {
     235    return constrained;
     236  }
     237 
     238  /** Set whether the property is constrained.
     239   ** If the set method throws <CODE>java.beans.PropertyVetoException</CODE>
     240   ** (or subclass thereof) and the bean implements addVetoableChangeListener()
     241   ** and removeVetoableChangeListener(), then setConstrained(true) may safely
     242   ** be called.  Otherwise, the system behavior is undefined.
     243   ** <B>Spec note:</B> given those strict parameters, it would be nice if it
     244   ** got set automatically by detection, but oh well.<P>
     245   ** When a property is constrained, its set method is required to:<P>
     246   ** <OL>
     247   ** <LI>Fire the <CODE>VetoableChangeListener.vetoableChange()</CODE>
     248   **     event notifying others of the change and allowing them a chance to
     249   **     say it is a bad thing.</LI>
     250   ** <LI>If any of the listeners throws a PropertyVetoException, then
     251   **     it must fire another vetoableChange() event notifying the others
     252   **     of a reversion to the old value (though, of course, the change
     253   **     was never made).  Then it rethrows the PropertyVetoException and
     254   **     exits.</LI>
     255   ** <LI>If all has gone well to this point, the value may be changed.</LI>
     256   ** </OL>
     257   ** @param constrained whether the property is constrained or not.
     258   **/
     259  public void setConstrained(boolean constrained) {
     260    this.constrained = constrained;
     261  }
     262 
     263  /** Get the PropertyEditor class.  Defaults to null. **/
     264  public Class getPropertyEditorClass() {
     265    return propertyEditorClass;
     266  }
     267 
     268  /** Set the PropertyEditor class.  If the class does not implement
     269   ** the PropertyEditor interface, you will likely get an exception
     270   ** late in the game.
     271   ** @param propertyEditorClass the PropertyEditor class for this
     272   **        class to use.
     273   **/
     274  public void setPropertyEditorClass(Class propertyEditorClass) {
     275    this.propertyEditorClass = propertyEditorClass;
     276  }
     277 
     278  private void findMethods(Class beanClass, String getMethodName1,
     279                           String getMethodName2, String setMethodName)
     280    throws IntrospectionException
     281  {
     282    try {
     283      // Try the first get method name
     284      if (getMethodName1 != null) {
     285        try {
     286          getMethod = beanClass.getMethod(getMethodName1, new Class[0]);
     287        }
     288        catch (NoSuchMethodException e) {
     289        }
     290      }
     291
     292      // Fall back to the second get method name
     293      if (getMethod == null && getMethodName2 != null) {
     294        try {
     295          getMethod = beanClass.getMethod(getMethodName2, new Class[0]);
     296        }
     297        catch (NoSuchMethodException e) {
     298        }
     299      }
     300
     301      // Try the set method name
     302      if (setMethodName != null) {
     303        if (getMethod != null) {
     304          // If there is a get method, use its return type to help
     305          // select the corresponding set method.
     306          Class propertyType = getMethod.getReturnType();
     307          if (propertyType == Void.TYPE) {
     308            String msg = "The property's read method has return type 'void'";
     309            throw new IntrospectionException(msg);
     310          }
     311         
     312          Class[] setArgs = new Class[]{propertyType};
     313          try {
     314            setMethod = beanClass.getMethod(setMethodName, setArgs);
     315          }
     316          catch (NoSuchMethodException e) {
     317          }
     318        }
     319        else if (getMethodName1 == null && getMethodName2 == null) {
     320          // If this is a write-only property, choose the first set method
     321          // with the required name, one parameter and return type 'void'
     322          Method[] methods = beanClass.getMethods();
     323          for (int i = 0; i < methods.length; i++) {
     324            if (methods[i].getName().equals(setMethodName) &&
     325                methods[i].getParameterTypes().length == 1 &&
     326                methods[i].getReturnType() == Void.TYPE) {
     327              setMethod = methods[i];
     328              break;
     329            }
     330          }
     331        }
     332      }
     333    }
     334    catch (SecurityException e) {
     335      // FIXME -- shouldn't we just allow SecurityException to propagate?
     336      String msg = "SecurityException thrown on attempt to access methods.";
     337      throw new IntrospectionException(msg);
     338    }
     339  }
     340
     341  private void checkMethods()
     342    throws IntrospectionException
     343  {
     344    if (getMethod != null) {
     345      if (getMethod.getParameterTypes().length > 0) {
     346        throw new IntrospectionException("get method has parameters");
     347      }
     348      this.propertyType = getMethod.getReturnType();
     349      if (propertyType == Void.TYPE) {
     350        throw new IntrospectionException("get method has void return type");
     351      }
     352    }
     353    if (setMethod != null) {
     354      if (setMethod.getParameterTypes().length != 1) {
     355        String msg = "set method does not have exactly one parameter";
     356        throw new IntrospectionException(msg);
     357      }
     358      if (getMethod == null) {
     359        propertyType = setMethod.getParameterTypes()[0];
     360      }
     361      else {
     362        if (!propertyType.equals(setMethod.getParameterTypes()[0])) {
     363          String msg = "set and get methods do not share the same type";
     364          throw new IntrospectionException(msg);
     365        }
     366        if ((!getMethod.getDeclaringClass().
     367             isAssignableFrom(setMethod.getDeclaringClass())) &&
     368            (!setMethod.getDeclaringClass().
     369             isAssignableFrom(getMethod.getDeclaringClass()))) {
     370          String msg = "set and get methods are not in the same class.";
     371          throw new IntrospectionException(msg);
     372        }
     373      }
     374    }
     375  }
    344376}
  • branches/GNU/src/gcc/libjava/java/beans/VetoableChangeListener.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    1 /* java.beans.VetoableChangeListener
    2    Copyright (C) 1998, 2000 Free Software Foundation, Inc.
     1/*
     2   Copyright (C) 1998, 2000 Free Software Foundation, Inc.
    33
    44This file is part of GNU Classpath.
     
    88the Free Software Foundation; either version 2, or (at your option)
    99any later version.
    10  
     10
    1111GNU Classpath is distributed in the hope that it will be useful, but
    1212WITHOUT ANY WARRANTY; without even the implied warranty of
     
    4242
    4343/**
    44  ** VetoableChangeListener allows a class to monitor
    45  ** proposed changes to properties of a Bean and, if
    46  ** desired, prevent them from occurring.<P>
    47  **
    48  ** A vetoableChange() event will be fired <EM>before</EM>
    49  ** the property has changed.  If any listener rejects the
    50  ** change by throwing the PropertyChangeException, a new
    51  ** vetoableChange() event will be fired to all listeners
    52  ** who received a vetoableChange() event in the first
    53  ** place informing them of a reversion to the old value.
    54  ** The value, of course, never actually changed.<P>
    55  **
    56  ** <STRONG>Note:</STRONG> This class may not be reliably
    57  ** used to determine whether a property has actually
    58  ** changed.  Use the PropertyChangeListener interface
    59  ** for that instead.
    60  **
    61  ** @author John Keiser
    62  ** @version 1.1.0, 29 Jul 1998
    63  ** @since JDK1.1
    64  ** @see java.beans.PropertyChangeListener
    65  ** @see java.beans.VetoableChangeSupport
    66  **/
    67 
     44 * VetoableChangeListener allows a class to monitor proposed changes to
     45 * properties of a Bean and, if desired, prevent them from occurring. A
     46 * vetoableChange() event will be fired <em>after</em> the property change has
     47 * been requested, but before it is permanent. If any listener rejects the
     48 * change by throwing the PropertyChangeException, a new vetoableChange()
     49 * event will be fired to all listeners who received a vetoableChange() event
     50 * in the first place, informing them to revert back to the old value. Thus,
     51 * the listener that threw the exception the first time should be prepared
     52 * to rethrow it the second time. The value, of course, never actually changed.
     53 *
     54 * <p><strong>Note:</strong> This class may not be reliably used to determine
     55 * whether a property has actually changed.  Use the PropertyChangeListener
     56 * interface for that instead.
     57 *
     58 * @author John Keiser
     59 * @see java.beans.PropertyChangeListener
     60 * @see java.beans.VetoableChangeSupport
     61 * @since 1.1
     62 * @status updated to 1.4
     63 */
    6864public interface VetoableChangeListener extends EventListener
    6965{
    70   /** Fired before a Bean's property changes.
    71    ** @param e the change (containing the old and new values)
    72    ** @exception PropertyChangeException if the listener
    73    **            does not desire the change to be made.
    74    **/
    75   public abstract void vetoableChange(PropertyChangeEvent e)
    76     throws PropertyVetoException;
    77 }
     66  /**
     67   *
     68   *
     69   *
     70   *
     71 
     72  throws PropertyVetoException;
     73}
  • branches/GNU/src/gcc/libjava/java/beans/VetoableChangeSupport.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    1 /* java.beans.VetoableChangeSupport
    2    Copyright (C) 1998 Free Software Foundation, Inc.
     1/*
     2   Copyright (C) 1998 Free Software Foundation, Inc.
    33
    44This file is part of GNU Classpath.
     
    88the Free Software Foundation; either version 2, or (at your option)
    99any later version.
    10  
     10
    1111GNU Classpath is distributed in the hope that it will be useful, but
    1212WITHOUT ANY WARRANTY; without even the implied warranty of
     
    3636exception statement from your version. */
    3737
     38
    3839package java.beans;
    39 import java.util.Hashtable;
    40 import java.util.Vector;
    41 import java.util.Enumeration;
     40
     41import java.io.IOException;
    4242import java.io.ObjectInputStream;
    4343import java.io.ObjectOutputStream;
    44 import java.io.IOException;
    4544import java.io.Serializable;
     45
     46
     47
     48
     49
     50
    4651
    4752/**
    48  ** VetoableChangeSupport makes it easy to fire vetoable
    49  ** change events and handle listeners as well as reversion
    50  ** of old values when things go wrong.
    51  **
    52  ** @author John Keiser
    53  ** @since JDK1.1
    54  ** @version 1.2.0, 15 Mar 1998
    55  **/
    56 
    57 public class VetoableChangeSupport implements java.io.Serializable {
    58         transient Hashtable propertyListeners = new Hashtable();
    59         transient Vector listeners = new Vector();
    60         Hashtable children;
    61         Object source;
    62         int vetoableChangeSupportSerializedDataVersion = 2;
    63         private static final long serialVersionUID = -5090210921595982017L;
    64 
    65         /**
    66          * Saves the state of the object to the stream. */
    67         private void writeObject(ObjectOutputStream stream) throws IOException {
    68                 children = propertyListeners.isEmpty() ? null : propertyListeners;
    69                 stream.defaultWriteObject();
    70                 for (Enumeration e = listeners.elements(); e.hasMoreElements(); ) {
    71                         VetoableChangeListener l = (VetoableChangeListener)e.nextElement();
    72                         if (l instanceof Serializable)
    73                           stream.writeObject(l);
    74                 }
    75                 stream.writeObject(null);
    76         }
    77 
    78         /**
    79          * Reads the object back from stream (deserialization).
    80          */
    81         private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
    82                 stream.defaultReadObject();
    83                 propertyListeners = (children == null) ? new Hashtable() : children;
    84                 VetoableChangeListener l;
    85                 while ((l = (VetoableChangeListener)stream.readObject()) != null) {
    86                         addVetoableChangeListener(l);
    87                 }
    88                 // FIXME: XXX: There is no spec for JDK 1.1 serialization
    89                 // so it is unclear what to do if the value of
    90                 // vetoableChangeSupportSerializedDataVersion is 1.
    91         }
    92 
    93 
    94         /** Create VetoableChangeSupport to work with a specific
    95          ** source bean.
    96          ** @param source the source bean to use.
    97          **/
    98         public VetoableChangeSupport(Object source) {
    99                 this.source = source;
    100         }
    101 
    102         /** Adds a VetoableChangeListener to the list of listeners.
    103          ** All property change events will be sent to this listener.
    104          ** <P>
    105          **
    106          ** The listener add is not unique: that is, <em>n</em> adds with
    107          ** the same listener will result in <em>n</em> events being sent
    108          ** to that listener for every property change.
    109          ** <P>
    110          **
    111          ** Adding a null listener will cause undefined behavior.
    112          **
    113          ** @param l the listener to add.
    114          **/
    115         public void addVetoableChangeListener(VetoableChangeListener l) {
    116                 listeners.addElement(l);
    117         }
    118 
    119         /** Adds a VetoableChangeListener listening on the specified property.
    120          ** Events will be sent to the listener for that particular property.
    121          ** <P>
    122          **
    123          ** The listener add is not unique; that is, <em>n</em> adds on a
    124          ** particular property for a particular listener will result in
    125          ** <em>n</em> events being sent to that listener when that
    126          ** property is changed.
    127          ** <P>
    128          **
    129          ** The effect is cumulative, too; if you are registered to listen
    130          ** to receive events on all property changes, and then you
    131          ** register on a particular property, you will receive change
    132          ** events for that property twice.
    133          ** <P>
    134          **
    135          ** Adding a null listener will cause undefined behavior.
    136          **
    137          ** @param propertyName the name of the property to listen on.
    138          ** @param l the listener to add.
    139          **/
    140         public void addVetoableChangeListener(String propertyName, VetoableChangeListener l) {
    141                 synchronized(propertyListeners) {
    142                         Vector v = (Vector)propertyListeners.get(propertyName);
    143                         try {
    144                                 v.addElement(l);
    145                         } catch(NullPointerException e) {
    146                                 /* If v is not found, create a new vector. */
    147                                 v = new Vector();
    148                                 v.addElement(l);
    149                                 propertyListeners.put(propertyName, v);
    150                         }
    151                 }
    152         }
    153 
    154         /** Removes a VetoableChangeListener from the list of listeners.
    155          ** If any specific properties are being listened on, they must
    156          ** be deregistered by themselves; this will only remove the
    157          ** general listener to all properties.
    158          ** <P>
    159          **
    160          ** If <code>add()</code> has been called multiple times for a
    161          ** particular listener, <code>remove()</code> will have to be
    162          ** called the same number of times to deregister it.
    163          **
    164          ** @param l the listener to remove.
    165          **/
    166         public void removeVetoableChangeListener(VetoableChangeListener l) {
    167                 listeners.removeElement(l);
    168         }
    169 
    170         /** Removes a VetoableChangeListener from listening to a specific property.
    171          ** <P>
    172          **
    173          ** If <code>add()</code> has been called multiple times for a
    174          ** particular listener on a property, <code>remove()</code> will
    175          ** have to be called the same number of times to deregister it.
    176          **
    177          ** @param propertyName the property to stop listening on.
    178          ** @param l the listener to remove.
    179          **/
    180         public void removeVetoableChangeListener(String propertyName, VetoableChangeListener l) {
    181                 synchronized(propertyListeners) {
    182                         Vector v = (Vector)propertyListeners.get(propertyName);
    183                         try {
    184                                 v.removeElement(l);
    185                                 if(v.size() == 0) {
    186                                         propertyListeners.remove(propertyName);
    187                                 }
    188                         } catch(NullPointerException e) {
    189                                 /* if v is not found, do nothing. */
    190                         }
    191                 }
    192         }
    193 
    194 
    195         /** Fire a VetoableChangeEvent to all the listeners.
    196          ** If any listener objects, a reversion event will be sent to
    197          ** those listeners who received the initial event.
    198          **
    199          ** @param proposedChange the event to send.
    200          ** @exception PropertyVetoException if the change is vetoed.
    201          **/
    202         public void fireVetoableChange(PropertyChangeEvent proposedChange) throws PropertyVetoException {
    203                 int currentListener=0;
    204                 try {
    205                         for(;currentListener<listeners.size();currentListener++) {
    206                                 ((VetoableChangeListener)listeners.elementAt(currentListener)).vetoableChange(proposedChange);
    207                         }
    208                 } catch(PropertyVetoException e) {
    209                         PropertyChangeEvent reversion = new PropertyChangeEvent(proposedChange.getSource(),proposedChange.getPropertyName(),proposedChange.getNewValue(),proposedChange.getOldValue());
    210                         for(int sendAgain=0;sendAgain<currentListener;sendAgain++) {
    211                                 try {
    212                                         ((VetoableChangeListener)listeners.elementAt(sendAgain)).vetoableChange(reversion);
    213                                 } catch(PropertyVetoException e2) {
    214                                 }
    215                         }
    216                         throw e;
    217                 }
    218 
    219                 Vector moreListeners = (Vector)propertyListeners.get(proposedChange.getPropertyName());
    220                 if(moreListeners != null) {
    221                         try {
    222                                 for(currentListener = 0; currentListener < moreListeners.size(); currentListener++) {
    223                                         ((VetoableChangeListener)moreListeners.elementAt(currentListener)).vetoableChange(proposedChange);
    224                                 }
    225                         } catch(PropertyVetoException e) {
    226                                 PropertyChangeEvent reversion = new PropertyChangeEvent(proposedChange.getSource(),proposedChange.getPropertyName(),proposedChange.getNewValue(),proposedChange.getOldValue());
    227                                 for(int sendAgain=0;sendAgain<listeners.size();sendAgain++) {
    228                                         try {
    229                                                 ((VetoableChangeListener)listeners.elementAt(currentListener)).vetoableChange(proposedChange);
    230                                         } catch(PropertyVetoException e2) {             
    231                                         }
    232                                 }
    233 
    234                                 for(int sendAgain=0;sendAgain<currentListener;sendAgain++) {
    235                                         try {
    236                                                 ((VetoableChangeListener)moreListeners.elementAt(sendAgain)).vetoableChange(reversion);
    237                                         } catch(PropertyVetoException e2) {
    238                                         }
    239                                 }
    240                                 throw e;
    241                         }
    242                 }
    243         }
    244 
    245         /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners.
    246          ** If any listener objects, a reversion event will be sent to
    247          ** those listeners who received the initial event.
    248          **
    249          ** @param propertyName the name of the property that
    250          ** changed.
    251          ** @param oldVal the old value.
    252          ** @param newVal the new value.
    253          ** @exception PropertyVetoException if the change is vetoed.
    254          **/
    255         public void fireVetoableChange(String propertyName, Object oldVal, Object newVal) throws PropertyVetoException {
    256                 fireVetoableChange(new PropertyChangeEvent(source,propertyName,oldVal,newVal));
    257         }
    258 
    259         /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners.
    260          ** If any listener objects, a reversion event will be sent to
    261          ** those listeners who received the initial event.
    262          **
    263          ** @param propertyName the name of the property that
    264          ** changed.
    265          ** @param oldVal the old value.
    266          ** @param newVal the new value.
    267          ** @exception PropertyVetoException if the change is vetoed.
    268          **/
    269         public void fireVetoableChange(String propertyName, boolean oldVal, boolean newVal) throws PropertyVetoException {
    270                 fireVetoableChange(new PropertyChangeEvent(source,propertyName,new Boolean(oldVal),new Boolean(newVal)));
    271         }
    272 
    273         /** Fire a VetoableChangeEvent containing the old and new values of the property to all the listeners.
    274          ** If any listener objects, a reversion event will be sent to
    275          ** those listeners who received the initial event.
    276          **
    277          ** @param propertyName the name of the property that
    278          ** changed.
    279          ** @param oldVal the old value.
    280          ** @param newVal the new value.
    281          ** @exception PropertyVetoException if the change is vetoed.
    282          **/
    283         public void fireVetoableChange(String propertyName, int oldVal, int newVal) throws PropertyVetoException {
    284                 fireVetoableChange(new PropertyChangeEvent(source,propertyName,new Integer(oldVal),new Integer(newVal)));
    285         }
    286 
    287 
    288         /** Tell whether the specified property is being listened on or not.
    289          ** This will only return <code>true</code> if there are listeners
    290          ** on all properties or if there is a listener specifically on this
    291          ** property.
    292          **
    293          ** @param propertyName the property that may be listened on
    294          ** @return whether the property is being listened on
    295          **/
    296         public boolean hasListeners(String propertyName) {
    297                 return listeners.size() > 0  || propertyListeners.get(propertyName) != null;
    298         }
    299 }
     53 * VetoableChangeSupport makes it easy to fire vetoable change events and
     54 * handle listeners. It allows chaining of listeners, as well as filtering
     55 * by property name. In addition, it will serialize only those listeners
     56 * which are serializable, ignoring the others without problem. This class
     57 * is thread-safe.
     58 *
     59 * @author John Keiser
     60 * @author Eric Blake <[email protected]>
     61 * @since 1.1
     62 * @status updated to 1.4
     63 */
     64public class VetoableChangeSupport implements Serializable
     65{
     66  /**
     67   * Compatible with JDK 1.1+.
     68   */
     69  private static final long serialVersionUID = -5090210921595982017L;
     70
     71  /**
     72   * Maps property names (String) to named listeners (VetoableChangeSupport).
     73   * If this is a child instance, this field will be null.
     74   *
     75   * @serial the map of property names to named listener managers
     76   * @since 1.2
     77   */
     78  private Hashtable children;
     79
     80  /**
     81   * The non-null source object for any generated events.
     82   *
     83   * @serial the event source
     84   */
     85  private final Object source;
     86
     87  /**
     88   * A field to compare serialization versions - this class uses version 2.
     89   *
     90   * @serial the serialization format
     91   */
     92  private final int vetoableChangeSupportSerializedDataVersion = 2;
     93
     94  /**
     95   * The list of all registered vetoable listeners. If this instance was
     96   * created by user code, this only holds the global listeners (ie. not tied
     97   * to a name), and may be null. If it was created by this class, as a
     98   * helper for named properties, then this vector will be non-null, and this
     99   * instance appears as a value in the <code>children</code> hashtable of
     100   * another instance, so that the listeners are tied to the key of that
     101   * hashtable entry.
     102   */
     103  private transient Vector listeners;
     104
     105  /**
     106   * Create a VetoableChangeSupport to work with a specific source bean.
     107   *
     108   * @param source the source bean to use
     109   * @throws NullPointerException if source is null
     110   */
     111  public VetoableChangeSupport(Object source)
     112  {
     113    this.source = source;
     114    if (source == null)
     115      throw new NullPointerException();
     116  }
     117
     118  /**
     119   * Adds a VetoableChangeListener to the list of global listeners. All
     120   * vetoable change events will be sent to this listener. The listener add
     121   * is not unique: that is, <em>n</em> adds with the same listener will
     122   * result in <em>n</em> events being sent to that listener for every
     123   * vetoable change. Adding a null listener may cause a NullPointerException
     124   * down the road. This method will unwrap a VetoableChangeListenerProxy,
     125   * registering the underlying delegate to the named property list.
     126   *
     127   * @param l the listener to add
     128   */
     129  public synchronized void addVetoableChangeListener(VetoableChangeListener l)
     130  {
     131    if (l instanceof VetoableChangeListenerProxy)
     132      {
     133        VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
     134        addVetoableChangeListener(p.propertyName,
     135                                  (VetoableChangeListener) p.getListener());
     136      }
     137    else
     138      {
     139        if (listeners == null)
     140          listeners = new Vector();
     141        listeners.add(l);
     142      }
     143  }
     144
     145  /**
     146   * Removes a VetoableChangeListener from the list of global listeners. If
     147   * any specific properties are being listened on, they must be deregistered
     148   * by themselves; this will only remove the general listener to all
     149   * properties. If <code>add()</code> has been called multiple times for a
     150   * particular listener, <code>remove()</code> will have to be called the
     151   * same number of times to deregister it. This method will unwrap a
     152   * VetoableChangeListenerProxy, removing the underlying delegate from the
     153   * named property list.
     154   *
     155   * @param l the listener to remove
     156   */
     157  public synchronized void
     158    removeVetoableChangeListener(VetoableChangeListener l)
     159  {
     160    if (l instanceof VetoableChangeListenerProxy)
     161      {
     162        VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
     163        removeVetoableChangeListener(p.propertyName,
     164                                     (VetoableChangeListener) p.getListener());
     165      }
     166    else if (listeners != null)
     167      {
     168        listeners.remove(l);
     169        if (listeners.isEmpty())
     170          listeners = null;
     171      }
     172  }
     173
     174  /**
     175   * Returns an array of all registered vetoable change listeners. Those that
     176   * were registered under a name will be wrapped in a
     177   * <code>VetoableChangeListenerProxy</code>, so you must check whether the
     178   * listener is an instance of the proxy class in order to see what name the
     179   * real listener is registered under. If there are no registered listeners,
     180   * this returns an empty array.
     181   *
     182   * @return the array of registered listeners
     183   * @see VetoableChangeListenerProxy
     184   * @since 1.4
     185   */
     186  public synchronized VetoableChangeListener[] getVetoableChangeListeners()
     187  {
     188    ArrayList list = new ArrayList();
     189    if (listeners != null)
     190      list.addAll(listeners);
     191    if (children != null)
     192      {
     193        int i = children.size();
     194        Iterator iter = children.entrySet().iterator();
     195        while (--i >= 0)
     196          {
     197            Entry e = (Entry) iter.next();
     198            String name = (String) e.getKey();
     199            Vector v = ((VetoableChangeSupport) e.getValue()).listeners;
     200            int j = v.size();
     201            while (--j >= 0)
     202              list.add(new VetoableChangeListenerProxy
     203                (name, (VetoableChangeListener) v.get(j)));
     204          }
     205      }
     206    return (VetoableChangeListener[])
     207      list.toArray(new VetoableChangeListener[list.size()]);
     208  }
     209
     210  /**
     211   * Adds a VetoableChangeListener listening on the specified property. Events
     212   * will be sent to the listener only if the property name matches. The
     213   * listener add is not unique; that is, <em>n</em> adds on a particular
     214   * property for a particular listener will result in <em>n</em> events
     215   * being sent to that listener when that property is changed. The effect is
     216   * cumulative, too; if you are registered to listen to receive events on
     217   * all vetoable changes, and then you register on a particular property,
     218   * you will receive change events for that property twice. Adding a null
     219   * listener may cause a NullPointerException down the road. This method
     220   * will unwrap a VetoableChangeListenerProxy, registering the underlying
     221   * delegate to the named property list if the names match, and discarding
     222   * it otherwise.
     223   *
     224   * @param propertyName the name of the property to listen on
     225   * @param l the listener to add
     226   * @throws NullPointerException if propertyName is null
     227   */
     228  public synchronized void addVetoableChangeListener(String propertyName,
     229                                                     VetoableChangeListener l)
     230  {
     231    while (l instanceof VetoableChangeListenerProxy)
     232      {
     233        VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
     234        if (propertyName == null ? p.propertyName != null
     235            : ! propertyName.equals(p.propertyName))
     236          return;
     237        l = (VetoableChangeListener) p.getListener();
     238      }
     239    VetoableChangeSupport s = null;
     240    if (children == null)
     241      children = new Hashtable();
     242    else
     243      s = (VetoableChangeSupport) children.get(propertyName);
     244    if (s == null)
     245      {
     246        s = new VetoableChangeSupport(source);
     247        s.listeners = new Vector();
     248        children.put(propertyName, s);
     249      }
     250    s.listeners.add(l);
     251  }
     252
     253  /**
     254   * Removes a VetoableChangeListener from listening to a specific property.
     255   * If <code>add()</code> has been called multiple times for a particular
     256   * listener on a property, <code>remove()</code> will have to be called the
     257   * same number of times to deregister it. This method will unwrap a
     258   * VetoableChangeListenerProxy, removing the underlying delegate from the
     259   * named property list if the names match.
     260   *
     261   * @param propertyName the property to stop listening on
     262   * @param l the listener to remove
     263   * @throws NullPointerException if propertyName is null
     264   */
     265  public synchronized void
     266    removeVetoableChangeListener(String propertyName, VetoableChangeListener l)
     267  {
     268    if (children == null)
     269      return;
     270    VetoableChangeSupport s
     271      = (VetoableChangeSupport) children.get(propertyName);
     272    if (s == null)
     273      return;
     274    while (l instanceof VetoableChangeListenerProxy)
     275      {
     276        VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l;
     277        if (propertyName == null ? p.propertyName != null
     278            : ! propertyName.equals(p.propertyName))
     279          return;
     280        l = (VetoableChangeListener) p.getListener();
     281      }
     282    s.listeners.remove(l);
     283    if (s.listeners.isEmpty())
     284      {
     285        children.remove(propertyName);
     286        if (children.isEmpty())
     287          children = null;
     288      }
     289  }
     290
     291  /**
     292   * Returns an array of all vetoable change listeners registered under the
     293   * given property name. If there are no registered listeners, this returns
     294   * an empty array.
     295   *
     296   * @return the array of registered listeners
     297   * @throws NullPointerException if propertyName is null
     298   * @since 1.4
     299   */
     300  public synchronized VetoableChangeListener[]
     301    getVetoableChangeListeners(String propertyName)
     302  {
     303    if (children == null)
     304      return new VetoableChangeListener[0];
     305    VetoableChangeSupport s
     306      = (VetoableChangeSupport) children.get(propertyName);
     307    if (s == null)
     308      return new VetoableChangeListener[0];
     309    return (VetoableChangeListener[])
     310      s.listeners.toArray(new VetoableChangeListener[s.listeners.size()]);
     311  }
     312
     313  /**
     314   * Fire a PropertyChangeEvent containing the old and new values of the
     315   * property to all the global listeners, and to all the listeners for the
     316   * specified property name. This does nothing if old and new are non-null
     317   * and equal. If the change is vetoed, a new event is fired to notify
     318   * listeners about the rollback before the exception is thrown.
     319   *
     320   * @param propertyName the name of the property that changed
     321   * @param oldVal the old value
     322   * @param newVal the new value
     323   * @throws PropertyVetoException if the change is vetoed by a listener
     324   */
     325  public void fireVetoableChange(String propertyName,
     326                                 Object oldVal, Object newVal)
     327    throws PropertyVetoException
     328  {
     329    fireVetoableChange(new PropertyChangeEvent(source, propertyName,
     330                                               oldVal, newVal));
     331  }
     332
     333  /**
     334   * Fire a PropertyChangeEvent containing the old and new values of the
     335   * property to all the global listeners, and to all the listeners for the
     336   * specified property name. This does nothing if old and new are equal.
     337   * If the change is vetoed, a new event is fired to notify listeners about
     338   * the rollback before the exception is thrown.
     339   *
     340   * @param propertyName the name of the property that changed
     341   * @param oldVal the old value
     342   * @param newVal the new value
     343   * @throws PropertyVetoException if the change is vetoed by a listener
     344   */
     345  public void fireVetoableChange(String propertyName, int oldVal, int newVal)
     346    throws PropertyVetoException
     347  {
     348    if (oldVal != newVal)
     349      fireVetoableChange(new PropertyChangeEvent(source, propertyName,
     350                                                 new Integer(oldVal),
     351                                                 new Integer(newVal)));
     352  }
     353
     354  /**
     355   * Fire a PropertyChangeEvent containing the old and new values of the
     356   * property to all the global listeners, and to all the listeners for the
     357   * specified property name. This does nothing if old and new are equal.
     358   * If the change is vetoed, a new event is fired to notify listeners about
     359   * the rollback before the exception is thrown.
     360   *
     361   * @param propertyName the name of the property that changed
     362   * @param oldVal the old value
     363   * @param newVal the new value
     364   * @throws PropertyVetoException if the change is vetoed by a listener
     365   */
     366  public void fireVetoableChange(String propertyName,
     367                                 boolean oldVal, boolean newVal)
     368    throws PropertyVetoException
     369  {
     370    if (oldVal != newVal)
     371      fireVetoableChange(new PropertyChangeEvent(source, propertyName,
     372                                                 Boolean.valueOf(oldVal),
     373                                                 Boolean.valueOf(newVal)));
     374  }
     375
     376  /**
     377   * Fire a PropertyChangeEvent to all the global listeners, and to all the
     378   * listeners for the specified property name. This does nothing if old and
     379   * new values of the event are equal. If the change is vetoed, a new event
     380   * is fired to notify listeners about the rollback before the exception is
     381   * thrown.
     382   *
     383   * @param event the event to fire
     384   * @throws NullPointerException if event is null
     385   * @throws PropertyVetoException if the change is vetoed by a listener
     386   */
     387  public void fireVetoableChange(PropertyChangeEvent event)
     388    throws PropertyVetoException
     389  {
     390    if (event.oldValue != null && event.oldValue.equals(event.newValue))
     391      return;
     392    Vector v = listeners; // Be thread-safe.
     393    if (v != null)
     394      {
     395        int i = v.size();
     396        try
     397          {
     398            while (--i >= 0)
     399              ((VetoableChangeListener) v.get(i)).vetoableChange(event);
     400          }
     401        catch (PropertyVetoException e)
     402          {
     403            event = event.rollback();
     404            int limit = i;
     405            i = v.size();
     406            while (--i >= limit)
     407              ((VetoableChangeListener) v.get(i)).vetoableChange(event);
     408            throw e;
     409          }
     410      }
     411    Hashtable h = children; // Be thread-safe.
     412    if (h != null && event.propertyName != null)
     413      {
     414        VetoableChangeSupport s
     415          = (VetoableChangeSupport) h.get(event.propertyName);
     416        if (s != null)
     417          {
     418            Vector v1 = s.listeners; // Be thread-safe.
     419            int i = v1 == null ? 0 : v1.size();
     420            try
     421              {
     422                while (--i >= 0)
     423                  ((VetoableChangeListener) v1.get(i)).vetoableChange(event);
     424              }
     425            catch (PropertyVetoException e)
     426              {
     427                event = event.rollback();
     428                int limit = i;
     429                i = v.size();
     430                while (--i >= 0)
     431                  ((VetoableChangeListener) v.get(i)).vetoableChange(event);
     432                i = v1.size();
     433                while (--i >= limit)
     434                  ((VetoableChangeListener) v1.get(i)).vetoableChange(event);
     435                throw e;
     436              }
     437          }
     438      }
     439  }
     440
     441  /**
     442   * Tell whether the specified property is being listened on or not. This
     443   * will only return <code>true</code> if there are listeners on all
     444   * properties or if there is a listener specifically on this property.
     445   *
     446   * @param propertyName the property that may be listened on
     447   * @return whether the property is being listened on
     448   * @throws NullPointerException if propertyName is null
     449   */
     450  public synchronized boolean hasListeners(String propertyName)
     451  {
     452    return listeners != null || (children != null
     453                                 && children.get(propertyName) != null);
     454  }
     455
     456  /**
     457   * Saves the state of the object to the stream.
     458   *
     459   * @param s the stream to write to
     460   * @throws IOException if anything goes wrong
     461   * @serialData this writes out a null-terminated list of serializable
     462   *             global vetoable change listeners (the listeners for a named
     463   *             property are written out as the global listeners of the
     464   *             children, when the children hashtable is saved)
     465   */
     466  private synchronized void writeObject(ObjectOutputStream s)
     467    throws IOException
     468  {
     469    s.defaultWriteObject();
     470    if (listeners != null)
     471      {
     472        int i = listeners.size();
     473        while (--i >= 0)
     474          if (listeners.get(i) instanceof Serializable)
     475            s.writeObject(listeners.get(i));
     476      }
     477    s.writeObject(null);
     478  }
     479
     480  /**
     481   * Reads the object back from stream (deserialization).
     482   *
     483   * XXX Since serialization for 1.1 streams was not documented, this may
     484   * not work if vetoableChangeSupportSerializedDataVersion is 1.
     485   *
     486   * @param s the stream to read from
     487   * @throws IOException if reading the stream fails
     488   * @throws ClassNotFoundException if deserialization fails
     489   * @serialData this reads in a null-terminated list of serializable
     490   *             global vetoable change listeners (the listeners for a named
     491   *             property are written out as the global listeners of the
     492   *             children, when the children hashtable is saved)
     493   */
     494  private void readObject(ObjectInputStream s)
     495    throws IOException, ClassNotFoundException
     496  {
     497    s.defaultReadObject();
     498    VetoableChangeListener l = (VetoableChangeListener) s.readObject();
     499    while (l != null)
     500      {
     501        addVetoableChangeListener(l);
     502        l = (VetoableChangeListener) s.readObject();
     503      }
     504    // Sun is not as careful with children as we are, and lets some proxys
     505    // in that can never receive events. So, we clean up anything that got
     506    // serialized, to make sure our invariants hold.
     507    if (children != null)
     508      {
     509        int i = children.size();
     510        Iterator iter = children.entrySet().iterator();
     511        while (--i >= 0)
     512          {
     513            Entry e = (Entry) iter.next();
     514            String name = (String) e.getKey();
     515            VetoableChangeSupport vcs = (VetoableChangeSupport) e.getValue();
     516            if (vcs.listeners == null)
     517              vcs.listeners = new Vector();
     518            if (vcs.children != null)
     519              vcs.listeners.addAll
     520                (Arrays.asList(vcs.getVetoableChangeListeners(name)));
     521            if (vcs.listeners.size() == 0)
     522              iter.remove();
     523            else
     524              vcs.children = null;
     525          }
     526        if (children.size() == 0)
     527          children = null;
     528      }
     529  }
     530} // class VetoableChangeSupport
  • branches/GNU/src/gcc/libjava/java/beans/beancontext/BeanContextChildSupport.java

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1390 r1391  
    6161 */
    6262
    63 public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable {
     63public class BeanContextChildSupport
     64  implements BeanContextChild, BeanContextServicesListener, Serializable
     65{
     66  static final long serialVersionUID = 6328947014421475877L;
     67
    6468        /**
    6569         * The peer on which to perform <code>set</code> actions.
Note: See TracChangeset for help on using the changeset viewer.