1 /*
2 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
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).
16 *
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.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
45
46 import java.io.IOException;
47 import java.io.InputStream;
48 import java.io.ObjectInputStream;
49 import java.io.ObjectOutputStream;
50 import java.io.Serializable;
51
52 import java.net.URL;
53
54 import java.util.ArrayList;
55 import java.util.Collection;
56 import java.util.HashMap;
57 import java.util.Iterator;
58 import java.util.Locale;
59 import java.util.Map;
60
61
62 /**
63 * This helper class provides a utility implementation of the
64 * java.beans.beancontext.BeanContext interface.
65 * </p>
66 * <p>
67 * Since this class directly implements the BeanContext interface, the class
68 * can, and is intended to be used either by subclassing this implementation,
69 * or via ad-hoc delegation of an instance of this class from another.
70 * </p>
71 *
72 * @author Laurence P. G. Cable
73 * @since 1.2
74 */
75 public class BeanContextSupport extends BeanContextChildSupport
76 implements BeanContext,
77 Serializable,
78 PropertyChangeListener,
79 VetoableChangeListener {
80
81 // Fix for bug 4282900 to pass JCK regression test
82 static final long serialVersionUID = -4879613978649577204L;
83
84 /**
85 *
334 boolean isProxyPeer() { return proxyPeer != null; }
335
336 Object getProxyPeer() { return proxyPeer; }
337 /*
338 * fields
339 */
340
341
342 private Object child;
343 private Object proxyPeer;
344
345 private transient boolean removePending;
346 }
347
348 /**
349 * <p>
350 * Subclasses can override this method to insert their own subclass
351 * of Child without having to override add() or the other Collection
352 * methods that add children to the set.
353 * </p>
354 *
355 * @param targetChild the child to create the Child on behalf of
356 * @param peer the peer if the tragetChild and the peer are related by an implementation of BeanContextProxy
357 */
358
359 protected BCSChild createBCSChild(Object targetChild, Object peer) {
360 return new BCSChild(targetChild, peer);
361 }
362
363 /************************************************************************/
364
365 /**
366 * Adds/nests a child within this <tt>BeanContext</tt>.
367 * <p>
368 * Invoked as a side effect of java.beans.Beans.instantiate().
369 * If the child object is not valid for adding then this method
370 * throws an IllegalStateException.
371 * </p>
372 *
373 *
374 * @param targetChild The child objects to nest
475 }
476
477 /**
478 * Removes a child from this BeanContext. If the child object is not
479 * for adding then this method throws an IllegalStateException.
480 * @param targetChild The child objects to remove
481 * @see #validatePendingRemove
482 */
483 public boolean remove(Object targetChild) {
484 return remove(targetChild, true);
485 }
486
487 /**
488 * internal remove used when removal caused by
489 * unexpected <tt>setBeanContext</tt> or
490 * by <tt>remove()</tt> invocation.
491 * @param targetChild the JavaBean, BeanContext, or Object to be removed
492 * @param callChildSetBC used to indicate that
493 * the child should be notified that it is no
494 * longer nested in this <tt>BeanContext</tt>.
495 */
496 protected boolean remove(Object targetChild, boolean callChildSetBC) {
497
498 if (targetChild == null) throw new IllegalArgumentException();
499
500 synchronized(BeanContext.globalHierarchyLock) {
501 if (!containsKey(targetChild)) return false;
502
503 if (!validatePendingRemove(targetChild)) {
504 throw new IllegalStateException();
505 }
506
507 BCSChild bcsc = (BCSChild)children.get(targetChild);
508 BCSChild pbcsc = null;
509 Object peer = null;
510
511 // we are required to notify the child that it is no longer nested here if
512 // it implements java.beans.beancontext.BeanContextChild
513
514 synchronized(targetChild) {
563 * @param c the specified <tt>Collection</tt>
564 *
565 * @return <tt>true</tt> if all objects
566 * in the collection are children of
567 * this <tt>BeanContext</tt>, false if not.
568 */
569 public boolean containsAll(Collection c) {
570 synchronized(children) {
571 Iterator i = c.iterator();
572 while (i.hasNext())
573 if(!contains(i.next()))
574 return false;
575
576 return true;
577 }
578 }
579
580 /**
581 * add Collection to set of Children (Unsupported)
582 * implementations must synchronized on the hierarchy lock and "children" protected field
583 * @throws UnsupportedOperationException
584 */
585 public boolean addAll(Collection c) {
586 throw new UnsupportedOperationException();
587 }
588
589 /**
590 * remove all specified children (Unsupported)
591 * implementations must synchronized on the hierarchy lock and "children" protected field
592 * @throws UnsupportedOperationException
593 */
594 public boolean removeAll(Collection c) {
595 throw new UnsupportedOperationException();
596 }
597
598
599 /**
600 * retain only specified children (Unsupported)
601 * implementations must synchronized on the hierarchy lock and "children" protected field
602 * @throws UnsupportedOperationException
603 */
604 public boolean retainAll(Collection c) {
605 throw new UnsupportedOperationException();
606 }
607
608 /**
609 * clear the children (Unsupported)
610 * implementations must synchronized on the hierarchy lock and "children" protected field
611 * @throws UnsupportedOperationException
612 */
613 public void clear() {
614 throw new UnsupportedOperationException();
615 }
616
617 /**
618 * Adds a BeanContextMembershipListener
619 *
620 * @param bcml the BeanContextMembershipListener to add
621 * @throws NullPointerException
622 */
623
624 public void addBeanContextMembershipListener(BeanContextMembershipListener bcml) {
625 if (bcml == null) throw new NullPointerException("listener");
626
627 synchronized(bcmListeners) {
628 if (bcmListeners.contains(bcml))
629 return;
630 else
631 bcmListeners.add(bcml);
632 }
633 }
634
635 /**
636 * Removes a BeanContextMembershipListener
637 *
638 * @param bcml the BeanContextMembershipListener to remove
639 * @throws NullPointerException
640 */
641
642 public void removeBeanContextMembershipListener(BeanContextMembershipListener bcml) {
643 if (bcml == null) throw new NullPointerException("listener");
644
645 synchronized(bcmListeners) {
646 if (!bcmListeners.contains(bcml))
647 return;
648 else
649 bcmListeners.remove(bcml);
650 }
651 }
652
653 /**
654 * @param name the name of the resource requested.
655 * @param bcc the child object making the request.
656 *
657 * @return the requested resource as an InputStream
658 * @throws NullPointerException
659 */
660
661 public InputStream getResourceAsStream(String name, BeanContextChild bcc) {
662 if (name == null) throw new NullPointerException("name");
663 if (bcc == null) throw new NullPointerException("bcc");
664
665 if (containsKey(bcc)) {
666 ClassLoader cl = bcc.getClass().getClassLoader();
667
668 return cl != null ? cl.getResourceAsStream(name)
669 : ClassLoader.getSystemResourceAsStream(name);
670 } else throw new IllegalArgumentException("Not a valid child");
671 }
672
673 /**
674 * @param name the name of the resource requested.
675 * @param bcc the child object making the request.
676 *
677 * @return the requested resource as an InputStream
678 */
832 */
833 public boolean isSerializing() { return serializing; }
834
835 /**
836 * Returns an iterator of all children
837 * of this <tt>BeanContext</tt>.
838 * @return an iterator for all the current BCSChild values
839 */
840 protected Iterator bcsChildren() { synchronized(children) { return children.values().iterator(); } }
841
842 /**
843 * called by writeObject after defaultWriteObject() but prior to
844 * serialization of currently serializable children.
845 *
846 * This method may be overridden by subclasses to perform custom
847 * serialization of their state prior to this superclass serializing
848 * the children.
849 *
850 * This method should not however be used by subclasses to replace their
851 * own implementation (if any) of writeObject().
852 */
853
854 protected void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
855 }
856
857 /**
858 * called by readObject after defaultReadObject() but prior to
859 * deserialization of any children.
860 *
861 * This method may be overridden by subclasses to perform custom
862 * deserialization of their state prior to this superclass deserializing
863 * the children.
864 *
865 * This method should not however be used by subclasses to replace their
866 * own implementation (if any) of readObject().
867 */
868
869 protected void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
870 }
871
872 /**
873 * Called by readObject with the newly deserialized child and BCSChild.
874 * @param child the newly deserialized child
875 * @param bcsc the newly deserialized BCSChild
876 */
877 protected void childDeserializedHook(Object child, BCSChild bcsc) {
878 synchronized(children) {
879 children.put(child, bcsc);
880 }
881 }
882
883 /**
884 * Used by writeObject to serialize a Collection.
885 * @param oos the <tt>ObjectOutputStream</tt>
886 * to use during serialization
897 else
898 objects[i] = null;
899 }
900
901 oos.writeInt(count); // number of subsequent objects
902
903 for (int i = 0; count > 0; i++) {
904 Object o = objects[i];
905
906 if (o != null) {
907 oos.writeObject(o);
908 count--;
909 }
910 }
911 }
912
913 /**
914 * used by readObject to deserialize a collection.
915 * @param ois the ObjectInputStream to use
916 * @param coll the Collection
917 */
918 protected final void deserialize(ObjectInputStream ois, Collection coll) throws IOException, ClassNotFoundException {
919 int count = 0;
920
921 count = ois.readInt();
922
923 while (count-- > 0) {
924 coll.add(ois.readObject());
925 }
926 }
927
928 /**
929 * Used to serialize all children of
930 * this <tt>BeanContext</tt>.
931 * @param oos the <tt>ObjectOutputStream</tt>
932 * to use during serialization
933 * @throws IOException if serialization failed
934 */
935 public final void writeChildren(ObjectOutputStream oos) throws IOException {
936 if (serializable <= 0) return;
988 synchronized (BeanContext.globalHierarchyLock) {
989 try {
990 oos.defaultWriteObject(); // serialize the BeanContextSupport object
991
992 bcsPreSerializationHook(oos);
993
994 if (serializable > 0 && this.equals(getBeanContextPeer()))
995 writeChildren(oos);
996
997 serialize(oos, (Collection)bcmListeners);
998 } finally {
999 serializing = false;
1000 }
1001 }
1002 }
1003
1004 /**
1005 * When an instance of this class is used as a delegate for the
1006 * implementation of the BeanContext protocols (and its subprotocols)
1007 * there exists a 'chicken and egg' problem during deserialization
1008 */
1009
1010 public final void readChildren(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1011 int count = serializable;
1012
1013 while (count-- > 0) {
1014 Object child = null;
1015 BeanContextSupport.BCSChild bscc = null;
1016
1017 try {
1018 child = ois.readObject();
1019 bscc = (BeanContextSupport.BCSChild)ois.readObject();
1020 } catch (IOException ioe) {
1021 continue;
1022 } catch (ClassNotFoundException cnfe) {
1023 continue;
1024 }
1025
1026
1027 synchronized(child) {
1105 containsKey(source) &&
1106 ((BCSChild)children.get(source)).isRemovePending()) {
1107 BeanContext bc = getBeanContextPeer();
1108
1109 if (bc.equals(pce.getOldValue()) && !bc.equals(pce.getNewValue())) {
1110 remove(source, false);
1111 } else {
1112 ((BCSChild)children.get(source)).setRemovePending(false);
1113 }
1114 }
1115 }
1116 }
1117
1118 /**
1119 * <p>
1120 * Subclasses of this class may override, or envelope, this method to
1121 * add validation behavior for the BeanContext to examine child objects
1122 * immediately prior to their being added to the BeanContext.
1123 * </p>
1124 *
1125 * @return true iff the child may be added to this BeanContext, otherwise false.
1126 */
1127
1128 protected boolean validatePendingAdd(Object targetChild) {
1129 return true;
1130 }
1131
1132 /**
1133 * <p>
1134 * Subclasses of this class may override, or envelope, this method to
1135 * add validation behavior for the BeanContext to examine child objects
1136 * immediately prior to their being removed from the BeanContext.
1137 * </p>
1138 *
1139 * @return true iff the child may be removed from this BeanContext, otherwise false.
1140 */
1141
1142 protected boolean validatePendingRemove(Object targetChild) {
1143 return true;
1144 }
1145
1146 /**
1147 * subclasses may override this method to simply extend add() semantics
1148 * after the child has been added and before the event notification has
1149 * occurred. The method is called with the child synchronized.
1150 */
1151
1152 protected void childJustAddedHook(Object child, BCSChild bcsc) {
1153 }
1154
1155 /**
1156 * subclasses may override this method to simply extend remove() semantics
1157 * after the child has been removed and before the event notification has
1158 * occurred. The method is called with the child synchronized.
1159 */
1160
1161 protected void childJustRemovedHook(Object child, BCSChild bcsc) {
1162 }
1163
1164 /**
1165 * Gets the Component (if any) associated with the specified child.
1166 * @param child the specified child
1167 * @return the Component (if any) associated with the specified child.
1168 */
1169 protected static final Visibility getChildVisibility(Object child) {
1170 try {
1171 return (Visibility)child;
1172 } catch (ClassCastException cce) {
1173 return null;
1174 }
1175 }
1176
1177 /**
1178 * Gets the Serializable (if any) associated with the specified Child
1237 */
1238 protected static final BeanContextChild getChildBeanContextChild(Object child) {
1239 try {
1240 BeanContextChild bcc = (BeanContextChild)child;
1241
1242 if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
1243 throw new IllegalArgumentException("child cannot implement both BeanContextChild and BeanContextProxy");
1244 else
1245 return bcc;
1246 } catch (ClassCastException cce) {
1247 try {
1248 return ((BeanContextProxy)child).getBeanContextProxy();
1249 } catch (ClassCastException cce1) {
1250 return null;
1251 }
1252 }
1253 }
1254
1255 /**
1256 * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
1257 */
1258
1259 protected final void fireChildrenAdded(BeanContextMembershipEvent bcme) {
1260 Object[] copy;
1261
1262 synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
1263
1264 for (int i = 0; i < copy.length; i++)
1265 ((BeanContextMembershipListener)copy[i]).childrenAdded(bcme);
1266 }
1267
1268 /**
1269 * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
1270 */
1271
1272 protected final void fireChildrenRemoved(BeanContextMembershipEvent bcme) {
1273 Object[] copy;
1274
1275 synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
1276
1277 for (int i = 0; i < copy.length; i++)
1278 ((BeanContextMembershipListener)copy[i]).childrenRemoved(bcme);
1279 }
1280
1281 /**
1282 * protected method called from constructor and readObject to initialize
1283 * transient state of BeanContextSupport instance.
1284 *
1285 * This class uses this method to instantiate inner class listeners used
1286 * to monitor PropertyChange and VetoableChange events on children.
1287 *
1288 * subclasses may envelope this method to add their own initialization
1289 * behavior
|
1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
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).
16 *
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.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
45
46 import java.io.IOException;
47 import java.io.InputStream;
48 import java.io.ObjectInputStream;
49 import java.io.ObjectOutputStream;
50 import java.io.Serializable;
51
52 import java.net.URL;
53
54 import java.util.ArrayList;
55 import java.util.Collection;
56 import java.util.HashMap;
57 import java.util.Iterator;
58 import java.util.Locale;
59 import java.util.Map;
60
61
62 /**
63 * This helper class provides a utility implementation of the
64 * java.beans.beancontext.BeanContext interface.
65 * <p>
66 * Since this class directly implements the BeanContext interface, the class
67 * can, and is intended to be used either by subclassing this implementation,
68 * or via ad-hoc delegation of an instance of this class from another.
69 * </p>
70 *
71 * @author Laurence P. G. Cable
72 * @since 1.2
73 */
74 public class BeanContextSupport extends BeanContextChildSupport
75 implements BeanContext,
76 Serializable,
77 PropertyChangeListener,
78 VetoableChangeListener {
79
80 // Fix for bug 4282900 to pass JCK regression test
81 static final long serialVersionUID = -4879613978649577204L;
82
83 /**
84 *
333 boolean isProxyPeer() { return proxyPeer != null; }
334
335 Object getProxyPeer() { return proxyPeer; }
336 /*
337 * fields
338 */
339
340
341 private Object child;
342 private Object proxyPeer;
343
344 private transient boolean removePending;
345 }
346
347 /**
348 * <p>
349 * Subclasses can override this method to insert their own subclass
350 * of Child without having to override add() or the other Collection
351 * methods that add children to the set.
352 * </p>
353 * @return Subtype-specific subclass of Child without overriding collection methods
354 * @param targetChild the child to create the Child on behalf of
355 * @param peer the peer if the tragetChild and the peer are related by an implementation of BeanContextProxy
356 */
357
358 protected BCSChild createBCSChild(Object targetChild, Object peer) {
359 return new BCSChild(targetChild, peer);
360 }
361
362 /************************************************************************/
363
364 /**
365 * Adds/nests a child within this <tt>BeanContext</tt>.
366 * <p>
367 * Invoked as a side effect of java.beans.Beans.instantiate().
368 * If the child object is not valid for adding then this method
369 * throws an IllegalStateException.
370 * </p>
371 *
372 *
373 * @param targetChild The child objects to nest
474 }
475
476 /**
477 * Removes a child from this BeanContext. If the child object is not
478 * for adding then this method throws an IllegalStateException.
479 * @param targetChild The child objects to remove
480 * @see #validatePendingRemove
481 */
482 public boolean remove(Object targetChild) {
483 return remove(targetChild, true);
484 }
485
486 /**
487 * internal remove used when removal caused by
488 * unexpected <tt>setBeanContext</tt> or
489 * by <tt>remove()</tt> invocation.
490 * @param targetChild the JavaBean, BeanContext, or Object to be removed
491 * @param callChildSetBC used to indicate that
492 * the child should be notified that it is no
493 * longer nested in this <tt>BeanContext</tt>.
494 * @return whether or not was present before being removed
495 */
496 protected boolean remove(Object targetChild, boolean callChildSetBC) {
497
498 if (targetChild == null) throw new IllegalArgumentException();
499
500 synchronized(BeanContext.globalHierarchyLock) {
501 if (!containsKey(targetChild)) return false;
502
503 if (!validatePendingRemove(targetChild)) {
504 throw new IllegalStateException();
505 }
506
507 BCSChild bcsc = (BCSChild)children.get(targetChild);
508 BCSChild pbcsc = null;
509 Object peer = null;
510
511 // we are required to notify the child that it is no longer nested here if
512 // it implements java.beans.beancontext.BeanContextChild
513
514 synchronized(targetChild) {
563 * @param c the specified <tt>Collection</tt>
564 *
565 * @return <tt>true</tt> if all objects
566 * in the collection are children of
567 * this <tt>BeanContext</tt>, false if not.
568 */
569 public boolean containsAll(Collection c) {
570 synchronized(children) {
571 Iterator i = c.iterator();
572 while (i.hasNext())
573 if(!contains(i.next()))
574 return false;
575
576 return true;
577 }
578 }
579
580 /**
581 * add Collection to set of Children (Unsupported)
582 * implementations must synchronized on the hierarchy lock and "children" protected field
583 * @throws UnsupportedOperationException thrown unconditionally by this implementation
584 * @return this implementation unconditionally throws {@code UnsupportedOperationException}
585 */
586 public boolean addAll(Collection c) {
587 throw new UnsupportedOperationException();
588 }
589
590 /**
591 * remove all specified children (Unsupported)
592 * implementations must synchronized on the hierarchy lock and "children" protected field
593 * @throws UnsupportedOperationException thrown unconditionally by this implementation
594 * @return this implementation unconditionally throws {@code UnsupportedOperationException}
595
596 */
597 public boolean removeAll(Collection c) {
598 throw new UnsupportedOperationException();
599 }
600
601
602 /**
603 * retain only specified children (Unsupported)
604 * implementations must synchronized on the hierarchy lock and "children" protected field
605 * @throws UnsupportedOperationException thrown unconditionally by this implementation
606 * @return this implementation unconditionally throws {@code UnsupportedOperationException}
607 */
608 public boolean retainAll(Collection c) {
609 throw new UnsupportedOperationException();
610 }
611
612 /**
613 * clear the children (Unsupported)
614 * implementations must synchronized on the hierarchy lock and "children" protected field
615 * @throws UnsupportedOperationException thrown unconditionally by this implementation
616 */
617 public void clear() {
618 throw new UnsupportedOperationException();
619 }
620
621 /**
622 * Adds a BeanContextMembershipListener
623 *
624 * @param bcml the BeanContextMembershipListener to add
625 * @throws NullPointerException if the argument is null
626 */
627
628 public void addBeanContextMembershipListener(BeanContextMembershipListener bcml) {
629 if (bcml == null) throw new NullPointerException("listener");
630
631 synchronized(bcmListeners) {
632 if (bcmListeners.contains(bcml))
633 return;
634 else
635 bcmListeners.add(bcml);
636 }
637 }
638
639 /**
640 * Removes a BeanContextMembershipListener
641 *
642 * @param bcml the BeanContextMembershipListener to remove
643 * @throws NullPointerException if the argument is null
644 */
645
646 public void removeBeanContextMembershipListener(BeanContextMembershipListener bcml) {
647 if (bcml == null) throw new NullPointerException("listener");
648
649 synchronized(bcmListeners) {
650 if (!bcmListeners.contains(bcml))
651 return;
652 else
653 bcmListeners.remove(bcml);
654 }
655 }
656
657 /**
658 * @param name the name of the resource requested.
659 * @param bcc the child object making the request.
660 *
661 * @return the requested resource as an InputStream
662 * @throws NullPointerException if the argument is null
663 */
664
665 public InputStream getResourceAsStream(String name, BeanContextChild bcc) {
666 if (name == null) throw new NullPointerException("name");
667 if (bcc == null) throw new NullPointerException("bcc");
668
669 if (containsKey(bcc)) {
670 ClassLoader cl = bcc.getClass().getClassLoader();
671
672 return cl != null ? cl.getResourceAsStream(name)
673 : ClassLoader.getSystemResourceAsStream(name);
674 } else throw new IllegalArgumentException("Not a valid child");
675 }
676
677 /**
678 * @param name the name of the resource requested.
679 * @param bcc the child object making the request.
680 *
681 * @return the requested resource as an InputStream
682 */
836 */
837 public boolean isSerializing() { return serializing; }
838
839 /**
840 * Returns an iterator of all children
841 * of this <tt>BeanContext</tt>.
842 * @return an iterator for all the current BCSChild values
843 */
844 protected Iterator bcsChildren() { synchronized(children) { return children.values().iterator(); } }
845
846 /**
847 * called by writeObject after defaultWriteObject() but prior to
848 * serialization of currently serializable children.
849 *
850 * This method may be overridden by subclasses to perform custom
851 * serialization of their state prior to this superclass serializing
852 * the children.
853 *
854 * This method should not however be used by subclasses to replace their
855 * own implementation (if any) of writeObject().
856 * @param oos the {@code ObjectOutputStream} to use during serialization
857 * @throws IOException if serialization failed
858 */
859
860 protected void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
861 }
862
863 /**
864 * called by readObject after defaultReadObject() but prior to
865 * deserialization of any children.
866 *
867 * This method may be overridden by subclasses to perform custom
868 * deserialization of their state prior to this superclass deserializing
869 * the children.
870 *
871 * This method should not however be used by subclasses to replace their
872 * own implementation (if any) of readObject().
873 * @param ois the {@code ObjectInputStream} to use during deserialization
874 * @throws IOException if deserialization failed
875 * @throws ClassNotFoundException if needed classes are not found
876 */
877
878 protected void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
879 }
880
881 /**
882 * Called by readObject with the newly deserialized child and BCSChild.
883 * @param child the newly deserialized child
884 * @param bcsc the newly deserialized BCSChild
885 */
886 protected void childDeserializedHook(Object child, BCSChild bcsc) {
887 synchronized(children) {
888 children.put(child, bcsc);
889 }
890 }
891
892 /**
893 * Used by writeObject to serialize a Collection.
894 * @param oos the <tt>ObjectOutputStream</tt>
895 * to use during serialization
906 else
907 objects[i] = null;
908 }
909
910 oos.writeInt(count); // number of subsequent objects
911
912 for (int i = 0; count > 0; i++) {
913 Object o = objects[i];
914
915 if (o != null) {
916 oos.writeObject(o);
917 count--;
918 }
919 }
920 }
921
922 /**
923 * used by readObject to deserialize a collection.
924 * @param ois the ObjectInputStream to use
925 * @param coll the Collection
926 * @throws IOException if deserialization failed
927 * @throws ClassNotFoundException if needed classes are not found
928 */
929 protected final void deserialize(ObjectInputStream ois, Collection coll) throws IOException, ClassNotFoundException {
930 int count = 0;
931
932 count = ois.readInt();
933
934 while (count-- > 0) {
935 coll.add(ois.readObject());
936 }
937 }
938
939 /**
940 * Used to serialize all children of
941 * this <tt>BeanContext</tt>.
942 * @param oos the <tt>ObjectOutputStream</tt>
943 * to use during serialization
944 * @throws IOException if serialization failed
945 */
946 public final void writeChildren(ObjectOutputStream oos) throws IOException {
947 if (serializable <= 0) return;
999 synchronized (BeanContext.globalHierarchyLock) {
1000 try {
1001 oos.defaultWriteObject(); // serialize the BeanContextSupport object
1002
1003 bcsPreSerializationHook(oos);
1004
1005 if (serializable > 0 && this.equals(getBeanContextPeer()))
1006 writeChildren(oos);
1007
1008 serialize(oos, (Collection)bcmListeners);
1009 } finally {
1010 serializing = false;
1011 }
1012 }
1013 }
1014
1015 /**
1016 * When an instance of this class is used as a delegate for the
1017 * implementation of the BeanContext protocols (and its subprotocols)
1018 * there exists a 'chicken and egg' problem during deserialization
1019 * @param ois the ObjectInputStream to use
1020 * @throws IOException if deserialization failed
1021 * @throws ClassNotFoundException if needed classes are not found
1022 */
1023
1024 public final void readChildren(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1025 int count = serializable;
1026
1027 while (count-- > 0) {
1028 Object child = null;
1029 BeanContextSupport.BCSChild bscc = null;
1030
1031 try {
1032 child = ois.readObject();
1033 bscc = (BeanContextSupport.BCSChild)ois.readObject();
1034 } catch (IOException ioe) {
1035 continue;
1036 } catch (ClassNotFoundException cnfe) {
1037 continue;
1038 }
1039
1040
1041 synchronized(child) {
1119 containsKey(source) &&
1120 ((BCSChild)children.get(source)).isRemovePending()) {
1121 BeanContext bc = getBeanContextPeer();
1122
1123 if (bc.equals(pce.getOldValue()) && !bc.equals(pce.getNewValue())) {
1124 remove(source, false);
1125 } else {
1126 ((BCSChild)children.get(source)).setRemovePending(false);
1127 }
1128 }
1129 }
1130 }
1131
1132 /**
1133 * <p>
1134 * Subclasses of this class may override, or envelope, this method to
1135 * add validation behavior for the BeanContext to examine child objects
1136 * immediately prior to their being added to the BeanContext.
1137 * </p>
1138 *
1139 * @param targetChild the child to create the Child on behalf of
1140 * @return true iff the child may be added to this BeanContext, otherwise false.
1141 */
1142
1143 protected boolean validatePendingAdd(Object targetChild) {
1144 return true;
1145 }
1146
1147 /**
1148 * <p>
1149 * Subclasses of this class may override, or envelope, this method to
1150 * add validation behavior for the BeanContext to examine child objects
1151 * immediately prior to their being removed from the BeanContext.
1152 * </p>
1153 *
1154 * @param targetChild the child to create the Child on behalf of
1155 * @return true iff the child may be removed from this BeanContext, otherwise false.
1156 */
1157
1158 protected boolean validatePendingRemove(Object targetChild) {
1159 return true;
1160 }
1161
1162 /**
1163 * subclasses may override this method to simply extend add() semantics
1164 * after the child has been added and before the event notification has
1165 * occurred. The method is called with the child synchronized.
1166 * @param child the child
1167 * @param bcsc the BCSChild
1168 */
1169
1170 protected void childJustAddedHook(Object child, BCSChild bcsc) {
1171 }
1172
1173 /**
1174 * subclasses may override this method to simply extend remove() semantics
1175 * after the child has been removed and before the event notification has
1176 * occurred. The method is called with the child synchronized.
1177 * @param child the child
1178 * @param bcsc the BCSChild
1179 */
1180
1181 protected void childJustRemovedHook(Object child, BCSChild bcsc) {
1182 }
1183
1184 /**
1185 * Gets the Component (if any) associated with the specified child.
1186 * @param child the specified child
1187 * @return the Component (if any) associated with the specified child.
1188 */
1189 protected static final Visibility getChildVisibility(Object child) {
1190 try {
1191 return (Visibility)child;
1192 } catch (ClassCastException cce) {
1193 return null;
1194 }
1195 }
1196
1197 /**
1198 * Gets the Serializable (if any) associated with the specified Child
1257 */
1258 protected static final BeanContextChild getChildBeanContextChild(Object child) {
1259 try {
1260 BeanContextChild bcc = (BeanContextChild)child;
1261
1262 if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
1263 throw new IllegalArgumentException("child cannot implement both BeanContextChild and BeanContextProxy");
1264 else
1265 return bcc;
1266 } catch (ClassCastException cce) {
1267 try {
1268 return ((BeanContextProxy)child).getBeanContextProxy();
1269 } catch (ClassCastException cce1) {
1270 return null;
1271 }
1272 }
1273 }
1274
1275 /**
1276 * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
1277 * @param bcme the event to fire
1278 */
1279
1280 protected final void fireChildrenAdded(BeanContextMembershipEvent bcme) {
1281 Object[] copy;
1282
1283 synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
1284
1285 for (int i = 0; i < copy.length; i++)
1286 ((BeanContextMembershipListener)copy[i]).childrenAdded(bcme);
1287 }
1288
1289 /**
1290 * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
1291 * @param bcme the event to fire
1292 */
1293
1294 protected final void fireChildrenRemoved(BeanContextMembershipEvent bcme) {
1295 Object[] copy;
1296
1297 synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
1298
1299 for (int i = 0; i < copy.length; i++)
1300 ((BeanContextMembershipListener)copy[i]).childrenRemoved(bcme);
1301 }
1302
1303 /**
1304 * protected method called from constructor and readObject to initialize
1305 * transient state of BeanContextSupport instance.
1306 *
1307 * This class uses this method to instantiate inner class listeners used
1308 * to monitor PropertyChange and VetoableChange events on children.
1309 *
1310 * subclasses may envelope this method to add their own initialization
1311 * behavior
|