1. /*
  2. * @(#)BeanContextChildSupport.java 1.16 04/03/04
  3. *
  4. * Copyright 2004 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.16, 03/04/04
  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. * Add a PropertyChangeListener for a specific property.
  104. * The same listener object may be added more than once. For each
  105. * property, the listener will be invoked the number of times it was added
  106. * for that property.
  107. * If <code>name</code> or <code>pcl</code> is null, no exception is thrown
  108. * and no action is taken.
  109. *
  110. * @param name The name of the property to listen on
  111. * @param pcl The <code>PropertyChangeListener</code> to be added
  112. */
  113. public void addPropertyChangeListener(String name, PropertyChangeListener pcl) {
  114. pcSupport.addPropertyChangeListener(name, pcl);
  115. }
  116. /**
  117. * Remove a PropertyChangeListener for a specific property.
  118. * If <code>pcl</code> was added more than once to the same event
  119. * source for the specified property, it will be notified one less time
  120. * after being removed.
  121. * If <code>name</code> is null, no exception is thrown
  122. * and no action is taken.
  123. * If <code>pcl</code> is null, or was never added for the specified
  124. * property, no exception is thrown and no action is taken.
  125. *
  126. * @param name The name of the property that was listened on
  127. * @param pcl The PropertyChangeListener to be removed
  128. */
  129. public void removePropertyChangeListener(String name, PropertyChangeListener pcl) {
  130. pcSupport.removePropertyChangeListener(name, pcl);
  131. }
  132. /**
  133. * Add a VetoableChangeListener for a specific property.
  134. * The same listener object may be added more than once. For each
  135. * property, the listener will be invoked the number of times it was added
  136. * for that property.
  137. * If <code>name</code> or <code>vcl</code> is null, no exception is thrown
  138. * and no action is taken.
  139. *
  140. * @param name The name of the property to listen on
  141. * @param vcl The <code>VetoableChangeListener</code> to be added
  142. */
  143. public void addVetoableChangeListener(String name, VetoableChangeListener vcl) {
  144. vcSupport.addVetoableChangeListener(name, vcl);
  145. }
  146. /**
  147. * Removes a <code>VetoableChangeListener</code>.
  148. * If <code>pcl</code> was added more than once to the same event
  149. * source for the specified property, it will be notified one less time
  150. * after being removed.
  151. * If <code>name</code> is null, no exception is thrown
  152. * and no action is taken.
  153. * If <code>vcl</code> is null, or was never added for the specified
  154. * property, no exception is thrown and no action is taken.
  155. *
  156. * @param name The name of the property that was listened on
  157. * @param vcl The <code>VetoableChangeListener</code> to be removed
  158. */
  159. public void removeVetoableChangeListener(String name, VetoableChangeListener vcl) {
  160. vcSupport.removeVetoableChangeListener(name, vcl);
  161. }
  162. /**
  163. * A service provided by the nesting BeanContext has been revoked.
  164. *
  165. * Subclasses may override this method in order to implement their own
  166. * behaviors.
  167. * @param bcsre The <code>BeanContextServiceRevokedEvent</code> fired as a
  168. * result of a service being revoked
  169. */
  170. public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) { }
  171. /**
  172. * A new service is available from the nesting BeanContext.
  173. *
  174. * Subclasses may override this method in order to implement their own
  175. * behaviors
  176. * @param bcsae The BeanContextServiceAvailableEvent fired as a
  177. * result of a service becoming available
  178. *
  179. */
  180. public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) { }
  181. /**
  182. * Gets the <tt>BeanContextChild</tt> associated with this
  183. * <tt>BeanContextChildSupport</tt>.
  184. *
  185. * @return the <tt>BeanContextChild</tt> peer of this class
  186. */
  187. public BeanContextChild getBeanContextChildPeer() { return beanContextChildPeer; }
  188. /**
  189. * Reports whether or not this class is a delegate of another.
  190. *
  191. * @return true if this class is a delegate of another
  192. */
  193. public boolean isDelegated() { return !this.equals(beanContextChildPeer); }
  194. /**
  195. * Report a bound property update to any registered listeners. No event is
  196. * fired if old and new are equal and non-null.
  197. * @param name The programmatic name of the property that was changed
  198. * @param oldValue The old value of the property
  199. * @param newValue The new value of the property
  200. */
  201. public void firePropertyChange(String name, Object oldValue, Object newValue) {
  202. pcSupport.firePropertyChange(name, oldValue, newValue);
  203. }
  204. /**
  205. * Report a vetoable property update to any registered listeners.
  206. * If anyone vetos the change, then fire a new event
  207. * reverting everyone to the old value and then rethrow
  208. * the PropertyVetoException. <P>
  209. *
  210. * No event is fired if old and new are equal and non-null.
  211. * <P>
  212. * @param name The programmatic name of the property that is about to
  213. * change
  214. *
  215. * @param oldValue The old value of the property
  216. * @param newValue - The new value of the property
  217. *
  218. * @throws PropertyVetoException if the recipient wishes the property
  219. * change to be rolled back.
  220. */
  221. public void fireVetoableChange(String name, Object oldValue, Object newValue) throws PropertyVetoException {
  222. vcSupport.fireVetoableChange(name, oldValue, newValue);
  223. }
  224. /**
  225. * Called from setBeanContext to validate (or otherwise) the
  226. * pending change in the nesting BeanContext property value.
  227. * Returning false will cause setBeanContext to throw
  228. * PropertyVetoException.
  229. * @param newValue the new value that has been requested for
  230. * the BeanContext property
  231. * @return <code>true</code> if the change operation is to be vetoed
  232. */
  233. public boolean validatePendingSetBeanContext(BeanContext newValue) {
  234. return true;
  235. }
  236. /**
  237. * This method may be overridden by subclasses to provide their own
  238. * release behaviors. When invoked any resources held by this instance
  239. * obtained from its current BeanContext property should be released
  240. * since the object is no longer nested within that BeanContext.
  241. */
  242. protected void releaseBeanContextResources() {
  243. // do nothing
  244. }
  245. /**
  246. * This method may be overridden by subclasses to provide their own
  247. * initialization behaviors. When invoked any resources requried by the
  248. * BeanContextChild should be obtained from the current BeanContext.
  249. */
  250. protected void initializeBeanContextResources() {
  251. // do nothing
  252. }
  253. /**
  254. * Write the persistence state of the object.
  255. */
  256. private void writeObject(ObjectOutputStream oos) throws IOException {
  257. /*
  258. * dont serialize if we are delegated and the delegator isnt also
  259. * serializable.
  260. */
  261. if (!equals(beanContextChildPeer) && !(beanContextChildPeer instanceof Serializable))
  262. throw new IOException("BeanContextChildSupport beanContextChildPeer not Serializable");
  263. else
  264. oos.defaultWriteObject();
  265. }
  266. /**
  267. * Restore a persistent object, must wait for subsequent setBeanContext()
  268. * to fully restore any resources obtained from the new nesting
  269. * BeanContext
  270. */
  271. private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
  272. ois.defaultReadObject();
  273. }
  274. /*
  275. * fields
  276. */
  277. /**
  278. * The <code>BeanContext</code> in which
  279. * this <code>BeanContextChild</code> is nested.
  280. */
  281. public BeanContextChild beanContextChildPeer;
  282. /**
  283. * The <tt>PropertyChangeSupport</tt> associated with this
  284. * <tt>BeanContextChildSupport</tt>.
  285. */
  286. protected PropertyChangeSupport pcSupport;
  287. /**
  288. * The <tt>VetoableChangeSupport</tt> associated with this
  289. * <tt>BeanContextChildSupport</tt>.
  290. */
  291. protected VetoableChangeSupport vcSupport;
  292. protected transient BeanContext beanContext;
  293. /**
  294. * A flag indicating that there has been
  295. * at least one <code>PropertyChangeVetoException</code>
  296. * thrown for the attempted setBeanContext operation.
  297. */
  298. protected transient boolean rejectedSetBCOnce;
  299. }