jdk/src/share/classes/java/beans/beancontext/BeanContextChildSupport.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1998-2004 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package java.beans.beancontext;
       
    27 
       
    28 import java.beans.PropertyChangeEvent;
       
    29 import java.beans.PropertyChangeListener;
       
    30 import java.beans.PropertyChangeSupport;
       
    31 
       
    32 import java.beans.VetoableChangeListener;
       
    33 import java.beans.VetoableChangeSupport;
       
    34 
       
    35 import java.beans.PropertyVetoException;
       
    36 
       
    37 import java.io.IOException;
       
    38 import java.io.ObjectInputStream;
       
    39 import java.io.ObjectOutputStream;
       
    40 import java.io.Serializable;
       
    41 
       
    42 /**
       
    43  * <p>
       
    44  * This is a general support class to provide support for implementing the
       
    45  * BeanContextChild protocol.
       
    46  *
       
    47  * This class may either be directly subclassed, or encapsulated and delegated
       
    48  * to in order to implement this interface for a given component.
       
    49  * </p>
       
    50  *
       
    51  * @author      Laurence P. G. Cable
       
    52  * @since       1.2
       
    53  *
       
    54  * @see java.beans.beancontext.BeanContext
       
    55  * @see java.beans.beancontext.BeanContextServices
       
    56  * @see java.beans.beancontext.BeanContextChild
       
    57  */
       
    58 
       
    59 public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable {
       
    60 
       
    61     static final long serialVersionUID = 6328947014421475877L;
       
    62 
       
    63     /**
       
    64      * construct a BeanContextChildSupport where this class has been
       
    65      * subclassed in order to implement the JavaBean component itself.
       
    66      */
       
    67 
       
    68     public BeanContextChildSupport() {
       
    69         super();
       
    70 
       
    71         beanContextChildPeer = this;
       
    72 
       
    73         pcSupport = new PropertyChangeSupport(beanContextChildPeer);
       
    74         vcSupport = new VetoableChangeSupport(beanContextChildPeer);
       
    75     }
       
    76 
       
    77     /**
       
    78      * construct a BeanContextChildSupport where the JavaBean component
       
    79      * itself implements BeanContextChild, and encapsulates this, delegating
       
    80      * that interface to this implementation
       
    81      */
       
    82 
       
    83     public BeanContextChildSupport(BeanContextChild bcc) {
       
    84         super();
       
    85 
       
    86         beanContextChildPeer = (bcc != null) ? bcc : this;
       
    87 
       
    88         pcSupport = new PropertyChangeSupport(beanContextChildPeer);
       
    89         vcSupport = new VetoableChangeSupport(beanContextChildPeer);
       
    90     }
       
    91 
       
    92     /**
       
    93      * Sets the <code>BeanContext</code> for
       
    94      * this <code>BeanContextChildSupport</code>.
       
    95      * @param bc the new value to be assigned to the <code>BeanContext</code>
       
    96      * property
       
    97      * @throws <code>PropertyVetoException</code> if the change is rejected
       
    98      */
       
    99     public synchronized void setBeanContext(BeanContext bc) throws PropertyVetoException {
       
   100         if (bc == beanContext) return;
       
   101 
       
   102         BeanContext oldValue = beanContext;
       
   103         BeanContext newValue = bc;
       
   104 
       
   105         if (!rejectedSetBCOnce) {
       
   106             if (rejectedSetBCOnce = !validatePendingSetBeanContext(bc)) {
       
   107                 throw new PropertyVetoException(
       
   108                     "setBeanContext() change rejected:",
       
   109                     new PropertyChangeEvent(beanContextChildPeer, "beanContext", oldValue, newValue)
       
   110                 );
       
   111             }
       
   112 
       
   113             try {
       
   114                 fireVetoableChange("beanContext",
       
   115                                    oldValue,
       
   116                                    newValue
       
   117                 );
       
   118             } catch (PropertyVetoException pve) {
       
   119                 rejectedSetBCOnce = true;
       
   120 
       
   121                 throw pve; // re-throw
       
   122             }
       
   123         }
       
   124 
       
   125         if (beanContext != null) releaseBeanContextResources();
       
   126 
       
   127         beanContext       = newValue;
       
   128         rejectedSetBCOnce = false;
       
   129 
       
   130         firePropertyChange("beanContext",
       
   131                            oldValue,
       
   132                            newValue
       
   133         );
       
   134 
       
   135         if (beanContext != null) initializeBeanContextResources();
       
   136     }
       
   137 
       
   138     /**
       
   139      * Gets the nesting <code>BeanContext</code>
       
   140      * for this <code>BeanContextChildSupport</code>.
       
   141      * @return the nesting <code>BeanContext</code> for
       
   142      * this <code>BeanContextChildSupport</code>.
       
   143      */
       
   144     public synchronized BeanContext getBeanContext() { return beanContext; }
       
   145 
       
   146     /**
       
   147      * Add a PropertyChangeListener for a specific property.
       
   148      * The same listener object may be added more than once.  For each
       
   149      * property,  the listener will be invoked the number of times it was added
       
   150      * for that property.
       
   151      * If <code>name</code> or <code>pcl</code> is null, no exception is thrown
       
   152      * and no action is taken.
       
   153      *
       
   154      * @param name The name of the property to listen on
       
   155      * @param pcl The <code>PropertyChangeListener</code> to be added
       
   156      */
       
   157     public void addPropertyChangeListener(String name, PropertyChangeListener pcl) {
       
   158         pcSupport.addPropertyChangeListener(name, pcl);
       
   159     }
       
   160 
       
   161     /**
       
   162      * Remove a PropertyChangeListener for a specific property.
       
   163      * If <code>pcl</code> was added more than once to the same event
       
   164      * source for the specified property, it will be notified one less time
       
   165      * after being removed.
       
   166      * If <code>name</code> is null, no exception is thrown
       
   167      * and no action is taken.
       
   168      * If <code>pcl</code> is null, or was never added for the specified
       
   169      * property, no exception is thrown and no action is taken.
       
   170      *
       
   171      * @param name The name of the property that was listened on
       
   172      * @param pcl The PropertyChangeListener to be removed
       
   173      */
       
   174     public void removePropertyChangeListener(String name, PropertyChangeListener pcl) {
       
   175         pcSupport.removePropertyChangeListener(name, pcl);
       
   176     }
       
   177 
       
   178     /**
       
   179      * Add a VetoableChangeListener for a specific property.
       
   180      * The same listener object may be added more than once.  For each
       
   181      * property,  the listener will be invoked the number of times it was added
       
   182      * for that property.
       
   183      * If <code>name</code> or <code>vcl</code> is null, no exception is thrown
       
   184      * and no action is taken.
       
   185      *
       
   186      * @param name The name of the property to listen on
       
   187      * @param vcl The <code>VetoableChangeListener</code> to be added
       
   188      */
       
   189     public void addVetoableChangeListener(String name, VetoableChangeListener vcl) {
       
   190         vcSupport.addVetoableChangeListener(name, vcl);
       
   191     }
       
   192 
       
   193     /**
       
   194      * Removes a <code>VetoableChangeListener</code>.
       
   195      * If <code>pcl</code> was added more than once to the same event
       
   196      * source for the specified property, it will be notified one less time
       
   197      * after being removed.
       
   198      * If <code>name</code> is null, no exception is thrown
       
   199      * and no action is taken.
       
   200      * If <code>vcl</code> is null, or was never added for the specified
       
   201      * property, no exception is thrown and no action is taken.
       
   202      *
       
   203      * @param name The name of the property that was listened on
       
   204      * @param vcl The <code>VetoableChangeListener</code> to be removed
       
   205      */
       
   206     public void removeVetoableChangeListener(String name, VetoableChangeListener vcl) {
       
   207         vcSupport.removeVetoableChangeListener(name, vcl);
       
   208     }
       
   209 
       
   210     /**
       
   211      * A service provided by the nesting BeanContext has been revoked.
       
   212      *
       
   213      * Subclasses may override this method in order to implement their own
       
   214      * behaviors.
       
   215      * @param bcsre The <code>BeanContextServiceRevokedEvent</code> fired as a
       
   216      * result of a service being revoked
       
   217      */
       
   218     public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) { }
       
   219 
       
   220     /**
       
   221      * A new service is available from the nesting BeanContext.
       
   222      *
       
   223      * Subclasses may override this method in order to implement their own
       
   224      * behaviors
       
   225      * @param bcsae The BeanContextServiceAvailableEvent fired as a
       
   226      * result of a service becoming available
       
   227      *
       
   228      */
       
   229     public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) { }
       
   230 
       
   231     /**
       
   232      * Gets the <tt>BeanContextChild</tt> associated with this
       
   233      * <tt>BeanContextChildSupport</tt>.
       
   234      *
       
   235      * @return the <tt>BeanContextChild</tt> peer of this class
       
   236      */
       
   237     public BeanContextChild getBeanContextChildPeer() { return beanContextChildPeer; }
       
   238 
       
   239     /**
       
   240      * Reports whether or not this class is a delegate of another.
       
   241      *
       
   242      * @return true if this class is a delegate of another
       
   243      */
       
   244     public boolean isDelegated() { return !this.equals(beanContextChildPeer); }
       
   245 
       
   246     /**
       
   247      * Report a bound property update to any registered listeners. No event is
       
   248      * fired if old and new are equal and non-null.
       
   249      * @param name The programmatic name of the property that was changed
       
   250      * @param oldValue  The old value of the property
       
   251      * @param newValue  The new value of the property
       
   252      */
       
   253     public void firePropertyChange(String name, Object oldValue, Object newValue) {
       
   254         pcSupport.firePropertyChange(name, oldValue, newValue);
       
   255     }
       
   256 
       
   257     /**
       
   258      * Report a vetoable property update to any registered listeners.
       
   259      * If anyone vetos the change, then fire a new event
       
   260      * reverting everyone to the old value and then rethrow
       
   261      * the PropertyVetoException. <P>
       
   262      *
       
   263      * No event is fired if old and new are equal and non-null.
       
   264      * <P>
       
   265      * @param name The programmatic name of the property that is about to
       
   266      * change
       
   267      *
       
   268      * @param oldValue The old value of the property
       
   269      * @param newValue - The new value of the property
       
   270      *
       
   271      * @throws PropertyVetoException if the recipient wishes the property
       
   272      * change to be rolled back.
       
   273      */
       
   274     public void fireVetoableChange(String name, Object oldValue, Object newValue) throws PropertyVetoException {
       
   275         vcSupport.fireVetoableChange(name, oldValue, newValue);
       
   276     }
       
   277 
       
   278     /**
       
   279      * Called from setBeanContext to validate (or otherwise) the
       
   280      * pending change in the nesting BeanContext property value.
       
   281      * Returning false will cause setBeanContext to throw
       
   282      * PropertyVetoException.
       
   283      * @param newValue the new value that has been requested for
       
   284      *  the BeanContext property
       
   285      * @return <code>true</code> if the change operation is to be vetoed
       
   286      */
       
   287     public boolean validatePendingSetBeanContext(BeanContext newValue) {
       
   288         return true;
       
   289     }
       
   290 
       
   291     /**
       
   292      * This method may be overridden by subclasses to provide their own
       
   293      * release behaviors. When invoked any resources held by this instance
       
   294      * obtained from its current BeanContext property should be released
       
   295      * since the object is no longer nested within that BeanContext.
       
   296      */
       
   297 
       
   298     protected  void releaseBeanContextResources() {
       
   299         // do nothing
       
   300     }
       
   301 
       
   302     /**
       
   303      * This method may be overridden by subclasses to provide their own
       
   304      * initialization behaviors. When invoked any resources requried by the
       
   305      * BeanContextChild should be obtained from the current BeanContext.
       
   306      */
       
   307 
       
   308     protected void initializeBeanContextResources() {
       
   309         // do nothing
       
   310     }
       
   311 
       
   312     /**
       
   313      * Write the persistence state of the object.
       
   314      */
       
   315 
       
   316     private void writeObject(ObjectOutputStream oos) throws IOException {
       
   317 
       
   318         /*
       
   319          * dont serialize if we are delegated and the delegator isnt also
       
   320          * serializable.
       
   321          */
       
   322 
       
   323         if (!equals(beanContextChildPeer) && !(beanContextChildPeer instanceof Serializable))
       
   324             throw new IOException("BeanContextChildSupport beanContextChildPeer not Serializable");
       
   325 
       
   326         else
       
   327             oos.defaultWriteObject();
       
   328 
       
   329     }
       
   330 
       
   331 
       
   332     /**
       
   333      * Restore a persistent object, must wait for subsequent setBeanContext()
       
   334      * to fully restore any resources obtained from the new nesting
       
   335      * BeanContext
       
   336      */
       
   337 
       
   338     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
       
   339         ois.defaultReadObject();
       
   340     }
       
   341 
       
   342     /*
       
   343      * fields
       
   344      */
       
   345 
       
   346     /**
       
   347      * The <code>BeanContext</code> in which
       
   348      * this <code>BeanContextChild</code> is nested.
       
   349      */
       
   350     public    BeanContextChild      beanContextChildPeer;
       
   351 
       
   352    /**
       
   353     * The <tt>PropertyChangeSupport</tt> associated with this
       
   354     * <tt>BeanContextChildSupport</tt>.
       
   355     */
       
   356     protected PropertyChangeSupport pcSupport;
       
   357 
       
   358    /**
       
   359     * The <tt>VetoableChangeSupport</tt> associated with this
       
   360     * <tt>BeanContextChildSupport</tt>.
       
   361     */
       
   362     protected VetoableChangeSupport vcSupport;
       
   363 
       
   364     protected transient BeanContext           beanContext;
       
   365 
       
   366    /**
       
   367     * A flag indicating that there has been
       
   368     * at least one <code>PropertyChangeVetoException</code>
       
   369     * thrown for the attempted setBeanContext operation.
       
   370     */
       
   371     protected transient boolean               rejectedSetBCOnce;
       
   372 
       
   373 }