Changeset 1391 for branches/GNU/src/gcc/libjava/java/beans
- Timestamp:
- Apr 27, 2004, 8:39:34 PM (22 years ago)
- Location:
- branches/GNU/src/gcc
- Files:
-
- 10 edited
-
. (modified) (1 prop)
-
libjava/java/beans/BeanInfo.java (modified) (1 diff, 1 prop)
-
libjava/java/beans/Introspector.java (modified) (2 diffs, 1 prop)
-
libjava/java/beans/PropertyChangeEvent.java (modified) (3 diffs, 1 prop)
-
libjava/java/beans/PropertyChangeListener.java (modified) (3 diffs, 1 prop)
-
libjava/java/beans/PropertyChangeSupport.java (modified) (3 diffs, 1 prop)
-
libjava/java/beans/PropertyDescriptor.java (modified) (1 diff, 1 prop)
-
libjava/java/beans/VetoableChangeListener.java (modified) (3 diffs, 1 prop)
-
libjava/java/beans/VetoableChangeSupport.java (modified) (3 diffs, 1 prop)
-
libjava/java/beans/beancontext/BeanContextChildSupport.java (modified) (1 diff, 1 prop)
Legend:
- Unmodified
- Added
- Removed
-
branches/GNU/src/gcc
- Property svn:ignore
-
old new 26 26 configure.vr 27 27 configure.vrs 28 28 29 Makefile 29 dir.info30 30 lost+found 31 31 update.out
-
- Property svn:ignore
-
branches/GNU/src/gcc/libjava/java/beans/BeanInfo.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 75 75 public interface BeanInfo { 76 76 /** 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; 78 78 /** 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; 80 80 /** 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; 82 82 /** 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; 84 84 85 85 /** Get the general description of this Bean type. -
Property cvs2svn:cvs-rev
changed from
-
branches/GNU/src/gcc/libjava/java/beans/Introspector.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 1 1 /* java.beans.Introspector 2 Copyright (C) 1998 Free Software Foundation, Inc.2 Copyright (C) 1998 Free Software Foundation, Inc. 3 3 4 4 This file is part of GNU Classpath. … … 210 210 } 211 211 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 212 238 /** 213 239 * Get the BeanInfo for class <CODE>beanClass</CODE>, -
Property cvs2svn:cvs-rev
changed from
-
branches/GNU/src/gcc/libjava/java/beans/PropertyChangeEvent.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 1 /* java.beans.PropertyChangeEvent2 Copyright (C) 1998, 2000 Free Software Foundation, Inc.1 /* 2 Copyright (C) 1998, 2000 Free Software Foundation, Inc. 3 3 4 4 This file is part of GNU Classpath. … … 8 8 the Free Software Foundation; either version 2, or (at your option) 9 9 any later version. 10 10 11 11 GNU Classpath is distributed in the hope that it will be useful, but 12 12 WITHOUT ANY WARRANTY; without even the implied warranty of … … 39 39 package java.beans; 40 40 41 42 41 43 /** 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 */ 62 public class PropertyChangeEvent extends EventObject 63 { 64 /** 65 * Compatible with JDK 1.1+. 66 */ 67 private static final long serialVersionUID = 7042693688939648123L; 61 68 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; 67 76 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; 69 84 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; 85 92 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; 92 100 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 } 99 120 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 } 106 130 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 } 117 140 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 -
Property cvs2svn:cvs-rev
changed from
-
branches/GNU/src/gcc/libjava/java/beans/PropertyChangeListener.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 1 /* java.beans.PropertyChangeListener2 Copyright (C) 1998, 2000 Free Software Foundation, Inc.1 /* 2 Copyright (C) 1998, 2000 Free Software Foundation, Inc. 3 3 4 4 This file is part of GNU Classpath. … … 8 8 the Free Software Foundation; either version 2, or (at your option) 9 9 any later version. 10 10 11 11 GNU Classpath is distributed in the hope that it will be useful, but 12 12 WITHOUT ANY WARRANTY; without even the implied warranty of … … 42 42 43 43 /** 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 */ 56 53 public interface PropertyChangeListener extends EventListener 57 54 { 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 -
Property cvs2svn:cvs-rev
changed from
-
branches/GNU/src/gcc/libjava/java/beans/PropertyChangeSupport.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 1 /* java.beans.PropertyChangeSupport2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.1 /* 2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. 3 3 4 4 This file is part of GNU Classpath. … … 8 8 the Free Software Foundation; either version 2, or (at your option) 9 9 any later version. 10 10 11 11 GNU Classpath is distributed in the hope that it will be useful, but 12 12 WITHOUT ANY WARRANTY; without even the implied warranty of … … 38 38 39 39 package java.beans; 40 import java.util.Hashtable; 41 import java.util.Vector; 42 import java.util.Enumeration; 40 41 import java.io.IOException; 43 42 import java.io.ObjectInputStream; 44 43 import java.io.ObjectOutputStream; 45 import java.io.IOException;46 44 import java.io.Serializable; 45 46 47 48 49 50 47 51 48 52 /** 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 */ 64 public 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 -
Property cvs2svn:cvs-rev
changed from
-
branches/GNU/src/gcc/libjava/java/beans/PropertyDescriptor.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 66 66 67 67 public 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<name>()</CODE> 83 ** (or, optionally, if the property is boolean, 84 ** <CODE>is<name>()</CODE>) and 85 ** <CODE>set<name>()</CODE> in class 86 ** <CODE><beanClass></CODE>, where <name> 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<name>()</CODE> 83 ** (or, optionally, if the property is boolean, 84 ** <CODE>is<name>()</CODE>) and 85 ** <CODE>set<name>()</CODE> in class 86 ** <CODE><beanClass></CODE>, where <name> 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 } 344 376 } -
Property cvs2svn:cvs-rev
changed from
-
branches/GNU/src/gcc/libjava/java/beans/VetoableChangeListener.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 1 /* java.beans.VetoableChangeListener2 Copyright (C) 1998, 2000 Free Software Foundation, Inc.1 /* 2 Copyright (C) 1998, 2000 Free Software Foundation, Inc. 3 3 4 4 This file is part of GNU Classpath. … … 8 8 the Free Software Foundation; either version 2, or (at your option) 9 9 any later version. 10 10 11 11 GNU Classpath is distributed in the hope that it will be useful, but 12 12 WITHOUT ANY WARRANTY; without even the implied warranty of … … 42 42 43 43 /** 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 */ 68 64 public interface VetoableChangeListener extends EventListener 69 65 { 70 /** Fired before a Bean's property changes.71 * * @param e the change (containing the old and new values)72 * * @exception PropertyChangeException if the listener73 * * 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 } -
Property cvs2svn:cvs-rev
changed from
-
branches/GNU/src/gcc/libjava/java/beans/VetoableChangeSupport.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 1 /* java.beans.VetoableChangeSupport2 Copyright (C) 1998 Free Software Foundation, Inc.1 /* 2 Copyright (C) 1998 Free Software Foundation, Inc. 3 3 4 4 This file is part of GNU Classpath. … … 8 8 the Free Software Foundation; either version 2, or (at your option) 9 9 any later version. 10 10 11 11 GNU Classpath is distributed in the hope that it will be useful, but 12 12 WITHOUT ANY WARRANTY; without even the implied warranty of … … 36 36 exception statement from your version. */ 37 37 38 38 39 package java.beans; 39 import java.util.Hashtable; 40 import java.util.Vector; 41 import java.util.Enumeration; 40 41 import java.io.IOException; 42 42 import java.io.ObjectInputStream; 43 43 import java.io.ObjectOutputStream; 44 import java.io.IOException;45 44 import java.io.Serializable; 45 46 47 48 49 50 46 51 47 52 /** 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 */ 64 public 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 -
Property cvs2svn:cvs-rev
changed from
-
branches/GNU/src/gcc/libjava/java/beans/beancontext/BeanContextChildSupport.java
-
Property cvs2svn:cvs-rev
changed from
1.1to1.1.1.2
r1390 r1391 61 61 */ 62 62 63 public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable { 63 public class BeanContextChildSupport 64 implements BeanContextChild, BeanContextServicesListener, Serializable 65 { 66 static final long serialVersionUID = 6328947014421475877L; 67 64 68 /** 65 69 * The peer on which to perform <code>set</code> actions. -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.
