Path: blob/master/src/java.desktop/share/classes/java/beans/beancontext/BeanContextChildSupport.java
41159 views
/*1* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.beans.beancontext;2627import java.beans.PropertyChangeEvent;28import java.beans.PropertyChangeListener;29import java.beans.PropertyChangeSupport;30import java.beans.PropertyVetoException;31import java.beans.VetoableChangeListener;32import java.beans.VetoableChangeSupport;33import java.io.IOException;34import java.io.ObjectInputStream;35import java.io.ObjectOutputStream;36import java.io.Serial;37import java.io.Serializable;3839/**40* <p>41* This is a general support class to provide support for implementing the42* BeanContextChild protocol.43*44* This class may either be directly subclassed, or encapsulated and delegated45* to in order to implement this interface for a given component.46* </p>47*48* @author Laurence P. G. Cable49* @since 1.250*51* @see java.beans.beancontext.BeanContext52* @see java.beans.beancontext.BeanContextServices53* @see java.beans.beancontext.BeanContextChild54*/5556public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable {5758/**59* Use serialVersionUID from JDK 1.2 for interoperability.60*/61@Serial62private static final long serialVersionUID = 6328947014421475877L;6364/**65* construct a BeanContextChildSupport where this class has been66* subclassed in order to implement the JavaBean component itself.67*/6869public BeanContextChildSupport() {70super();7172beanContextChildPeer = this;7374pcSupport = new PropertyChangeSupport(beanContextChildPeer);75vcSupport = new VetoableChangeSupport(beanContextChildPeer);76}7778/**79* construct a BeanContextChildSupport where the JavaBean component80* itself implements BeanContextChild, and encapsulates this, delegating81* that interface to this implementation82* @param bcc the underlying bean context child83*/8485public BeanContextChildSupport(BeanContextChild bcc) {86super();8788beanContextChildPeer = (bcc != null) ? bcc : this;8990pcSupport = new PropertyChangeSupport(beanContextChildPeer);91vcSupport = new VetoableChangeSupport(beanContextChildPeer);92}9394/**95* Sets the {@code BeanContext} for96* this {@code BeanContextChildSupport}.97* @param bc the new value to be assigned to the {@code BeanContext}98* property99* @throws PropertyVetoException if the change is rejected100*/101public synchronized void setBeanContext(BeanContext bc) throws PropertyVetoException {102if (bc == beanContext) return;103104BeanContext oldValue = beanContext;105BeanContext newValue = bc;106107if (!rejectedSetBCOnce) {108if (rejectedSetBCOnce = !validatePendingSetBeanContext(bc)) {109throw new PropertyVetoException(110"setBeanContext() change rejected:",111new PropertyChangeEvent(beanContextChildPeer, "beanContext", oldValue, newValue)112);113}114115try {116fireVetoableChange("beanContext",117oldValue,118newValue119);120} catch (PropertyVetoException pve) {121rejectedSetBCOnce = true;122123throw pve; // re-throw124}125}126127if (beanContext != null) releaseBeanContextResources();128129beanContext = newValue;130rejectedSetBCOnce = false;131132firePropertyChange("beanContext",133oldValue,134newValue135);136137if (beanContext != null) initializeBeanContextResources();138}139140/**141* Gets the nesting {@code BeanContext}142* for this {@code BeanContextChildSupport}.143* @return the nesting {@code BeanContext} for144* this {@code BeanContextChildSupport}.145*/146public synchronized BeanContext getBeanContext() { return beanContext; }147148/**149* Add a PropertyChangeListener for a specific property.150* The same listener object may be added more than once. For each151* property, the listener will be invoked the number of times it was added152* for that property.153* If {@code name} or {@code pcl} is null, no exception is thrown154* and no action is taken.155*156* @param name The name of the property to listen on157* @param pcl The {@code PropertyChangeListener} to be added158*/159public void addPropertyChangeListener(String name, PropertyChangeListener pcl) {160pcSupport.addPropertyChangeListener(name, pcl);161}162163/**164* Remove a PropertyChangeListener for a specific property.165* If {@code pcl} was added more than once to the same event166* source for the specified property, it will be notified one less time167* after being removed.168* If {@code name} is null, no exception is thrown169* and no action is taken.170* If {@code pcl} is null, or was never added for the specified171* property, no exception is thrown and no action is taken.172*173* @param name The name of the property that was listened on174* @param pcl The PropertyChangeListener to be removed175*/176public void removePropertyChangeListener(String name, PropertyChangeListener pcl) {177pcSupport.removePropertyChangeListener(name, pcl);178}179180/**181* Add a VetoableChangeListener for a specific property.182* The same listener object may be added more than once. For each183* property, the listener will be invoked the number of times it was added184* for that property.185* If {@code name} or {@code vcl} is null, no exception is thrown186* and no action is taken.187*188* @param name The name of the property to listen on189* @param vcl The {@code VetoableChangeListener} to be added190*/191public void addVetoableChangeListener(String name, VetoableChangeListener vcl) {192vcSupport.addVetoableChangeListener(name, vcl);193}194195/**196* Removes a {@code VetoableChangeListener}.197* If {@code pcl} was added more than once to the same event198* source for the specified property, it will be notified one less time199* after being removed.200* If {@code name} is null, no exception is thrown201* and no action is taken.202* If {@code vcl} is null, or was never added for the specified203* property, no exception is thrown and no action is taken.204*205* @param name The name of the property that was listened on206* @param vcl The {@code VetoableChangeListener} to be removed207*/208public void removeVetoableChangeListener(String name, VetoableChangeListener vcl) {209vcSupport.removeVetoableChangeListener(name, vcl);210}211212/**213* A service provided by the nesting BeanContext has been revoked.214*215* Subclasses may override this method in order to implement their own216* behaviors.217* @param bcsre The {@code BeanContextServiceRevokedEvent} fired as a218* result of a service being revoked219*/220public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) { }221222/**223* A new service is available from the nesting BeanContext.224*225* Subclasses may override this method in order to implement their own226* behaviors227* @param bcsae The BeanContextServiceAvailableEvent fired as a228* result of a service becoming available229*230*/231public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) { }232233/**234* Gets the {@code BeanContextChild} associated with this235* {@code BeanContextChildSupport}.236*237* @return the {@code BeanContextChild} peer of this class238*/239public BeanContextChild getBeanContextChildPeer() { return beanContextChildPeer; }240241/**242* Reports whether or not this class is a delegate of another.243*244* @return true if this class is a delegate of another245*/246public boolean isDelegated() { return !this.equals(beanContextChildPeer); }247248/**249* Report a bound property update to any registered listeners. No event is250* fired if old and new are equal and non-null.251* @param name The programmatic name of the property that was changed252* @param oldValue The old value of the property253* @param newValue The new value of the property254*/255public void firePropertyChange(String name, Object oldValue, Object newValue) {256pcSupport.firePropertyChange(name, oldValue, newValue);257}258259/**260* Report a vetoable property update to any registered listeners.261* If anyone vetos the change, then fire a new event262* reverting everyone to the old value and then rethrow263* the PropertyVetoException. <P>264*265* No event is fired if old and new are equal and non-null.266*267* @param name The programmatic name of the property that is about to268* change269*270* @param oldValue The old value of the property271* @param newValue - The new value of the property272*273* @throws PropertyVetoException if the recipient wishes the property274* change to be rolled back.275*/276public void fireVetoableChange(String name, Object oldValue, Object newValue) throws PropertyVetoException {277vcSupport.fireVetoableChange(name, oldValue, newValue);278}279280/**281* Called from setBeanContext to validate (or otherwise) the282* pending change in the nesting BeanContext property value.283* Returning false will cause setBeanContext to throw284* PropertyVetoException.285* @param newValue the new value that has been requested for286* the BeanContext property287* @return {@code true} if the change operation is to be vetoed288*/289public boolean validatePendingSetBeanContext(BeanContext newValue) {290return true;291}292293/**294* This method may be overridden by subclasses to provide their own295* release behaviors. When invoked any resources held by this instance296* obtained from its current BeanContext property should be released297* since the object is no longer nested within that BeanContext.298*/299300protected void releaseBeanContextResources() {301// do nothing302}303304/**305* This method may be overridden by subclasses to provide their own306* initialization behaviors. When invoked any resources required by the307* BeanContextChild should be obtained from the current BeanContext.308*/309310protected void initializeBeanContextResources() {311// do nothing312}313314/**315* Write the persistence state of the object.316*317* @param oos the {@code ObjectOutputStream} to write318* @throws IOException if an I/O error occurs319*/320@Serial321private void writeObject(ObjectOutputStream oos) throws IOException {322323/*324* don't serialize if we are delegated and the delegator is not also325* serializable.326*/327328if (!equals(beanContextChildPeer) && !(beanContextChildPeer instanceof Serializable))329throw new IOException("BeanContextChildSupport beanContextChildPeer not Serializable");330331else332oos.defaultWriteObject();333334}335336337/**338* Restore a persistent object, must wait for subsequent setBeanContext()339* to fully restore any resources obtained from the new nesting BeanContext.340*341* @param ois the {@code ObjectInputStream} to read342* @throws ClassNotFoundException if the class of a serialized object could343* not be found344* @throws IOException if an I/O error occurs345*/346@Serial347private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {348ois.defaultReadObject();349}350351/*352* fields353*/354355/**356* The {@code BeanContext} in which357* this {@code BeanContextChild} is nested.358*/359@SuppressWarnings("serial") // Not statically typed as Serializable360public BeanContextChild beanContextChildPeer;361362/**363* The {@code PropertyChangeSupport} associated with this364* {@code BeanContextChildSupport}.365*/366protected PropertyChangeSupport pcSupport;367368/**369* The {@code VetoableChangeSupport} associated with this370* {@code BeanContextChildSupport}.371*/372protected VetoableChangeSupport vcSupport;373374/**375* The bean context.376*/377protected transient BeanContext beanContext;378379/**380* A flag indicating that there has been381* at least one {@code PropertyChangeVetoException}382* thrown for the attempted setBeanContext operation.383*/384protected transient boolean rejectedSetBCOnce;385386}387388389