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