373 lines · 13.0 KB · Java
RawDownload
/* * Copyright (c) 1998, 2004, Oracle and/or its affiliates. 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.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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; /** * <p> * 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. * </p> * * @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 <code>BeanContext</code> for     * this <code>BeanContextChildSupport</code>.     * @param bc the new value to be assigned to the <code>BeanContext</code>     * property     * @throws <code>PropertyVetoException</code> 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 <code>BeanContext</code>     * for this <code>BeanContextChildSupport</code>.     * @return the nesting <code>BeanContext</code> for     * this <code>BeanContextChildSupport</code>.     */    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 <code>name</code> or <code>pcl</code> is null, no exception is thrown     * and no action is taken.     *     * @param name The name of the property to listen on     * @param pcl The <code>PropertyChangeListener</code> to be added     */    public void addPropertyChangeListener(String name, PropertyChangeListener pcl) {        pcSupport.addPropertyChangeListener(name, pcl);    }     /**     * Remove a PropertyChangeListener for a specific property.     * If <code>pcl</code> 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 <code>name</code> is null, no exception is thrown     * and no action is taken.     * If <code>pcl</code> 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 <code>name</code> or <code>vcl</code> is null, no exception is thrown     * and no action is taken.     *     * @param name The name of the property to listen on     * @param vcl The <code>VetoableChangeListener</code> to be added     */    public void addVetoableChangeListener(String name, VetoableChangeListener vcl) {        vcSupport.addVetoableChangeListener(name, vcl);    }     /**     * Removes a <code>VetoableChangeListener</code>.     * If <code>pcl</code> 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 <code>name</code> is null, no exception is thrown     * and no action is taken.     * If <code>vcl</code> 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 <code>VetoableChangeListener</code> 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 <code>BeanContextServiceRevokedEvent</code> 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 <tt>BeanContextChild</tt> associated with this     * <tt>BeanContextChildSupport</tt>.     *     * @return the <tt>BeanContextChild</tt> 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. <P>     *     * No event is fired if old and new are equal and non-null.     * <P>     * @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 <code>true</code> 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 <code>BeanContext</code> in which     * this <code>BeanContextChild</code> is nested.     */    public    BeanContextChild      beanContextChildPeer;    /**    * The <tt>PropertyChangeSupport</tt> associated with this    * <tt>BeanContextChildSupport</tt>.    */    protected PropertyChangeSupport pcSupport;    /**    * The <tt>VetoableChangeSupport</tt> associated with this    * <tt>BeanContextChildSupport</tt>.    */    protected VetoableChangeSupport vcSupport;     protected transient BeanContext           beanContext;    /**    * A flag indicating that there has been    * at least one <code>PropertyChangeVetoException</code>    * thrown for the attempted setBeanContext operation.    */    protected transient boolean               rejectedSetBCOnce; }