Separatelly compiling Beans and Applet modules. Using 'code injection' to allow Beans class to perform its Applet related functionality if Applet module is around.
2 * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
26 package java.beans.beancontext;
28 import java.awt.Component;
29 import java.awt.Container;
31 import java.beans.Beans;
34 import java.beans.PropertyChangeEvent;
35 import java.beans.PropertyChangeListener;
37 import java.beans.VetoableChangeListener;
38 import java.beans.PropertyVetoException;
40 import java.beans.Visibility;
42 import java.io.IOException;
43 import java.io.InputStream;
44 import java.io.ObjectInputStream;
45 import java.io.ObjectOutputStream;
46 import java.io.Serializable;
50 import java.util.ArrayList;
51 import java.util.Collection;
52 import java.util.HashMap;
53 import java.util.Iterator;
54 import java.util.Locale;
59 * This helper class provides a utility implementation of the
60 * java.beans.beancontext.BeanContext interface.
63 * Since this class directly implements the BeanContext interface, the class
64 * can, and is intended to be used either by subclassing this implementation,
65 * or via ad-hoc delegation of an instance of this class from another.
68 * @author Laurence P. G. Cable
71 public class BeanContextSupport extends BeanContextChildSupport
72 implements BeanContext,
74 PropertyChangeListener,
75 VetoableChangeListener {
77 // Fix for bug 4282900 to pass JCK regression test
78 static final long serialVersionUID = -4879613978649577204L;
82 * Construct a BeanContextSupport instance
85 * @param peer The peer <tt>BeanContext</tt> we are
86 * supplying an implementation for,
88 * if this object is its own peer
89 * @param lcle The current Locale for this BeanContext. If
90 * <tt>lcle</tt> is <tt>null</tt>, the default locale
91 * is assigned to the <tt>BeanContext</tt> instance.
92 * @param dTime The initial state,
93 * <tt>true</tt> if in design mode,
94 * <tt>false</tt> if runtime.
95 * @param visible The initial visibility.
96 * @see java.util.Locale#getDefault()
97 * @see java.util.Locale#setDefault(java.util.Locale)
99 public BeanContextSupport(BeanContext peer, Locale lcle, boolean dTime, boolean visible) {
102 locale = lcle != null ? lcle : Locale.getDefault();
104 okToUseGui = visible;
110 * Create an instance using the specified Locale and design mode.
112 * @param peer The peer <tt>BeanContext</tt> we
113 * are supplying an implementation for,
114 * or <tt>null</tt> if this object is its own peer
115 * @param lcle The current Locale for this <tt>BeanContext</tt>. If
116 * <tt>lcle</tt> is <tt>null</tt>, the default locale
117 * is assigned to the <tt>BeanContext</tt> instance.
118 * @param dtime The initial state, <tt>true</tt>
120 * <tt>false</tt> if runtime.
121 * @see java.util.Locale#getDefault()
122 * @see java.util.Locale#setDefault(java.util.Locale)
124 public BeanContextSupport(BeanContext peer, Locale lcle, boolean dtime) {
125 this (peer, lcle, dtime, true);
129 * Create an instance using the specified locale
131 * @param peer The peer BeanContext we are
132 * supplying an implementation for,
133 * or <tt>null</tt> if this object
135 * @param lcle The current Locale for this
136 * <tt>BeanContext</tt>. If
137 * <tt>lcle</tt> is <tt>null</tt>,
139 * is assigned to the <tt>BeanContext</tt>
141 * @see java.util.Locale#getDefault()
142 * @see java.util.Locale#setDefault(java.util.Locale)
144 public BeanContextSupport(BeanContext peer, Locale lcle) {
145 this (peer, lcle, false, true);
149 * Create an instance using with a default locale
151 * @param peer The peer <tt>BeanContext</tt> we are
152 * supplying an implementation for,
153 * or <tt>null</tt> if this object
156 public BeanContextSupport(BeanContext peer) {
157 this (peer, null, false, true);
161 * Create an instance that is not a delegate of another object
164 public BeanContextSupport() {
165 this (null, null, false, true);
169 * Gets the instance of <tt>BeanContext</tt> that
170 * this object is providing the implementation for.
171 * @return the BeanContext instance
173 public BeanContext getBeanContextPeer() { return (BeanContext)getBeanContextChildPeer(); }
177 * The instantiateChild method is a convenience hook
178 * in BeanContext to simplify
179 * the task of instantiating a Bean, nested,
180 * into a <tt>BeanContext</tt>.
183 * The semantics of the beanName parameter are defined by java.beans.Beans.instantate.
186 * @param beanName the name of the Bean to instantiate within this BeanContext
187 * @throws IOException if there is an I/O error when the bean is being deserialized
188 * @throws ClassNotFoundException if the class
189 * identified by the beanName parameter is not found
190 * @return the new object
192 public Object instantiateChild(String beanName)
193 throws IOException, ClassNotFoundException {
194 BeanContext bc = getBeanContextPeer();
196 return Beans.instantiate(bc.getClass().getClassLoader(), beanName, bc);
200 * Gets the number of children currently nested in
203 * @return number of children
206 synchronized(children) {
207 return children.size();
212 * Reports whether or not this
213 * <tt>BeanContext</tt> is empty.
214 * A <tt>BeanContext</tt> is considered
215 * empty when it contains zero
217 * @return if there are not children
219 public boolean isEmpty() {
220 synchronized(children) {
221 return children.isEmpty();
226 * Determines whether or not the specified object
227 * is currently a child of this <tt>BeanContext</tt>.
228 * @param o the Object in question
229 * @return if this object is a child
231 public boolean contains(Object o) {
232 synchronized(children) {
233 return children.containsKey(o);
238 * Determines whether or not the specified object
239 * is currently a child of this <tt>BeanContext</tt>.
240 * @param o the Object in question
241 * @return if this object is a child
243 public boolean containsKey(Object o) {
244 synchronized(children) {
245 return children.containsKey(o);
250 * Gets all JavaBean or <tt>BeanContext</tt> instances
251 * currently nested in this <tt>BeanContext</tt>.
252 * @return an <tt>Iterator</tt> of the nested children
254 public Iterator iterator() {
255 synchronized(children) {
256 return new BCSIterator(children.keySet().iterator());
261 * Gets all JavaBean or <tt>BeanContext</tt>
262 * instances currently nested in this BeanContext.
264 public Object[] toArray() {
265 synchronized(children) {
266 return children.keySet().toArray();
271 * Gets an array containing all children of
272 * this <tt>BeanContext</tt> that match
273 * the types contained in arry.
274 * @param arry The array of object
275 * types that are of interest.
276 * @return an array of children
278 public Object[] toArray(Object[] arry) {
279 synchronized(children) {
280 return children.keySet().toArray(arry);
285 /************************************************************************/
288 * protected final subclass that encapsulates an iterator but implements
289 * a noop remove() method.
292 protected static final class BCSIterator implements Iterator {
293 BCSIterator(Iterator i) { super(); src = i; }
295 public boolean hasNext() { return src.hasNext(); }
296 public Object next() { return src.next(); }
297 public void remove() { /* do nothing */ }
299 private Iterator src;
302 /************************************************************************/
305 * protected nested class containing per child information, an instance
306 * of which is associated with each child in the "children" hashtable.
307 * subclasses can extend this class to include their own per-child state.
309 * Note that this 'value' is serialized with the corresponding child 'key'
310 * when the BeanContextSupport is serialized.
313 protected class BCSChild implements Serializable {
315 private static final long serialVersionUID = -5815286101609939109L;
317 BCSChild(Object bcc, Object peer) {
324 Object getChild() { return child; }
326 void setRemovePending(boolean v) { removePending = v; }
328 boolean isRemovePending() { return removePending; }
330 boolean isProxyPeer() { return proxyPeer != null; }
332 Object getProxyPeer() { return proxyPeer; }
338 private Object child;
339 private Object proxyPeer;
341 private transient boolean removePending;
346 * Subclasses can override this method to insert their own subclass
347 * of Child without having to override add() or the other Collection
348 * methods that add children to the set.
351 * @param targetChild the child to create the Child on behalf of
352 * @param peer the peer if the tragetChild and the peer are related by an implementation of BeanContextProxy
355 protected BCSChild createBCSChild(Object targetChild, Object peer) {
356 return new BCSChild(targetChild, peer);
359 /************************************************************************/
362 * Adds/nests a child within this <tt>BeanContext</tt>.
364 * Invoked as a side effect of java.beans.Beans.instantiate().
365 * If the child object is not valid for adding then this method
366 * throws an IllegalStateException.
370 * @param targetChild The child objects to nest
371 * within this <tt>BeanContext</tt>
372 * @return true if the child was added successfully.
373 * @see #validatePendingAdd
375 public boolean add(Object targetChild) {
377 if (targetChild == null) throw new IllegalArgumentException();
379 // The specification requires that we do nothing if the child
380 // is already nested herein.
382 if (children.containsKey(targetChild)) return false; // test before locking
384 synchronized(BeanContext.globalHierarchyLock) {
385 if (children.containsKey(targetChild)) return false; // check again
387 if (!validatePendingAdd(targetChild)) {
388 throw new IllegalStateException();
392 // The specification requires that we invoke setBeanContext() on the
393 // newly added child if it implements the java.beans.beancontext.BeanContextChild interface
395 BeanContextChild cbcc = getChildBeanContextChild(targetChild);
396 BeanContextChild bccp = null;
398 synchronized(targetChild) {
400 if (targetChild instanceof BeanContextProxy) {
401 bccp = ((BeanContextProxy)targetChild).getBeanContextProxy();
403 if (bccp == null) throw new NullPointerException("BeanContextPeer.getBeanContextProxy()");
406 BCSChild bcsc = createBCSChild(targetChild, bccp);
407 BCSChild pbcsc = null;
409 synchronized (children) {
410 children.put(targetChild, bcsc);
412 if (bccp != null) children.put(bccp, pbcsc = createBCSChild(bccp, targetChild));
415 if (cbcc != null) synchronized(cbcc) {
417 cbcc.setBeanContext(getBeanContextPeer());
418 } catch (PropertyVetoException pve) {
420 synchronized (children) {
421 children.remove(targetChild);
423 if (bccp != null) children.remove(bccp);
426 throw new IllegalStateException();
429 cbcc.addPropertyChangeListener("beanContext", childPCL);
430 cbcc.addVetoableChangeListener("beanContext", childVCL);
433 Visibility v = getChildVisibility(targetChild);
442 if (getChildSerializable(targetChild) != null) serializable++;
444 childJustAddedHook(targetChild, bcsc);
447 v = getChildVisibility(bccp);
456 if (getChildSerializable(bccp) != null) serializable++;
458 childJustAddedHook(bccp, pbcsc);
464 // The specification requires that we fire a notification of the change
466 fireChildrenAdded(new BeanContextMembershipEvent(getBeanContextPeer(), bccp == null ? new Object[] { targetChild } : new Object[] { targetChild, bccp } ));
474 * Removes a child from this BeanContext. If the child object is not
475 * for adding then this method throws an IllegalStateException.
476 * @param targetChild The child objects to remove
477 * @see #validatePendingRemove
479 public boolean remove(Object targetChild) {
480 return remove(targetChild, true);
484 * internal remove used when removal caused by
485 * unexpected <tt>setBeanContext</tt> or
486 * by <tt>remove()</tt> invocation.
487 * @param targetChild the JavaBean, BeanContext, or Object to be removed
488 * @param callChildSetBC used to indicate that
489 * the child should be notified that it is no
490 * longer nested in this <tt>BeanContext</tt>.
492 protected boolean remove(Object targetChild, boolean callChildSetBC) {
494 if (targetChild == null) throw new IllegalArgumentException();
496 synchronized(BeanContext.globalHierarchyLock) {
497 if (!containsKey(targetChild)) return false;
499 if (!validatePendingRemove(targetChild)) {
500 throw new IllegalStateException();
503 BCSChild bcsc = (BCSChild)children.get(targetChild);
504 BCSChild pbcsc = null;
507 // we are required to notify the child that it is no longer nested here if
508 // it implements java.beans.beancontext.BeanContextChild
510 synchronized(targetChild) {
511 if (callChildSetBC) {
512 BeanContextChild cbcc = getChildBeanContextChild(targetChild);
513 if (cbcc != null) synchronized(cbcc) {
514 cbcc.removePropertyChangeListener("beanContext", childPCL);
515 cbcc.removeVetoableChangeListener("beanContext", childVCL);
518 cbcc.setBeanContext(null);
519 } catch (PropertyVetoException pve1) {
520 cbcc.addPropertyChangeListener("beanContext", childPCL);
521 cbcc.addVetoableChangeListener("beanContext", childVCL);
522 throw new IllegalStateException();
528 synchronized (children) {
529 children.remove(targetChild);
531 if (bcsc.isProxyPeer()) {
532 pbcsc = (BCSChild)children.get(peer = bcsc.getProxyPeer());
533 children.remove(peer);
537 if (getChildSerializable(targetChild) != null) serializable--;
539 childJustRemovedHook(targetChild, bcsc);
542 if (getChildSerializable(peer) != null) serializable--;
544 childJustRemovedHook(peer, pbcsc);
548 fireChildrenRemoved(new BeanContextMembershipEvent(getBeanContextPeer(), peer == null ? new Object[] { targetChild } : new Object[] { targetChild, peer } ));
556 * Tests to see if all objects in the
557 * specified <tt>Collection</tt> are children of
558 * this <tt>BeanContext</tt>.
559 * @param c the specified <tt>Collection</tt>
561 * @return <tt>true</tt> if all objects
562 * in the collection are children of
563 * this <tt>BeanContext</tt>, false if not.
565 public boolean containsAll(Collection c) {
566 synchronized(children) {
567 Iterator i = c.iterator();
569 if(!contains(i.next()))
577 * add Collection to set of Children (Unsupported)
578 * implementations must synchronized on the hierarchy lock and "children" protected field
579 * @throws UnsupportedOperationException
581 public boolean addAll(Collection c) {
582 throw new UnsupportedOperationException();
586 * remove all specified children (Unsupported)
587 * implementations must synchronized on the hierarchy lock and "children" protected field
588 * @throws UnsupportedOperationException
590 public boolean removeAll(Collection c) {
591 throw new UnsupportedOperationException();
596 * retain only specified children (Unsupported)
597 * implementations must synchronized on the hierarchy lock and "children" protected field
598 * @throws UnsupportedOperationException
600 public boolean retainAll(Collection c) {
601 throw new UnsupportedOperationException();
605 * clear the children (Unsupported)
606 * implementations must synchronized on the hierarchy lock and "children" protected field
607 * @throws UnsupportedOperationException
609 public void clear() {
610 throw new UnsupportedOperationException();
614 * Adds a BeanContextMembershipListener
616 * @param bcml the BeanContextMembershipListener to add
617 * @throws NullPointerException
620 public void addBeanContextMembershipListener(BeanContextMembershipListener bcml) {
621 if (bcml == null) throw new NullPointerException("listener");
623 synchronized(bcmListeners) {
624 if (bcmListeners.contains(bcml))
627 bcmListeners.add(bcml);
632 * Removes a BeanContextMembershipListener
634 * @param bcml the BeanContextMembershipListener to remove
635 * @throws NullPointerException
638 public void removeBeanContextMembershipListener(BeanContextMembershipListener bcml) {
639 if (bcml == null) throw new NullPointerException("listener");
641 synchronized(bcmListeners) {
642 if (!bcmListeners.contains(bcml))
645 bcmListeners.remove(bcml);
650 * @param name the name of the resource requested.
651 * @param bcc the child object making the request.
653 * @return the requested resource as an InputStream
654 * @throws NullPointerException
657 public InputStream getResourceAsStream(String name, BeanContextChild bcc) {
658 if (name == null) throw new NullPointerException("name");
659 if (bcc == null) throw new NullPointerException("bcc");
661 if (containsKey(bcc)) {
662 ClassLoader cl = bcc.getClass().getClassLoader();
664 return cl != null ? cl.getResourceAsStream(name)
665 : ClassLoader.getSystemResourceAsStream(name);
666 } else throw new IllegalArgumentException("Not a valid child");
670 * @param name the name of the resource requested.
671 * @param bcc the child object making the request.
673 * @return the requested resource as an InputStream
676 public URL getResource(String name, BeanContextChild bcc) {
677 if (name == null) throw new NullPointerException("name");
678 if (bcc == null) throw new NullPointerException("bcc");
680 if (containsKey(bcc)) {
681 ClassLoader cl = bcc.getClass().getClassLoader();
683 return cl != null ? cl.getResource(name)
684 : ClassLoader.getSystemResource(name);
685 } else throw new IllegalArgumentException("Not a valid child");
689 * Sets the new design time value for this <tt>BeanContext</tt>.
690 * @param dTime the new designTime value
692 public synchronized void setDesignTime(boolean dTime) {
693 if (designTime != dTime) {
696 firePropertyChange("designMode", Boolean.valueOf(!dTime), Boolean.valueOf(dTime));
702 * Reports whether or not this object is in
703 * currently in design time mode.
704 * @return <tt>true</tt> if in design time mode,
705 * <tt>false</tt> if not
707 public synchronized boolean isDesignTime() { return designTime; }
710 * Sets the locale of this BeanContext.
711 * @param newLocale the new locale. This method call will have
712 * no effect if newLocale is <CODE>null</CODE>.
713 * @throws PropertyVetoException if the new value is rejected
715 public synchronized void setLocale(Locale newLocale) throws PropertyVetoException {
717 if ((locale != null && !locale.equals(newLocale)) && newLocale != null) {
720 fireVetoableChange("locale", old, newLocale); // throws
724 firePropertyChange("locale", old, newLocale);
729 * Gets the locale for this <tt>BeanContext</tt>.
731 * @return the current Locale of the <tt>BeanContext</tt>
733 public synchronized Locale getLocale() { return locale; }
737 * This method is typically called from the environment in order to determine
738 * if the implementor "needs" a GUI.
741 * The algorithm used herein tests the BeanContextPeer, and its current children
742 * to determine if they are either Containers, Components, or if they implement
743 * Visibility and return needsGui() == true.
745 * @return <tt>true</tt> if the implementor needs a GUI
747 public synchronized boolean needsGui() {
748 BeanContext bc = getBeanContextPeer();
751 if (bc instanceof Visibility) return ((Visibility)bc).needsGui();
753 if (bc instanceof Container || bc instanceof Component)
757 synchronized(children) {
758 for (Iterator i = children.keySet().iterator(); i.hasNext();) {
762 return ((Visibility)c).needsGui();
763 } catch (ClassCastException cce) {
767 if (c instanceof Container || c instanceof Component)
776 * notify this instance that it may no longer render a GUI.
779 public synchronized void dontUseGui() {
783 // lets also tell the Children that can that they may not use their GUI's
784 synchronized(children) {
785 for (Iterator i = children.keySet().iterator(); i.hasNext();) {
786 Visibility v = getChildVisibility(i.next());
788 if (v != null) v.dontUseGui();
795 * Notify this instance that it may now render a GUI
798 public synchronized void okToUseGui() {
802 // lets also tell the Children that can that they may use their GUI's
803 synchronized(children) {
804 for (Iterator i = children.keySet().iterator(); i.hasNext();) {
805 Visibility v = getChildVisibility(i.next());
807 if (v != null) v.okToUseGui();
814 * Used to determine if the <tt>BeanContext</tt>
815 * child is avoiding using its GUI.
816 * @return is this instance avoiding using its GUI?
819 public boolean avoidingGui() {
820 return !okToUseGui && needsGui();
824 * Is this <tt>BeanContext</tt> in the
825 * process of being serialized?
826 * @return if this <tt>BeanContext</tt> is
827 * currently being serialized
829 public boolean isSerializing() { return serializing; }
832 * Returns an iterator of all children
833 * of this <tt>BeanContext</tt>.
834 * @return an iterator for all the current BCSChild values
836 protected Iterator bcsChildren() { synchronized(children) { return children.values().iterator(); } }
839 * called by writeObject after defaultWriteObject() but prior to
840 * serialization of currently serializable children.
842 * This method may be overridden by subclasses to perform custom
843 * serialization of their state prior to this superclass serializing
846 * This method should not however be used by subclasses to replace their
847 * own implementation (if any) of writeObject().
850 protected void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
854 * called by readObject after defaultReadObject() but prior to
855 * deserialization of any children.
857 * This method may be overridden by subclasses to perform custom
858 * deserialization of their state prior to this superclass deserializing
861 * This method should not however be used by subclasses to replace their
862 * own implementation (if any) of readObject().
865 protected void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
869 * Called by readObject with the newly deserialized child and BCSChild.
870 * @param child the newly deserialized child
871 * @param bcsc the newly deserialized BCSChild
873 protected void childDeserializedHook(Object child, BCSChild bcsc) {
874 synchronized(children) {
875 children.put(child, bcsc);
880 * Used by writeObject to serialize a Collection.
881 * @param oos the <tt>ObjectOutputStream</tt>
882 * to use during serialization
883 * @param coll the <tt>Collection</tt> to serialize
884 * @throws IOException if serialization failed
886 protected final void serialize(ObjectOutputStream oos, Collection coll) throws IOException {
888 Object[] objects = coll.toArray();
890 for (int i = 0; i < objects.length; i++) {
891 if (objects[i] instanceof Serializable)
897 oos.writeInt(count); // number of subsequent objects
899 for (int i = 0; count > 0; i++) {
900 Object o = objects[i];
910 * used by readObject to deserialize a collection.
911 * @param ois the ObjectInputStream to use
912 * @param coll the Collection
914 protected final void deserialize(ObjectInputStream ois, Collection coll) throws IOException, ClassNotFoundException {
917 count = ois.readInt();
919 while (count-- > 0) {
920 coll.add(ois.readObject());
925 * Used to serialize all children of
926 * this <tt>BeanContext</tt>.
927 * @param oos the <tt>ObjectOutputStream</tt>
928 * to use during serialization
929 * @throws IOException if serialization failed
931 public final void writeChildren(ObjectOutputStream oos) throws IOException {
932 if (serializable <= 0) return;
934 boolean prev = serializing;
940 synchronized(children) {
941 Iterator i = children.entrySet().iterator();
943 while (i.hasNext() && count < serializable) {
944 Map.Entry entry = (Map.Entry)i.next();
946 if (entry.getKey() instanceof Serializable) {
948 oos.writeObject(entry.getKey()); // child
949 oos.writeObject(entry.getValue()); // BCSChild
950 } catch (IOException ioe) {
961 if (count != serializable) {
962 throw new IOException("wrote different number of children than expected");
968 * Serialize the BeanContextSupport, if this instance has a distinct
969 * peer (that is this object is acting as a delegate for another) then
970 * the children of this instance are not serialized here due to a
971 * 'chicken and egg' problem that occurs on deserialization of the
972 * children at the same time as this instance.
974 * Therefore in situations where there is a distinct peer to this instance
975 * it should always call writeObject() followed by writeChildren() and
976 * readObject() followed by readChildren().
978 * @param oos the ObjectOutputStream
981 private synchronized void writeObject(ObjectOutputStream oos) throws IOException, ClassNotFoundException {
984 synchronized (BeanContext.globalHierarchyLock) {
986 oos.defaultWriteObject(); // serialize the BeanContextSupport object
988 bcsPreSerializationHook(oos);
990 if (serializable > 0 && this.equals(getBeanContextPeer()))
993 serialize(oos, (Collection)bcmListeners);
1001 * When an instance of this class is used as a delegate for the
1002 * implementation of the BeanContext protocols (and its subprotocols)
1003 * there exists a 'chicken and egg' problem during deserialization
1006 public final void readChildren(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1007 int count = serializable;
1009 while (count-- > 0) {
1010 Object child = null;
1011 BeanContextSupport.BCSChild bscc = null;
1014 child = ois.readObject();
1015 bscc = (BeanContextSupport.BCSChild)ois.readObject();
1016 } catch (IOException ioe) {
1018 } catch (ClassNotFoundException cnfe) {
1023 synchronized(child) {
1024 BeanContextChild bcc = null;
1027 bcc = (BeanContextChild)child;
1028 } catch (ClassCastException cce) {
1034 bcc.setBeanContext(getBeanContextPeer());
1036 bcc.addPropertyChangeListener("beanContext", childPCL);
1037 bcc.addVetoableChangeListener("beanContext", childVCL);
1039 } catch (PropertyVetoException pve) {
1044 childDeserializedHook(child, bscc);
1050 * deserialize contents ... if this instance has a distinct peer the
1051 * children are *not* serialized here, the peer's readObject() must call
1052 * readChildren() after deserializing this instance.
1055 private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1057 synchronized(BeanContext.globalHierarchyLock) {
1058 ois.defaultReadObject();
1062 bcsPreDeserializationHook(ois);
1064 if (serializable > 0 && this.equals(getBeanContextPeer()))
1067 deserialize(ois, bcmListeners = new ArrayList(1));
1072 * subclasses may envelope to monitor veto child property changes.
1075 public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException {
1076 String propertyName = pce.getPropertyName();
1077 Object source = pce.getSource();
1079 synchronized(children) {
1080 if ("beanContext".equals(propertyName) &&
1081 containsKey(source) &&
1082 !getBeanContextPeer().equals(pce.getNewValue())
1084 if (!validatePendingRemove(source)) {
1085 throw new PropertyVetoException("current BeanContext vetoes setBeanContext()", pce);
1086 } else ((BCSChild)children.get(source)).setRemovePending(true);
1092 * subclasses may envelope to monitor child property changes.
1095 public void propertyChange(PropertyChangeEvent pce) {
1096 String propertyName = pce.getPropertyName();
1097 Object source = pce.getSource();
1099 synchronized(children) {
1100 if ("beanContext".equals(propertyName) &&
1101 containsKey(source) &&
1102 ((BCSChild)children.get(source)).isRemovePending()) {
1103 BeanContext bc = getBeanContextPeer();
1105 if (bc.equals(pce.getOldValue()) && !bc.equals(pce.getNewValue())) {
1106 remove(source, false);
1108 ((BCSChild)children.get(source)).setRemovePending(false);
1116 * Subclasses of this class may override, or envelope, this method to
1117 * add validation behavior for the BeanContext to examine child objects
1118 * immediately prior to their being added to the BeanContext.
1121 * @return true iff the child may be added to this BeanContext, otherwise false.
1124 protected boolean validatePendingAdd(Object targetChild) {
1130 * Subclasses of this class may override, or envelope, this method to
1131 * add validation behavior for the BeanContext to examine child objects
1132 * immediately prior to their being removed from the BeanContext.
1135 * @return true iff the child may be removed from this BeanContext, otherwise false.
1138 protected boolean validatePendingRemove(Object targetChild) {
1143 * subclasses may override this method to simply extend add() semantics
1144 * after the child has been added and before the event notification has
1145 * occurred. The method is called with the child synchronized.
1148 protected void childJustAddedHook(Object child, BCSChild bcsc) {
1152 * subclasses may override this method to simply extend remove() semantics
1153 * after the child has been removed and before the event notification has
1154 * occurred. The method is called with the child synchronized.
1157 protected void childJustRemovedHook(Object child, BCSChild bcsc) {
1161 * Gets the Component (if any) associated with the specified child.
1162 * @param child the specified child
1163 * @return the Component (if any) associated with the specified child.
1165 protected static final Visibility getChildVisibility(Object child) {
1167 return (Visibility)child;
1168 } catch (ClassCastException cce) {
1174 * Gets the Serializable (if any) associated with the specified Child
1175 * @param child the specified child
1176 * @return the Serializable (if any) associated with the specified Child
1178 protected static final Serializable getChildSerializable(Object child) {
1180 return (Serializable)child;
1181 } catch (ClassCastException cce) {
1187 * Gets the PropertyChangeListener
1188 * (if any) of the specified child
1189 * @param child the specified child
1190 * @return the PropertyChangeListener (if any) of the specified child
1192 protected static final PropertyChangeListener getChildPropertyChangeListener(Object child) {
1194 return (PropertyChangeListener)child;
1195 } catch (ClassCastException cce) {
1201 * Gets the VetoableChangeListener
1202 * (if any) of the specified child
1203 * @param child the specified child
1204 * @return the VetoableChangeListener (if any) of the specified child
1206 protected static final VetoableChangeListener getChildVetoableChangeListener(Object child) {
1208 return (VetoableChangeListener)child;
1209 } catch (ClassCastException cce) {
1215 * Gets the BeanContextMembershipListener
1216 * (if any) of the specified child
1217 * @param child the specified child
1218 * @return the BeanContextMembershipListener (if any) of the specified child
1220 protected static final BeanContextMembershipListener getChildBeanContextMembershipListener(Object child) {
1222 return (BeanContextMembershipListener)child;
1223 } catch (ClassCastException cce) {
1229 * Gets the BeanContextChild (if any) of the specified child
1230 * @param child the specified child
1231 * @return the BeanContextChild (if any) of the specified child
1232 * @throws IllegalArgumentException if child implements both BeanContextChild and BeanContextProxy
1234 protected static final BeanContextChild getChildBeanContextChild(Object child) {
1236 BeanContextChild bcc = (BeanContextChild)child;
1238 if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
1239 throw new IllegalArgumentException("child cannot implement both BeanContextChild and BeanContextProxy");
1242 } catch (ClassCastException cce) {
1244 return ((BeanContextProxy)child).getBeanContextProxy();
1245 } catch (ClassCastException cce1) {
1252 * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
1255 protected final void fireChildrenAdded(BeanContextMembershipEvent bcme) {
1258 synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
1260 for (int i = 0; i < copy.length; i++)
1261 ((BeanContextMembershipListener)copy[i]).childrenAdded(bcme);
1265 * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
1268 protected final void fireChildrenRemoved(BeanContextMembershipEvent bcme) {
1271 synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
1273 for (int i = 0; i < copy.length; i++)
1274 ((BeanContextMembershipListener)copy[i]).childrenRemoved(bcme);
1278 * protected method called from constructor and readObject to initialize
1279 * transient state of BeanContextSupport instance.
1281 * This class uses this method to instantiate inner class listeners used
1282 * to monitor PropertyChange and VetoableChange events on children.
1284 * subclasses may envelope this method to add their own initialization
1288 protected synchronized void initialize() {
1289 children = new HashMap(serializable + 1);
1290 bcmListeners = new ArrayList(1);
1292 childPCL = new PropertyChangeListener() {
1295 * this adaptor is used by the BeanContextSupport class to forward
1296 * property changes from a child to the BeanContext, avoiding
1297 * accidential serialization of the BeanContext by a badly
1298 * behaved Serializable child.
1301 public void propertyChange(PropertyChangeEvent pce) {
1302 BeanContextSupport.this.propertyChange(pce);
1306 childVCL = new VetoableChangeListener() {
1309 * this adaptor is used by the BeanContextSupport class to forward
1310 * vetoable changes from a child to the BeanContext, avoiding
1311 * accidential serialization of the BeanContext by a badly
1312 * behaved Serializable child.
1315 public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException {
1316 BeanContextSupport.this.vetoableChange(pce);
1322 * Gets a copy of the this BeanContext's children.
1323 * @return a copy of the current nested children
1325 protected final Object[] copyChildren() {
1326 synchronized(children) { return children.keySet().toArray(); }
1330 * Tests to see if two class objects,
1331 * or their names are equal.
1332 * @param first the first object
1333 * @param second the second object
1334 * @return true if equal, false if not
1336 protected static final boolean classEquals(Class first, Class second) {
1337 return first.equals(second) || first.getName().equals(second.getName());
1347 * all accesses to the <code> protected HashMap children </code> field
1348 * shall be synchronized on that object.
1350 protected transient HashMap children;
1352 private int serializable = 0; // children serializable
1355 * all accesses to the <code> protected ArrayList bcmListeners </code> field
1356 * shall be synchronized on that object.
1358 protected transient ArrayList bcmListeners;
1363 * The current locale of this BeanContext.
1365 protected Locale locale;
1368 * A <tt>boolean</tt> indicating if this
1369 * instance may now render a GUI.
1371 protected boolean okToUseGui;
1375 * A <tt>boolean</tt> indicating whether or not
1376 * this object is currently in design time mode.
1378 protected boolean designTime;
1384 private transient PropertyChangeListener childPCL;
1386 private transient VetoableChangeListener childVCL;
1388 private transient boolean serializing;