Frames | No Frames |
1: /* java.beans.beancontext.BeanContextChildSupport 2: Copyright (C) 1999 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.beans.beancontext; 40: 41: import java.beans.PropertyChangeEvent; 42: import java.beans.PropertyChangeListener; 43: import java.beans.PropertyChangeSupport; 44: import java.beans.PropertyVetoException; 45: import java.beans.VetoableChangeListener; 46: import java.beans.VetoableChangeSupport; 47: import java.io.Serializable; 48: 49: /** 50: * Support for creating a <code>BeanContextChild</code>. 51: * This class contains the most common implementations of the methods in 52: * the <code>BeanContextChild</code> 53: * 54: * @specnote This class is not very well specified. I had to "fill in the 55: * blanks" in most places with what I thought was reasonable 56: * behavior. If there are problems, let me know. 57: * 58: * @author John Keiser 59: * @since 1.2 60: * @see java.beans.beancontext.BeanContextChild 61: */ 62: public class BeanContextChildSupport 63: implements BeanContextChild, BeanContextServicesListener, Serializable 64: { 65: static final long serialVersionUID = 6328947014421475877L; 66: 67: /** 68: * The peer on which to perform <code>set</code> actions. 69: * This is here so that this class can be used as a peer. 70: * <P> 71: * 72: * When extending this class, this variable will be set to 73: * <code>this</code>. 74: */ 75: public BeanContextChild beanContextChildPeer; 76: 77: /** 78: * The parent <code>BeanContext</code>. 79: */ 80: protected transient BeanContext beanContext; 81: 82: /** 83: * If <code>setBeanContext()</code> was vetoed once before, this 84: * is set to <code>true</code> so that the next time, vetoes will 85: * be ignored. 86: */ 87: protected transient boolean rejectedSetBCOnce; 88: 89: /** 90: * Listeners are registered here and events are fired through here. 91: */ 92: protected PropertyChangeSupport pcSupport; 93: 94: /** 95: * Listeners are registered here and events are fired through here. 96: */ 97: protected VetoableChangeSupport vcSupport; 98: 99: /** 100: * Create a new <code>BeanContextChildSupport</code> with itself as the peer. 101: * This is meant to be used when you subclass 102: * <code>BeanContextChildSupport</code> to create your child. 103: */ 104: public BeanContextChildSupport() 105: { 106: this (null); 107: } 108: 109: /** 110: * Create a new <code>BeanContextChildSupport</code> with the specified peer. 111: * @param peer the peer to use, or <code>null</code> to specify 112: * <code>this</code>. 113: */ 114: public BeanContextChildSupport (BeanContextChild peer) 115: { 116: if (peer == null) 117: { 118: peer = this; 119: } 120: 121: beanContextChildPeer = peer; 122: pcSupport = new PropertyChangeSupport (peer); 123: vcSupport = new VetoableChangeSupport (peer); 124: } 125: 126: /** 127: * Set the parent <code>BeanContext</code>. 128: * <P> 129: * 130: * When this Object is being added to a new BeanContext or moved 131: * from an old one, a non-null value will be passed in. 132: * <P> 133: * 134: * When this Object is being removed from the current 135: * <code>BeanContext</code>, <code>setBeanContext()</code> will 136: * receive the parameter <code>null</code>. 137: * <P> 138: * 139: * Order of events: 140: * <OL> 141: * <LI> 142: * If the new <code>BeanContext</code> is the same as the old 143: * one, nothing happens. 144: * </LI> 145: * <LI> 146: * If the change has not been rejected or vetoed before, call 147: * <code>validatePendingSetBeanContext()</code>. If this call 148: * returns <code>false</code>, the change is rejected and a 149: * <code>PropertyVetoException</code> is thrown. 150: * </LI> 151: * <LI> 152: * If the change has not been rejected or vetoed before, 153: * <code>VetoableChangeEvent</code>s are fired with the name 154: * <code>"beanContext"</code>, using the 155: * <code>fireVetoableChange()</code> method. If a veto 156: * occurs, reversion events are fired using the same method, 157: * the change is rejected, and the veto is rethrown. 158: * </LI> 159: * <LI> 160: * <code>releaseBeanContextResources()</code> is called. 161: * </LI> 162: * <LI> 163: * The change is made. 164: * </LI> 165: * <LI> 166: * <code>PropertyChangeEvent</code>s are fired using the 167: * <code>firePropertyChange()</code> method. 168: * </LI> 169: * <LI> 170: * <code>initializeBeanContextResources()</code> is called. 171: * </LI> 172: * </OL> 173: * <P> 174: * 175: * @param newBeanContext the new parent for the 176: * <code>BeanContextChild</code>, or <code>null</code> to 177: * signify removal from a tree. 178: * @exception PropertyVetoException if the 179: * <code>BeanContextChild</code> implementor does not 180: * wish to have its parent changed. 181: */ 182: public void setBeanContext(BeanContext newBeanContext) 183: throws PropertyVetoException 184: { 185: synchronized (beanContextChildPeer) 186: { 187: if (newBeanContext == beanContext) 188: return; 189: 190: if (!rejectedSetBCOnce) 191: { 192: if (!validatePendingSetBeanContext (newBeanContext)) 193: { 194: rejectedSetBCOnce = true; 195: throw new PropertyVetoException ("validatePendingSetBeanContext() rejected change", 196: new PropertyChangeEvent(beanContextChildPeer, "beanContext", beanContext, newBeanContext)); 197: } 198: 199: try 200: { 201: fireVetoableChange ("beanContext", beanContext, newBeanContext); 202: } 203: catch (PropertyVetoException e) 204: { 205: rejectedSetBCOnce = true; 206: throw e; 207: } 208: } 209: 210: releaseBeanContextResources (); 211: 212: beanContext = newBeanContext; 213: rejectedSetBCOnce = false; 214: 215: firePropertyChange ("beanContext", beanContext, newBeanContext); 216: 217: initializeBeanContextResources (); 218: } 219: } 220: 221: /** 222: * Get the parent <code>BeanContext</code>. 223: * @return the parent <code>BeanContext</code>. 224: */ 225: public BeanContext getBeanContext() 226: { 227: return beanContext; 228: } 229: 230: /** 231: * Get the peer (or <code>this</code> if there is no peer). 232: * @return the peer, or <code>this</code> if there is no peer. 233: */ 234: public BeanContextChild getBeanContextChildPeer() { 235: return beanContextChildPeer; 236: } 237: 238: /** 239: * Determine whether there is a peer. 240: * This is true iff <code>getBeanContextChildPeer() == this</code>. 241: * @return whether there is a peer. 242: */ 243: public boolean isDelegated() { 244: return beanContextChildPeer == this; 245: } 246: 247: /** 248: * Add a listener that will be notified when a specific property changes. 249: * @param propertyName the name of the property to listen on. 250: * @param listener the listener to listen on the property. 251: */ 252: public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { 253: pcSupport.addPropertyChangeListener(propertyName, listener); 254: } 255: 256: /** 257: * Remove a listener to a certain property. 258: * 259: * @param propertyName the name of the property being listened on. 260: * @param listener the listener listening on the property. 261: */ 262: public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { 263: pcSupport.removePropertyChangeListener(propertyName, listener); 264: } 265: 266: /** 267: * Add a listener that will be notified when a specific property 268: * change is requested (a PropertyVetoException may be thrown) as 269: * well as after the change is successfully made. 270: * 271: * @param propertyName the name of the property to listen on. 272: * @param listener the listener to listen on the property. 273: */ 274: public void addVetoableChangeListener(String propertyName, VetoableChangeListener listener) { 275: vcSupport.addVetoableChangeListener(propertyName, listener); 276: } 277: 278: /** 279: * Remove a listener to a certain property. 280: * 281: * @param propertyName the name of the property being listened on 282: * @param listener the listener listening on the property. 283: */ 284: public void removeVetoableChangeListener(String propertyName, VetoableChangeListener listener) { 285: vcSupport.removeVetoableChangeListener(propertyName, listener); 286: } 287: 288: /** 289: * Fire a property change. 290: * 291: * @param propertyName the name of the property that changed 292: * @param oldVal the old value of the property 293: * @param newVal the new value of the property 294: */ 295: public void firePropertyChange(String propertyName, Object oldVal, Object newVal) { 296: pcSupport.firePropertyChange(propertyName, oldVal, newVal); 297: } 298: 299: /** 300: * Fire a vetoable property change. 301: * 302: * @param propertyName the name of the property that changed 303: * @param oldVal the old value of the property 304: * @param newVal the new value of the property 305: * @exception PropertyVetoException if the change is vetoed. 306: */ 307: public void fireVetoableChange(String propertyName, Object oldVal, Object newVal) 308: throws PropertyVetoException { 309: vcSupport.fireVetoableChange(propertyName, oldVal, newVal); 310: } 311: 312: /** 313: * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked. 314: * If you have a reference to such a service, it should be 315: * discarded and may no longer function properly. 316: * <code>getService()</code> will no longer work on the specified 317: * service class after this event has been fired. 318: * <P> 319: * 320: * <EM>This method is meant to be overriden.</EM> 321: * <code>BeanContextChildSupport</code>'s implementation does 322: * nothing. 323: * 324: * @param event the service revoked event. 325: * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean) 326: */ 327: public void serviceRevoked(BeanContextServiceRevokedEvent event) { 328: } 329: 330: /** 331: * Called by <code>BeanContextServices</code> whenever a service is made available. 332: * <P> 333: * 334: * <EM>This method is meant to be overriden.</EM> 335: * <code>BeanContextChildSupport</code>'s implementation does 336: * nothing. 337: * 338: * @param event the service revoked event, with useful information 339: * about the new service. 340: */ 341: public void serviceAvailable(BeanContextServiceAvailableEvent event) { 342: } 343: 344: /** 345: * Called by <code>setBeanContext()</code> to determine whether the set should be rejected. 346: * <P> 347: * 348: * <EM>This method is meant to be overriden.</EM> 349: * <code>BeanContextChildSupport</code>'s implementation simply 350: * returns <code>true</code>. 351: * 352: * @param newBeanContext the new parent. 353: * @return whether to allow the parent to be changed to the new 354: * value. 355: */ 356: public boolean validatePendingSetBeanContext(BeanContext newBeanContext) { 357: return true; 358: } 359: 360: /** 361: * Called by <code>setBeanContext()</code> to release resources of a what will soon no longer be the parent. 362: * <P> 363: * 364: * <EM>This method is meant to be overriden.</EM> 365: * <code>BeanContextChildSupport</code>'s implementation does 366: * nothing. 367: */ 368: protected void releaseBeanContextResources() { 369: } 370: 371: /** 372: * Called by <code>setBeanContext()</code> to grab resources when the parent has been set. 373: * <P> 374: * 375: * <EM>This method is meant to be overriden.</EM> 376: * <code>BeanContextChildSupport</code>'s implementation does 377: * nothing. 378: */ 379: protected void initializeBeanContextResources() { 380: } 381: }