1. /*
  2. * @(#)BeanContextChildSupport.java 1.10 00/02/02
  3. *
  4. * Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.beans.beancontext;
  11. import java.beans.PropertyChangeEvent;
  12. import java.beans.PropertyChangeListener;
  13. import java.beans.PropertyChangeSupport;
  14. import java.beans.VetoableChangeListener;
  15. import java.beans.VetoableChangeSupport;
  16. import java.beans.PropertyVetoException;
  17. import java.io.IOException;
  18. import java.io.ObjectInputStream;
  19. import java.io.ObjectOutputStream;
  20. import java.io.Serializable;
  21. /**
  22. * <p>
  23. * This is a general support class to provide support for implementing the
  24. * BeanContextChild protocol.
  25. *
  26. * This class may either be directly subclassed, or encapsulated and delegated
  27. * to in order to implement this interface for a given component.
  28. * </p>
  29. *
  30. * @author Laurence P. G. Cable
  31. * @version 1.10, 02/02/00
  32. * @since 1.2
  33. *
  34. * @seealso java.beans.beancontext.BeanContext
  35. * @seealso java.beans.beancontext.BeanContextServices
  36. * @seealso java.beans.beancontext.BeanContextChild
  37. */
  38. public class BeanContextChildSupport implements BeanContextChild, BeanContextServicesListener, Serializable {
  39. static final long serialVersionUID = 6328947014421475877L;
  40. /**
  41. * construct a BeanContextChildSupport where this class has been
  42. * subclassed in order to implement the JavaBean component itself.
  43. */
  44. public BeanContextChildSupport() {
  45. super();
  46. beanContextChildPeer = this;
  47. pcSupport = new PropertyChangeSupport(beanContextChildPeer);
  48. vcSupport = new VetoableChangeSupport(beanContextChildPeer);
  49. }
  50. /**
  51. * construct a BeanContextChildSupport where the JavaBean component
  52. * itself implements BeanContextChild, and encapsulates this, delegating
  53. * that interface to this implementation
  54. */
  55. public BeanContextChildSupport(BeanContextChild bcc) {
  56. super();
  57. beanContextChildPeer = (bcc != null) ? bcc : this;
  58. pcSupport = new PropertyChangeSupport(beanContextChildPeer);
  59. vcSupport = new VetoableChangeSupport(beanContextChildPeer);
  60. }
  61. /**
  62. * Sets the <code>BeanContext</code> for
  63. * this <code>BeanContextChildSupport</code>.
  64. * @param bc the new value to be assigned to the <code>BeanContext</code>
  65. * property
  66. * @throws <code>PropertyVetoException</code> if the change is rejected
  67. */
  68. public synchronized void setBeanContext(BeanContext bc) throws PropertyVetoException {
  69. if (bc == beanContext) return;
  70. BeanContext oldValue = beanContext;
  71. BeanContext newValue = bc;
  72. if (!rejectedSetBCOnce) {
  73. if (rejectedSetBCOnce = !validatePendingSetBeanContext(bc)) {
  74. throw new PropertyVetoException(
  75. "setBeanContext() change rejected:",
  76. new PropertyChangeEvent(beanContextChildPeer, "beanContext", oldValue, newValue)
  77. );
  78. }
  79. try {
  80. fireVetoableChange("beanContext",
  81. oldValue,
  82. newValue
  83. );
  84. } catch (PropertyVetoException pve) {
  85. rejectedSetBCOnce = true;
  86. throw pve; // re-throw
  87. }
  88. }
  89. if (beanContext != null) releaseBeanContextResources();
  90. beanContext = newValue;
  91. rejectedSetBCOnce = false;
  92. firePropertyChange("beanContext",
  93. oldValue,
  94. newValue
  95. );
  96. if (beanContext != null) initializeBeanContextResources();
  97. }
  98. /**
  99. * Gets the nesting <code>BeanContext</code>
  100. * for this <code>BeanContextChildSupport</code>.
  101. * @return the nesting <code>BeanContext</code> for
  102. * this <code>BeanContextChildSupport</code>.
  103. */
  104. public synchronized BeanContext getBeanContext() { return beanContext; }
  105. /**
  106. * Adds a property change listener.
  107. * @param name The name of the property to listen on
  108. * @param pcl The <code>PropertyChangeListener</code> to be added
  109. */
  110. public void addPropertyChangeListener(String name, PropertyChangeListener pcl) {
  111. pcSupport.addPropertyChangeListener(name, pcl);
  112. }
  113. /**
  114. * Remove a property change listener.
  115. * @param name The name of the property that was listened on
  116. * @param pcl The PropertyChangeListener to be removed
  117. */
  118. public void removePropertyChangeListener(String name, PropertyChangeListener pcl) {
  119. pcSupport.removePropertyChangeListener(name, pcl);
  120. }
  121. /**
  122. * Adds a <code>VetoableChangeListener</code>.
  123. * @param name The name of the property to listen on
  124. * @param vcl The <code>VetoableChangeListener</code> to be added
  125. */
  126. public void addVetoableChangeListener(String name, VetoableChangeListener vcl) {
  127. vcSupport.addVetoableChangeListener(name, vcl);
  128. }
  129. /**
  130. * Removes a <code>VetoableChangeListener</code>.
  131. * @param name The name of the property that was listened on
  132. * @param vcl The <code>VetoableChangeListener</code> to be removed
  133. */
  134. public void removeVetoableChangeListener(String name, VetoableChangeListener vcl) {
  135. vcSupport.removeVetoableChangeListener(name, vcl);
  136. }
  137. /**
  138. * A service provided by the nesting BeanContext has been revoked.
  139. *
  140. * Subclasses may override this method in order to implement their own
  141. * behaviors.
  142. * @param bcsre The <code>BeanContextServiceRevokedEvent</code> fired as a
  143. * result of a service being revoked
  144. */
  145. public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) { }
  146. /**
  147. * A new service is available from the nesting BeanContext.
  148. *
  149. * Subclasses may override this method in order to implement their own
  150. * behaviors
  151. * @param bcsae The BeanContextServiceAvailableEvent fired as a
  152. * result of a service becoming available
  153. *
  154. */
  155. public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) { }
  156. /**
  157. * Gets the <tt>BeanContextChild</tt> associated with this
  158. * <tt>BeanContextChildSupport</tt>.
  159. *
  160. * @return the <tt>BeanContextChild</tt> peer of this class
  161. */
  162. public BeanContextChild getBeanContextChildPeer() { return beanContextChildPeer; }
  163. /**
  164. * Reports whether or not this class is a delegate of another.
  165. *
  166. * @return true if this class is a delegate of another
  167. */
  168. public boolean isDelegated() { return !this.equals(beanContextChildPeer); }
  169. /**
  170. * Report a bound property update to any registered listeners. No event is
  171. * fired if old and new are equal and non-null.
  172. * @param name The programmatic name of the property that was changed
  173. * @param oldValue The old value of the property
  174. * @param newValue The new value of the property
  175. */
  176. public void firePropertyChange(String name, Object oldValue, Object newValue) {
  177. pcSupport.firePropertyChange(name, oldValue, newValue);
  178. }
  179. /**
  180. * Report a vetoable property update to any registered listeners.
  181. * If anyone vetos the change, then fire a new event
  182. * reverting everyone to the old value and then rethrow
  183. * the PropertyVetoException. <P>
  184. *
  185. * No event is fired if old and new are equal and non-null.
  186. * <P>
  187. * @param name The programmatic name of the property that is about to
  188. * change
  189. *
  190. * @param oldValue The old value of the property
  191. * @param newValue - The new value of the property
  192. *
  193. * @throws PropertyVetoException if the recipient wishes the property
  194. * change to be rolled back.
  195. */
  196. public void fireVetoableChange(String name, Object oldValue, Object newValue) throws PropertyVetoException {
  197. vcSupport.fireVetoableChange(name, oldValue, newValue);
  198. }
  199. /**
  200. * Called from setBeanContext to validate (or otherwise) the
  201. * pending change in the nesting BeanContext property value.
  202. * Returning false will cause setBeanContext to throw
  203. * PropertyVetoException.
  204. * @param newValue the new value that has been requested for
  205. * the BeanContext property
  206. * @return <code>true</code> if the change operation is to be vetoed
  207. */
  208. public boolean validatePendingSetBeanContext(BeanContext newValue) {
  209. return true;
  210. }
  211. /**
  212. * This method may be overridden by subclasses to provide their own
  213. * release behaviors. When invoked any resources held by this instance
  214. * obtained from its current BeanContext property should be released
  215. * since the object is no longer nested within that BeanContext.
  216. */
  217. protected void releaseBeanContextResources() {
  218. // do nothing
  219. }
  220. /**
  221. * This method may be overridden by subclasses to provide their own
  222. * initialization behaviors. When invoked any resources requried by the
  223. * BeanContextChild should be obtained from the current BeanContext.
  224. */
  225. protected void initializeBeanContextResources() {
  226. // do nothing
  227. }
  228. /**
  229. * Write the persistence state of the object.
  230. */
  231. private void writeObject(ObjectOutputStream oos) throws IOException {
  232. /*
  233. * dont serialize if we are delegated and the delegator isnt also
  234. * serializable.
  235. */
  236. if (!equals(beanContextChildPeer) && !(beanContextChildPeer instanceof Serializable))
  237. throw new IOException("BeanContextChildSupport beanContextChildPeer not Serializable");
  238. else
  239. oos.defaultWriteObject();
  240. }
  241. /**
  242. * Restore a persistent object, must wait for subsequent setBeanContext()
  243. * to fully restore any resources obtained from the new nesting
  244. * BeanContext
  245. */
  246. private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
  247. ois.defaultReadObject();
  248. }
  249. /*
  250. * fields
  251. */
  252. /**
  253. * The <code>BeanContext</code> in which
  254. * this <code>BeanContextChild</code> is nested.
  255. */
  256. public BeanContextChild beanContextChildPeer;
  257. /**
  258. * The <tt>PropertyChangeSupport</tt> associated with this
  259. * <tt>BeanContextChildSupport</tt>.
  260. */
  261. protected PropertyChangeSupport pcSupport;
  262. /**
  263. * The <tt>VetoableChangeSupport</tt> associated with this
  264. * <tt>BeanContextChildSupport</tt>.
  265. */
  266. protected VetoableChangeSupport vcSupport;
  267. protected transient BeanContext beanContext;
  268. /**
  269. * A flag indicating that there has been
  270. * at least one <code>PropertyChangeVetoException</code>
  271. * thrown for the attempted setBeanContext operation.
  272. */
  273. protected transient boolean rejectedSetBCOnce;
  274. }