diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/classes/java/beans/beancontext/BeanContextChildSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/beans/beancontext/BeanContextChildSupport.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,373 @@ +/* + * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.beans.beancontext; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; + +import java.beans.PropertyVetoException; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + *

+ * This is a general support class to provide support for implementing the + * BeanContextChild protocol. + * + * This class may either be directly subclassed, or encapsulated and delegated + * to in order to implement this interface for a given component. + *

+ * + * @author Laurence P. G. Cable + * @since 1.2 + * + * @see java.beans.beancontext.BeanContext + * @see java.beans.beancontext.BeanContextServices + * @see java.beans.beancontext.BeanContextChild + */ + +public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable { + + static final long serialVersionUID = 6328947014421475877L; + + /** + * construct a BeanContextChildSupport where this class has been + * subclassed in order to implement the JavaBean component itself. + */ + + public BeanContextChildSupport() { + super(); + + beanContextChildPeer = this; + + pcSupport = new PropertyChangeSupport(beanContextChildPeer); + vcSupport = new VetoableChangeSupport(beanContextChildPeer); + } + + /** + * construct a BeanContextChildSupport where the JavaBean component + * itself implements BeanContextChild, and encapsulates this, delegating + * that interface to this implementation + */ + + public BeanContextChildSupport(BeanContextChild bcc) { + super(); + + beanContextChildPeer = (bcc != null) ? bcc : this; + + pcSupport = new PropertyChangeSupport(beanContextChildPeer); + vcSupport = new VetoableChangeSupport(beanContextChildPeer); + } + + /** + * Sets the BeanContext for + * this BeanContextChildSupport. + * @param bc the new value to be assigned to the BeanContext + * property + * @throws PropertyVetoException if the change is rejected + */ + public synchronized void setBeanContext(BeanContext bc) throws PropertyVetoException { + if (bc == beanContext) return; + + BeanContext oldValue = beanContext; + BeanContext newValue = bc; + + if (!rejectedSetBCOnce) { + if (rejectedSetBCOnce = !validatePendingSetBeanContext(bc)) { + throw new PropertyVetoException( + "setBeanContext() change rejected:", + new PropertyChangeEvent(beanContextChildPeer, "beanContext", oldValue, newValue) + ); + } + + try { + fireVetoableChange("beanContext", + oldValue, + newValue + ); + } catch (PropertyVetoException pve) { + rejectedSetBCOnce = true; + + throw pve; // re-throw + } + } + + if (beanContext != null) releaseBeanContextResources(); + + beanContext = newValue; + rejectedSetBCOnce = false; + + firePropertyChange("beanContext", + oldValue, + newValue + ); + + if (beanContext != null) initializeBeanContextResources(); + } + + /** + * Gets the nesting BeanContext + * for this BeanContextChildSupport. + * @return the nesting BeanContext for + * this BeanContextChildSupport. + */ + public synchronized BeanContext getBeanContext() { return beanContext; } + + /** + * Add a PropertyChangeListener for a specific property. + * The same listener object may be added more than once. For each + * property, the listener will be invoked the number of times it was added + * for that property. + * If name or pcl is null, no exception is thrown + * and no action is taken. + * + * @param name The name of the property to listen on + * @param pcl The PropertyChangeListener to be added + */ + public void addPropertyChangeListener(String name, PropertyChangeListener pcl) { + pcSupport.addPropertyChangeListener(name, pcl); + } + + /** + * Remove a PropertyChangeListener for a specific property. + * If pcl was added more than once to the same event + * source for the specified property, it will be notified one less time + * after being removed. + * If name is null, no exception is thrown + * and no action is taken. + * If pcl is null, or was never added for the specified + * property, no exception is thrown and no action is taken. + * + * @param name The name of the property that was listened on + * @param pcl The PropertyChangeListener to be removed + */ + public void removePropertyChangeListener(String name, PropertyChangeListener pcl) { + pcSupport.removePropertyChangeListener(name, pcl); + } + + /** + * Add a VetoableChangeListener for a specific property. + * The same listener object may be added more than once. For each + * property, the listener will be invoked the number of times it was added + * for that property. + * If name or vcl is null, no exception is thrown + * and no action is taken. + * + * @param name The name of the property to listen on + * @param vcl The VetoableChangeListener to be added + */ + public void addVetoableChangeListener(String name, VetoableChangeListener vcl) { + vcSupport.addVetoableChangeListener(name, vcl); + } + + /** + * Removes a VetoableChangeListener. + * If pcl was added more than once to the same event + * source for the specified property, it will be notified one less time + * after being removed. + * If name is null, no exception is thrown + * and no action is taken. + * If vcl is null, or was never added for the specified + * property, no exception is thrown and no action is taken. + * + * @param name The name of the property that was listened on + * @param vcl The VetoableChangeListener to be removed + */ + public void removeVetoableChangeListener(String name, VetoableChangeListener vcl) { + vcSupport.removeVetoableChangeListener(name, vcl); + } + + /** + * A service provided by the nesting BeanContext has been revoked. + * + * Subclasses may override this method in order to implement their own + * behaviors. + * @param bcsre The BeanContextServiceRevokedEvent fired as a + * result of a service being revoked + */ + public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) { } + + /** + * A new service is available from the nesting BeanContext. + * + * Subclasses may override this method in order to implement their own + * behaviors + * @param bcsae The BeanContextServiceAvailableEvent fired as a + * result of a service becoming available + * + */ + public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) { } + + /** + * Gets the BeanContextChild associated with this + * BeanContextChildSupport. + * + * @return the BeanContextChild peer of this class + */ + public BeanContextChild getBeanContextChildPeer() { return beanContextChildPeer; } + + /** + * Reports whether or not this class is a delegate of another. + * + * @return true if this class is a delegate of another + */ + public boolean isDelegated() { return !this.equals(beanContextChildPeer); } + + /** + * Report a bound property update to any registered listeners. No event is + * fired if old and new are equal and non-null. + * @param name The programmatic name of the property that was changed + * @param oldValue The old value of the property + * @param newValue The new value of the property + */ + public void firePropertyChange(String name, Object oldValue, Object newValue) { + pcSupport.firePropertyChange(name, oldValue, newValue); + } + + /** + * Report a vetoable property update to any registered listeners. + * If anyone vetos the change, then fire a new event + * reverting everyone to the old value and then rethrow + * the PropertyVetoException.

+ * + * No event is fired if old and new are equal and non-null. + *

+ * @param name The programmatic name of the property that is about to + * change + * + * @param oldValue The old value of the property + * @param newValue - The new value of the property + * + * @throws PropertyVetoException if the recipient wishes the property + * change to be rolled back. + */ + public void fireVetoableChange(String name, Object oldValue, Object newValue) throws PropertyVetoException { + vcSupport.fireVetoableChange(name, oldValue, newValue); + } + + /** + * Called from setBeanContext to validate (or otherwise) the + * pending change in the nesting BeanContext property value. + * Returning false will cause setBeanContext to throw + * PropertyVetoException. + * @param newValue the new value that has been requested for + * the BeanContext property + * @return true if the change operation is to be vetoed + */ + public boolean validatePendingSetBeanContext(BeanContext newValue) { + return true; + } + + /** + * This method may be overridden by subclasses to provide their own + * release behaviors. When invoked any resources held by this instance + * obtained from its current BeanContext property should be released + * since the object is no longer nested within that BeanContext. + */ + + protected void releaseBeanContextResources() { + // do nothing + } + + /** + * This method may be overridden by subclasses to provide their own + * initialization behaviors. When invoked any resources requried by the + * BeanContextChild should be obtained from the current BeanContext. + */ + + protected void initializeBeanContextResources() { + // do nothing + } + + /** + * Write the persistence state of the object. + */ + + private void writeObject(ObjectOutputStream oos) throws IOException { + + /* + * dont serialize if we are delegated and the delegator isnt also + * serializable. + */ + + if (!equals(beanContextChildPeer) && !(beanContextChildPeer instanceof Serializable)) + throw new IOException("BeanContextChildSupport beanContextChildPeer not Serializable"); + + else + oos.defaultWriteObject(); + + } + + + /** + * Restore a persistent object, must wait for subsequent setBeanContext() + * to fully restore any resources obtained from the new nesting + * BeanContext + */ + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + } + + /* + * fields + */ + + /** + * The BeanContext in which + * this BeanContextChild is nested. + */ + public BeanContextChild beanContextChildPeer; + + /** + * The PropertyChangeSupport associated with this + * BeanContextChildSupport. + */ + protected PropertyChangeSupport pcSupport; + + /** + * The VetoableChangeSupport associated with this + * BeanContextChildSupport. + */ + protected VetoableChangeSupport vcSupport; + + protected transient BeanContext beanContext; + + /** + * A flag indicating that there has been + * at least one PropertyChangeVetoException + * thrown for the attempted setBeanContext operation. + */ + protected transient boolean rejectedSetBCOnce; + +}