237 } 238 } 239 240 /** 241 * Determines whether or not the specified object 242 * is currently a child of this <tt>BeanContext</tt>. 243 * @param o the Object in question 244 * @return if this object is a child 245 */ 246 public boolean containsKey(Object o) { 247 synchronized(children) { 248 return children.containsKey(o); 249 } 250 } 251 252 /** 253 * Gets all JavaBean or <tt>BeanContext</tt> instances 254 * currently nested in this <tt>BeanContext</tt>. 255 * @return an <tt>Iterator</tt> of the nested children 256 */ 257 public Iterator iterator() { 258 synchronized(children) { 259 return new BCSIterator(children.keySet().iterator()); 260 } 261 } 262 263 /** 264 * Gets all JavaBean or <tt>BeanContext</tt> 265 * instances currently nested in this BeanContext. 266 */ 267 public Object[] toArray() { 268 synchronized(children) { 269 return children.keySet().toArray(); 270 } 271 } 272 273 /** 274 * Gets an array containing all children of 275 * this <tt>BeanContext</tt> that match 276 * the types contained in arry. 277 * @param arry The array of object 278 * types that are of interest. 279 * @return an array of children 280 */ 281 public Object[] toArray(Object[] arry) { 282 synchronized(children) { 283 return children.keySet().toArray(arry); 284 } 285 } 286 287 288 /************************************************************************/ 289 290 /** 291 * protected final subclass that encapsulates an iterator but implements 292 * a noop remove() method. 293 */ 294 295 protected static final class BCSIterator implements Iterator { 296 BCSIterator(Iterator i) { super(); src = i; } 297 298 public boolean hasNext() { return src.hasNext(); } 299 public Object next() { return src.next(); } 300 public void remove() { /* do nothing */ } 301 302 private Iterator src; 303 } 304 305 /************************************************************************/ 306 307 /* 308 * protected nested class containing per child information, an instance 309 * of which is associated with each child in the "children" hashtable. 310 * subclasses can extend this class to include their own per-child state. 311 * 312 * Note that this 'value' is serialized with the corresponding child 'key' 313 * when the BeanContextSupport is serialized. 314 */ 315 316 protected class BCSChild implements Serializable { 317 318 private static final long serialVersionUID = -5815286101609939109L; 319 320 BCSChild(Object bcc, Object peer) { 321 super(); 322 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) { 515 if (callChildSetBC) { 516 BeanContextChild cbcc = getChildBeanContextChild(targetChild); 517 if (cbcc != null) synchronized(cbcc) { 518 cbcc.removePropertyChangeListener("beanContext", childPCL); 519 cbcc.removeVetoableChangeListener("beanContext", childVCL); 520 521 try { 522 cbcc.setBeanContext(null); 523 } catch (PropertyVetoException pve1) { 524 cbcc.addPropertyChangeListener("beanContext", childPCL); 525 cbcc.addVetoableChangeListener("beanContext", childVCL); 526 throw new IllegalStateException(); 527 } 528 529 } 530 } 531 532 synchronized (children) { 533 children.remove(targetChild); 534 535 if (bcsc.isProxyPeer()) { 536 pbcsc = (BCSChild)children.get(peer = bcsc.getProxyPeer()); 537 children.remove(peer); 538 } 539 } 540 541 if (getChildSerializable(targetChild) != null) serializable--; 542 543 childJustRemovedHook(targetChild, bcsc); 544 545 if (peer != null) { 546 if (getChildSerializable(peer) != null) serializable--; 547 548 childJustRemovedHook(peer, pbcsc); 549 } 550 } 551 552 fireChildrenRemoved(new BeanContextMembershipEvent(getBeanContextPeer(), peer == null ? new Object[] { targetChild } : new Object[] { targetChild, peer } )); 553 554 } 555 556 return true; 557 } 558 559 /** 560 * Tests to see if all objects in the 561 * specified <tt>Collection</tt> are children of 562 * this <tt>BeanContext</tt>. 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 746 * if the implementor "needs" a GUI. 747 * </p> 748 * <p> 749 * The algorithm used herein tests the BeanContextPeer, and its current children 750 * to determine if they are either Containers, Components, or if they implement 751 * Visibility and return needsGui() == true. 752 * </p> 753 * @return <tt>true</tt> if the implementor needs a GUI 754 */ 755 public synchronized boolean needsGui() { 756 BeanContext bc = getBeanContextPeer(); 757 758 if (bc != this) { 759 if (bc instanceof Visibility) return ((Visibility)bc).needsGui(); 760 761 if (bc instanceof Container || bc instanceof Component) 762 return true; 763 } 764 765 synchronized(children) { 766 for (Iterator i = children.keySet().iterator(); i.hasNext();) { 767 Object c = i.next(); 768 769 try { 770 return ((Visibility)c).needsGui(); 771 } catch (ClassCastException cce) { 772 // do nothing ... 773 } 774 775 if (c instanceof Container || c instanceof Component) 776 return true; 777 } 778 } 779 780 return false; 781 } 782 783 /** 784 * notify this instance that it may no longer render a GUI. 785 */ 786 787 public synchronized void dontUseGui() { 788 if (okToUseGui) { 789 okToUseGui = false; 790 791 // lets also tell the Children that can that they may not use their GUI's 792 synchronized(children) { 793 for (Iterator i = children.keySet().iterator(); i.hasNext();) { 794 Visibility v = getChildVisibility(i.next()); 795 796 if (v != null) v.dontUseGui(); 797 } 798 } 799 } 800 } 801 802 /** 803 * Notify this instance that it may now render a GUI 804 */ 805 806 public synchronized void okToUseGui() { 807 if (!okToUseGui) { 808 okToUseGui = true; 809 810 // lets also tell the Children that can that they may use their GUI's 811 synchronized(children) { 812 for (Iterator i = children.keySet().iterator(); i.hasNext();) { 813 Visibility v = getChildVisibility(i.next()); 814 815 if (v != null) v.okToUseGui(); 816 } 817 } 818 } 819 } 820 821 /** 822 * Used to determine if the <tt>BeanContext</tt> 823 * child is avoiding using its GUI. 824 * @return is this instance avoiding using its GUI? 825 * @see Visibility 826 */ 827 public boolean avoidingGui() { 828 return !okToUseGui && needsGui(); 829 } 830 831 /** 832 * Is this <tt>BeanContext</tt> in the 833 * process of being serialized? 834 * @return if this <tt>BeanContext</tt> is 835 * currently being serialized 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 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 896 * @param coll the <tt>Collection</tt> to serialize 897 * @throws IOException if serialization failed 898 */ 899 protected final void serialize(ObjectOutputStream oos, Collection coll) throws IOException { 900 int count = 0; 901 Object[] objects = coll.toArray(); 902 903 for (int i = 0; i < objects.length; i++) { 904 if (objects[i] instanceof Serializable) 905 count++; 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; 948 949 boolean prev = serializing; 950 951 serializing = true; 952 953 int count = 0; 954 955 synchronized(children) { 956 Iterator i = children.entrySet().iterator(); 957 958 while (i.hasNext() && count < serializable) { 959 Map.Entry entry = (Map.Entry)i.next(); 960 961 if (entry.getKey() instanceof Serializable) { 962 try { 963 oos.writeObject(entry.getKey()); // child 964 oos.writeObject(entry.getValue()); // BCSChild 965 } catch (IOException ioe) { 966 serializing = prev; 967 throw ioe; 968 } 969 count++; 970 } 971 } 972 } 973 974 serializing = prev; 975 976 if (count != serializable) { 977 throw new IOException("wrote different number of children than expected"); 978 } 979 1065 } 1066 1067 /** 1068 * deserialize contents ... if this instance has a distinct peer the 1069 * children are *not* serialized here, the peer's readObject() must call 1070 * readChildren() after deserializing this instance. 1071 */ 1072 1073 private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 1074 1075 synchronized(BeanContext.globalHierarchyLock) { 1076 ois.defaultReadObject(); 1077 1078 initialize(); 1079 1080 bcsPreDeserializationHook(ois); 1081 1082 if (serializable > 0 && this.equals(getBeanContextPeer())) 1083 readChildren(ois); 1084 1085 deserialize(ois, bcmListeners = new ArrayList(1)); 1086 } 1087 } 1088 1089 /** 1090 * subclasses may envelope to monitor veto child property changes. 1091 */ 1092 1093 public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException { 1094 String propertyName = pce.getPropertyName(); 1095 Object source = pce.getSource(); 1096 1097 synchronized(children) { 1098 if ("beanContext".equals(propertyName) && 1099 containsKey(source) && 1100 !getBeanContextPeer().equals(pce.getNewValue()) 1101 ) { 1102 if (!validatePendingRemove(source)) { 1103 throw new PropertyVetoException("current BeanContext vetoes setBeanContext()", pce); 1104 } else ((BCSChild)children.get(source)).setRemovePending(true); 1105 } 1106 } 1107 } 1108 1109 /** 1110 * subclasses may envelope to monitor child property changes. 1111 */ 1112 1113 public void propertyChange(PropertyChangeEvent pce) { 1114 String propertyName = pce.getPropertyName(); 1115 Object source = pce.getSource(); 1116 1117 synchronized(children) { 1118 if ("beanContext".equals(propertyName) && 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 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 1312 */ 1313 1314 protected synchronized void initialize() { 1315 children = new HashMap(serializable + 1); 1316 bcmListeners = new ArrayList(1); 1317 1318 childPCL = new PropertyChangeListener() { 1319 1320 /* 1321 * this adaptor is used by the BeanContextSupport class to forward 1322 * property changes from a child to the BeanContext, avoiding 1323 * accidential serialization of the BeanContext by a badly 1324 * behaved Serializable child. 1325 */ 1326 1327 public void propertyChange(PropertyChangeEvent pce) { 1328 BeanContextSupport.this.propertyChange(pce); 1329 } 1330 }; 1331 1332 childVCL = new VetoableChangeListener() { 1333 1334 /* 1335 * this adaptor is used by the BeanContextSupport class to forward 1336 * vetoable changes from a child to the BeanContext, avoiding 1342 BeanContextSupport.this.vetoableChange(pce); 1343 } 1344 }; 1345 } 1346 1347 /** 1348 * Gets a copy of the this BeanContext's children. 1349 * @return a copy of the current nested children 1350 */ 1351 protected final Object[] copyChildren() { 1352 synchronized(children) { return children.keySet().toArray(); } 1353 } 1354 1355 /** 1356 * Tests to see if two class objects, 1357 * or their names are equal. 1358 * @param first the first object 1359 * @param second the second object 1360 * @return true if equal, false if not 1361 */ 1362 protected static final boolean classEquals(Class first, Class second) { 1363 return first.equals(second) || first.getName().equals(second.getName()); 1364 } 1365 1366 1367 /* 1368 * fields 1369 */ 1370 1371 1372 /** 1373 * all accesses to the <code> protected HashMap children </code> field 1374 * shall be synchronized on that object. 1375 */ 1376 protected transient HashMap children; 1377 1378 private int serializable = 0; // children serializable 1379 1380 /** 1381 * all accesses to the <code> protected ArrayList bcmListeners </code> field 1382 * shall be synchronized on that object. 1383 */ 1384 protected transient ArrayList bcmListeners; 1385 1386 // 1387 1388 /** 1389 * The current locale of this BeanContext. 1390 */ 1391 protected Locale locale; 1392 1393 /** 1394 * A <tt>boolean</tt> indicating if this 1395 * instance may now render a GUI. 1396 */ 1397 protected boolean okToUseGui; 1398 1399 1400 /** 1401 * A <tt>boolean</tt> indicating whether or not 1402 * this object is currently in design time mode. 1403 */ 1404 protected boolean designTime; | 237 } 238 } 239 240 /** 241 * Determines whether or not the specified object 242 * is currently a child of this <tt>BeanContext</tt>. 243 * @param o the Object in question 244 * @return if this object is a child 245 */ 246 public boolean containsKey(Object o) { 247 synchronized(children) { 248 return children.containsKey(o); 249 } 250 } 251 252 /** 253 * Gets all JavaBean or <tt>BeanContext</tt> instances 254 * currently nested in this <tt>BeanContext</tt>. 255 * @return an <tt>Iterator</tt> of the nested children 256 */ 257 public Iterator<Object> iterator() { 258 synchronized(children) { 259 return new BCSIterator(children.keySet().iterator()); 260 } 261 } 262 263 /** 264 * Gets all JavaBean or <tt>BeanContext</tt> 265 * instances currently nested in this BeanContext. 266 */ 267 public Object[] toArray() { 268 synchronized(children) { 269 return children.keySet().toArray(); 270 } 271 } 272 273 /** 274 * Gets an array containing all children of 275 * this <tt>BeanContext</tt> that match 276 * the types contained in arry. 277 * @param arry The array of object 278 * types that are of interest. 279 * @return an array of children 280 */ 281 public Object[] toArray(Object[] arry) { 282 synchronized(children) { 283 return children.keySet().toArray(arry); 284 } 285 } 286 287 288 /************************************************************************/ 289 290 /** 291 * protected final subclass that encapsulates an iterator but implements 292 * a noop remove() method. 293 */ 294 295 protected static final class BCSIterator implements Iterator<Object> { 296 BCSIterator(Iterator<?> i) { super(); src = i; } 297 298 public boolean hasNext() { return src.hasNext(); } 299 public Object next() { return src.next(); } 300 public void remove() { /* do nothing */ } 301 302 private Iterator<?> src; 303 } 304 305 /************************************************************************/ 306 307 /* 308 * protected nested class containing per child information, an instance 309 * of which is associated with each child in the "children" hashtable. 310 * subclasses can extend this class to include their own per-child state. 311 * 312 * Note that this 'value' is serialized with the corresponding child 'key' 313 * when the BeanContextSupport is serialized. 314 */ 315 316 protected class BCSChild implements Serializable { 317 318 private static final long serialVersionUID = -5815286101609939109L; 319 320 BCSChild(Object bcc, Object peer) { 321 super(); 322 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 = 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) { 515 if (callChildSetBC) { 516 BeanContextChild cbcc = getChildBeanContextChild(targetChild); 517 if (cbcc != null) synchronized(cbcc) { 518 cbcc.removePropertyChangeListener("beanContext", childPCL); 519 cbcc.removeVetoableChangeListener("beanContext", childVCL); 520 521 try { 522 cbcc.setBeanContext(null); 523 } catch (PropertyVetoException pve1) { 524 cbcc.addPropertyChangeListener("beanContext", childPCL); 525 cbcc.addVetoableChangeListener("beanContext", childVCL); 526 throw new IllegalStateException(); 527 } 528 529 } 530 } 531 532 synchronized (children) { 533 children.remove(targetChild); 534 535 if (bcsc.isProxyPeer()) { 536 pbcsc = children.get(peer = bcsc.getProxyPeer()); 537 children.remove(peer); 538 } 539 } 540 541 if (getChildSerializable(targetChild) != null) serializable--; 542 543 childJustRemovedHook(targetChild, bcsc); 544 545 if (peer != null) { 546 if (getChildSerializable(peer) != null) serializable--; 547 548 childJustRemovedHook(peer, pbcsc); 549 } 550 } 551 552 fireChildrenRemoved(new BeanContextMembershipEvent(getBeanContextPeer(), peer == null ? new Object[] { targetChild } : new Object[] { targetChild, peer } )); 553 554 } 555 556 return true; 557 } 558 559 /** 560 * Tests to see if all objects in the 561 * specified <tt>Collection</tt> are children of 562 * this <tt>BeanContext</tt>. 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 @SuppressWarnings("rawtypes") 570 public boolean containsAll(Collection c) { 571 synchronized(children) { 572 Iterator<?> i = c.iterator(); 573 while (i.hasNext()) 574 if(!contains(i.next())) 575 return false; 576 577 return true; 578 } 579 } 580 581 /** 582 * add Collection to set of Children (Unsupported) 583 * implementations must synchronized on the hierarchy lock and "children" protected field 584 * @throws UnsupportedOperationException thrown unconditionally by this implementation 585 * @return this implementation unconditionally throws {@code UnsupportedOperationException} 586 */ 587 @SuppressWarnings("rawtypes") 588 public boolean addAll(Collection c) { 589 throw new UnsupportedOperationException(); 590 } 591 592 /** 593 * remove all specified children (Unsupported) 594 * implementations must synchronized on the hierarchy lock and "children" protected field 595 * @throws UnsupportedOperationException thrown unconditionally by this implementation 596 * @return this implementation unconditionally throws {@code UnsupportedOperationException} 597 598 */ 599 @SuppressWarnings("rawtypes") 600 public boolean removeAll(Collection c) { 601 throw new UnsupportedOperationException(); 602 } 603 604 605 /** 606 * retain only specified children (Unsupported) 607 * implementations must synchronized on the hierarchy lock and "children" protected field 608 * @throws UnsupportedOperationException thrown unconditionally by this implementation 609 * @return this implementation unconditionally throws {@code UnsupportedOperationException} 610 */ 611 @SuppressWarnings("rawtypes") 612 public boolean retainAll(Collection c) { 613 throw new UnsupportedOperationException(); 614 } 615 616 /** 617 * clear the children (Unsupported) 618 * implementations must synchronized on the hierarchy lock and "children" protected field 619 * @throws UnsupportedOperationException thrown unconditionally by this implementation 620 */ 621 public void clear() { 622 throw new UnsupportedOperationException(); 623 } 624 625 /** 626 * Adds a BeanContextMembershipListener 627 * 628 * @param bcml the BeanContextMembershipListener to add 629 * @throws NullPointerException if the argument is null 630 */ 631 750 * if the implementor "needs" a GUI. 751 * </p> 752 * <p> 753 * The algorithm used herein tests the BeanContextPeer, and its current children 754 * to determine if they are either Containers, Components, or if they implement 755 * Visibility and return needsGui() == true. 756 * </p> 757 * @return <tt>true</tt> if the implementor needs a GUI 758 */ 759 public synchronized boolean needsGui() { 760 BeanContext bc = getBeanContextPeer(); 761 762 if (bc != this) { 763 if (bc instanceof Visibility) return ((Visibility)bc).needsGui(); 764 765 if (bc instanceof Container || bc instanceof Component) 766 return true; 767 } 768 769 synchronized(children) { 770 for (Iterator<Object> i = children.keySet().iterator(); i.hasNext();) { 771 Object c = i.next(); 772 773 try { 774 return ((Visibility)c).needsGui(); 775 } catch (ClassCastException cce) { 776 // do nothing ... 777 } 778 779 if (c instanceof Container || c instanceof Component) 780 return true; 781 } 782 } 783 784 return false; 785 } 786 787 /** 788 * notify this instance that it may no longer render a GUI. 789 */ 790 791 public synchronized void dontUseGui() { 792 if (okToUseGui) { 793 okToUseGui = false; 794 795 // lets also tell the Children that can that they may not use their GUI's 796 synchronized(children) { 797 for (Iterator<Object> i = children.keySet().iterator(); i.hasNext();) { 798 Visibility v = getChildVisibility(i.next()); 799 800 if (v != null) v.dontUseGui(); 801 } 802 } 803 } 804 } 805 806 /** 807 * Notify this instance that it may now render a GUI 808 */ 809 810 public synchronized void okToUseGui() { 811 if (!okToUseGui) { 812 okToUseGui = true; 813 814 // lets also tell the Children that can that they may use their GUI's 815 synchronized(children) { 816 for (Iterator<Object> i = children.keySet().iterator(); i.hasNext();) { 817 Visibility v = getChildVisibility(i.next()); 818 819 if (v != null) v.okToUseGui(); 820 } 821 } 822 } 823 } 824 825 /** 826 * Used to determine if the <tt>BeanContext</tt> 827 * child is avoiding using its GUI. 828 * @return is this instance avoiding using its GUI? 829 * @see Visibility 830 */ 831 public boolean avoidingGui() { 832 return !okToUseGui && needsGui(); 833 } 834 835 /** 836 * Is this <tt>BeanContext</tt> in the 837 * process of being serialized? 838 * @return if this <tt>BeanContext</tt> is 839 * currently being serialized 840 */ 841 public boolean isSerializing() { return serializing; } 842 843 /** 844 * Returns an iterator of all children 845 * of this <tt>BeanContext</tt>. 846 * @return an iterator for all the current BCSChild values 847 */ 848 protected Iterator<BCSChild> bcsChildren() { synchronized(children) { return children.values().iterator(); } } 849 850 /** 851 * called by writeObject after defaultWriteObject() but prior to 852 * serialization of currently serializable children. 853 * 854 * This method may be overridden by subclasses to perform custom 855 * serialization of their state prior to this superclass serializing 856 * the children. 857 * 858 * This method should not however be used by subclasses to replace their 859 * own implementation (if any) of writeObject(). 860 * @param oos the {@code ObjectOutputStream} to use during serialization 861 * @throws IOException if serialization failed 862 */ 863 864 protected void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException { 865 } 866 867 /** 868 * called by readObject after defaultReadObject() but prior to 883 } 884 885 /** 886 * Called by readObject with the newly deserialized child and BCSChild. 887 * @param child the newly deserialized child 888 * @param bcsc the newly deserialized BCSChild 889 */ 890 protected void childDeserializedHook(Object child, BCSChild bcsc) { 891 synchronized(children) { 892 children.put(child, bcsc); 893 } 894 } 895 896 /** 897 * Used by writeObject to serialize a Collection. 898 * @param oos the <tt>ObjectOutputStream</tt> 899 * to use during serialization 900 * @param coll the <tt>Collection</tt> to serialize 901 * @throws IOException if serialization failed 902 */ 903 protected final void serialize(ObjectOutputStream oos, Collection<?> coll) throws IOException { 904 int count = 0; 905 Object[] objects = coll.toArray(); 906 907 for (int i = 0; i < objects.length; i++) { 908 if (objects[i] instanceof Serializable) 909 count++; 910 else 911 objects[i] = null; 912 } 913 914 oos.writeInt(count); // number of subsequent objects 915 916 for (int i = 0; count > 0; i++) { 917 Object o = objects[i]; 918 919 if (o != null) { 920 oos.writeObject(o); 921 count--; 922 } 923 } 924 } 925 926 /** 927 * used by readObject to deserialize a collection. 928 * @param ois the ObjectInputStream to use 929 * @param coll the Collection 930 * @throws IOException if deserialization failed 931 * @throws ClassNotFoundException if needed classes are not found 932 */ 933 @SuppressWarnings({"rawtypes", "unchecked"}) 934 protected final void deserialize(ObjectInputStream ois, Collection coll) throws IOException, ClassNotFoundException { 935 int count = 0; 936 937 count = ois.readInt(); 938 939 while (count-- > 0) { 940 coll.add(ois.readObject()); 941 } 942 } 943 944 /** 945 * Used to serialize all children of 946 * this <tt>BeanContext</tt>. 947 * @param oos the <tt>ObjectOutputStream</tt> 948 * to use during serialization 949 * @throws IOException if serialization failed 950 */ 951 public final void writeChildren(ObjectOutputStream oos) throws IOException { 952 if (serializable <= 0) return; 953 954 boolean prev = serializing; 955 956 serializing = true; 957 958 int count = 0; 959 960 synchronized(children) { 961 Iterator<Map.Entry<Object, BCSChild>> i = children.entrySet().iterator(); 962 963 while (i.hasNext() && count < serializable) { 964 Map.Entry<Object, BCSChild> entry = i.next(); 965 966 if (entry.getKey() instanceof Serializable) { 967 try { 968 oos.writeObject(entry.getKey()); // child 969 oos.writeObject(entry.getValue()); // BCSChild 970 } catch (IOException ioe) { 971 serializing = prev; 972 throw ioe; 973 } 974 count++; 975 } 976 } 977 } 978 979 serializing = prev; 980 981 if (count != serializable) { 982 throw new IOException("wrote different number of children than expected"); 983 } 984 1070 } 1071 1072 /** 1073 * deserialize contents ... if this instance has a distinct peer the 1074 * children are *not* serialized here, the peer's readObject() must call 1075 * readChildren() after deserializing this instance. 1076 */ 1077 1078 private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 1079 1080 synchronized(BeanContext.globalHierarchyLock) { 1081 ois.defaultReadObject(); 1082 1083 initialize(); 1084 1085 bcsPreDeserializationHook(ois); 1086 1087 if (serializable > 0 && this.equals(getBeanContextPeer())) 1088 readChildren(ois); 1089 1090 deserialize(ois, bcmListeners = new ArrayList<>(1)); 1091 } 1092 } 1093 1094 /** 1095 * subclasses may envelope to monitor veto child property changes. 1096 */ 1097 1098 public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException { 1099 String propertyName = pce.getPropertyName(); 1100 Object source = pce.getSource(); 1101 1102 synchronized(children) { 1103 if ("beanContext".equals(propertyName) && 1104 containsKey(source) && 1105 !getBeanContextPeer().equals(pce.getNewValue()) 1106 ) { 1107 if (!validatePendingRemove(source)) { 1108 throw new PropertyVetoException("current BeanContext vetoes setBeanContext()", pce); 1109 } else children.get(source).setRemovePending(true); 1110 } 1111 } 1112 } 1113 1114 /** 1115 * subclasses may envelope to monitor child property changes. 1116 */ 1117 1118 public void propertyChange(PropertyChangeEvent pce) { 1119 String propertyName = pce.getPropertyName(); 1120 Object source = pce.getSource(); 1121 1122 synchronized(children) { 1123 if ("beanContext".equals(propertyName) && 1124 containsKey(source) && 1125 children.get(source).isRemovePending()) { 1126 BeanContext bc = getBeanContextPeer(); 1127 1128 if (bc.equals(pce.getOldValue()) && !bc.equals(pce.getNewValue())) { 1129 remove(source, false); 1130 } else { 1131 children.get(source).setRemovePending(false); 1132 } 1133 } 1134 } 1135 } 1136 1137 /** 1138 * <p> 1139 * Subclasses of this class may override, or envelope, this method to 1140 * add validation behavior for the BeanContext to examine child objects 1141 * immediately prior to their being added to the BeanContext. 1142 * </p> 1143 * 1144 * @param targetChild the child to create the Child on behalf of 1145 * @return true iff the child may be added to this BeanContext, otherwise false. 1146 */ 1147 1148 protected boolean validatePendingAdd(Object targetChild) { 1149 return true; 1150 } 1151 1300 Object[] copy; 1301 1302 synchronized(bcmListeners) { copy = bcmListeners.toArray(); } 1303 1304 for (int i = 0; i < copy.length; i++) 1305 ((BeanContextMembershipListener)copy[i]).childrenRemoved(bcme); 1306 } 1307 1308 /** 1309 * protected method called from constructor and readObject to initialize 1310 * transient state of BeanContextSupport instance. 1311 * 1312 * This class uses this method to instantiate inner class listeners used 1313 * to monitor PropertyChange and VetoableChange events on children. 1314 * 1315 * subclasses may envelope this method to add their own initialization 1316 * behavior 1317 */ 1318 1319 protected synchronized void initialize() { 1320 children = new HashMap<>(serializable + 1); 1321 bcmListeners = new ArrayList<>(1); 1322 1323 childPCL = new PropertyChangeListener() { 1324 1325 /* 1326 * this adaptor is used by the BeanContextSupport class to forward 1327 * property changes from a child to the BeanContext, avoiding 1328 * accidential serialization of the BeanContext by a badly 1329 * behaved Serializable child. 1330 */ 1331 1332 public void propertyChange(PropertyChangeEvent pce) { 1333 BeanContextSupport.this.propertyChange(pce); 1334 } 1335 }; 1336 1337 childVCL = new VetoableChangeListener() { 1338 1339 /* 1340 * this adaptor is used by the BeanContextSupport class to forward 1341 * vetoable changes from a child to the BeanContext, avoiding 1347 BeanContextSupport.this.vetoableChange(pce); 1348 } 1349 }; 1350 } 1351 1352 /** 1353 * Gets a copy of the this BeanContext's children. 1354 * @return a copy of the current nested children 1355 */ 1356 protected final Object[] copyChildren() { 1357 synchronized(children) { return children.keySet().toArray(); } 1358 } 1359 1360 /** 1361 * Tests to see if two class objects, 1362 * or their names are equal. 1363 * @param first the first object 1364 * @param second the second object 1365 * @return true if equal, false if not 1366 */ 1367 protected static final boolean classEquals(Class<?> first, Class<?> second) { 1368 return first.equals(second) || first.getName().equals(second.getName()); 1369 } 1370 1371 1372 /* 1373 * fields 1374 */ 1375 1376 1377 /** 1378 * all accesses to the <code> protected HashMap children </code> field 1379 * shall be synchronized on that object. 1380 */ 1381 protected transient HashMap<Object, BCSChild> children; 1382 1383 private int serializable = 0; // children serializable 1384 1385 /** 1386 * all accesses to the <code> protected ArrayList bcmListeners </code> field 1387 * shall be synchronized on that object. 1388 */ 1389 protected transient ArrayList<BeanContextMembershipListener> bcmListeners; 1390 1391 // 1392 1393 /** 1394 * The current locale of this BeanContext. 1395 */ 1396 protected Locale locale; 1397 1398 /** 1399 * A <tt>boolean</tt> indicating if this 1400 * instance may now render a GUI. 1401 */ 1402 protected boolean okToUseGui; 1403 1404 1405 /** 1406 * A <tt>boolean</tt> indicating whether or not 1407 * this object is currently in design time mode. 1408 */ 1409 protected boolean designTime; |