Source for java.beans.beancontext.BeanContextSupport

   1: /* BeanContextSupport.java --
   2:    Copyright (C) 2003, 2005, 2006  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.beans.beancontext;
  40: 
  41: import gnu.classpath.NotImplementedException;
  42: 
  43: import java.beans.Beans;
  44: import java.beans.DesignMode;
  45: import java.beans.PropertyChangeEvent;
  46: import java.beans.PropertyChangeListener;
  47: import java.beans.PropertyVetoException;
  48: import java.beans.VetoableChangeListener;
  49: import java.beans.Visibility;
  50: import java.io.IOException;
  51: import java.io.InputStream;
  52: import java.io.ObjectInputStream;
  53: import java.io.ObjectOutputStream;
  54: import java.io.Serializable;
  55: import java.net.URL;
  56: import java.util.ArrayList;
  57: import java.util.Collection;
  58: import java.util.HashMap;
  59: import java.util.Iterator;
  60: import java.util.Locale;
  61: 
  62: /**
  63:  * This is a helper class for implementing a bean context.  It is
  64:  * intended to be used either by subclassing or by calling methods
  65:  * of this implementation from another.
  66:  *
  67:  * @author Michael Koch
  68:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
  69:  * @since 1.2
  70:  */
  71: public class BeanContextSupport extends BeanContextChildSupport
  72:   implements BeanContext, Serializable, PropertyChangeListener,
  73:   VetoableChangeListener
  74: {
  75:   private static final long serialVersionUID = -4879613978649577204L;
  76: 
  77:   // This won't show up in japi, but we mark it as a stub anyway,
  78:   // so that searches for NotImplementedException will find it.
  79:   private void readObject (ObjectInputStream s)
  80:     throws ClassNotFoundException, IOException, NotImplementedException
  81:   {
  82:     throw new Error ("Not implemented");
  83:   }
  84: 
  85:   // This won't show up in japi, but we mark it as a stub anyway,
  86:   // so that searches for NotImplementedException will find it.
  87:   private void writeObject (ObjectOutputStream s)
  88:     throws ClassNotFoundException, IOException, NotImplementedException
  89:   {
  90:     throw new Error ("Not implemented");
  91:   }
  92: 
  93:   protected class BCSChild implements Serializable
  94:   {
  95:     private static final long serialVersionUID = -5815286101609939109L;
  96: 
  97:     private Object targetChild;
  98:     private Object peer;
  99: 
 100:     BCSChild(Object targetChild, Object peer)
 101:     {
 102:       this.targetChild = targetChild;
 103:       this.peer = peer;
 104:     }
 105:   }
 106: 
 107:   protected static final class BCSIterator implements Iterator
 108:   {
 109:     private Iterator child;
 110: 
 111:     BCSIterator(Iterator child)
 112:     {
 113:       this.child = child;
 114:     }
 115: 
 116:     public boolean hasNext ()
 117:     {
 118:       return child.hasNext();
 119:     }
 120: 
 121:     public Object next ()
 122:     {
 123:       return child.next();
 124:     }
 125: 
 126:     public void remove ()
 127:     {
 128:       // This must be a noop remove operation.
 129:     }
 130:   }
 131: 
 132:   protected transient ArrayList bcmListeners;
 133: 
 134:   protected transient HashMap children;
 135: 
 136:   protected transient boolean designTime;
 137: 
 138:   protected transient Locale locale;
 139: 
 140:   protected transient boolean okToUseGui;
 141: 
 142:   /**
 143:    * Construct a BeanContextSupport instance.
 144:    */
 145:   public BeanContextSupport ()
 146:   {
 147:     this (null, null, true, true);
 148:   }
 149: 
 150:   /**
 151:    * Construct a BeanContextSupport instance.
 152:    */
 153:   public BeanContextSupport (BeanContext peer)
 154:   {
 155:     this (peer, null, true, true);
 156:   }
 157: 
 158:   /**
 159:    * Construct a BeanContextSupport instance.
 160:    */
 161:   public BeanContextSupport (BeanContext peer, Locale lcle)
 162:   {
 163:     this (peer, lcle, true, true);
 164:   }
 165: 
 166:   /**
 167:    * Construct a BeanContextSupport instance.
 168:    */
 169:   public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime)
 170:   {
 171:     this (peer, lcle, dtime, true);
 172:   }
 173: 
 174:   /**
 175:    * Construct a BeanContextSupport instance.
 176:    */
 177:   public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime,
 178:                              boolean visible)
 179:   {
 180:     super(peer);
 181: 
 182:     locale = lcle == null ? Locale.getDefault() : lcle;
 183:     designTime = dtime;
 184:     okToUseGui = visible;
 185: 
 186:     initialize ();
 187:   }
 188: 
 189:   /**
 190:    * <p>
 191:    * Add a child to the bean context.  A child can be a simple
 192:    * <code>Object</code>, a <code>BeanContextChild</code>
 193:    * or another <code>BeanContext</code>.  
 194:    * </p>
 195:    * <p>
 196:    * The children of a <code>BeanContext</code> form a set.  As
 197:    * a result, this method returns <code>false</code> if the given
 198:    * object is already a child of this context.
 199:    * </p>
 200:    * <p>
 201:    * If the child is a <code>BeanContextChild</code>, or a proxy
 202:    * for such a child, the <code>setBeanContext()</code> method
 203:    * is invoked on the child.  If this operation is vetoed by the
 204:    * child, via throwing a <code>PropertyVetoException</code>,
 205:    * then the current completion state of the <code>add()</code>
 206:    * operation is rolled back and a <code>IllegalStateException</code>
 207:    * is thrown.  If the <code>BeanContextChild</code> is successfully
 208:    * added, then the context registers with its
 209:    * <code>PropertyChangeListener</code> and
 210:    * <code>VetoableChangeListener</code> for "beanContext" events.
 211:    * </p>
 212:    * <p>
 213:    * If the child implements <code>java.beans.Visibility</code>,
 214:    * then its ability to use a GUI is set based on that of
 215:    * this context.
 216:    * </p>
 217:    * <p> 
 218:    * A <code>BeanContextMembershipEvent</code> is fired when the
 219:    * child is successfully added to the bean context.
 220:    * </p>
 221:    * <p>
 222:    * This method is synchronized over the global hierarchy lock.
 223:    * </p>
 224:    *
 225:    * @param targetChild the child to add.
 226:    * @return false if the child has already been added.
 227:    * @throws IllegalArgumentException if the child is null.
 228:    * @throws IllegalStateException if the child vetos the setting
 229:    *                               of its context.
 230:    */
 231:   public boolean add(Object targetChild)
 232:   {
 233:     synchronized (globalHierarchyLock)
 234:       {
 235:     if (targetChild == null)
 236:       throw new IllegalArgumentException();
 237: 
 238:     BCSChild child;
 239:     synchronized (children)
 240:       {
 241:         if (children.containsKey(targetChild)
 242:         || ! validatePendingAdd(targetChild))
 243:           return false;
 244:         child = createBCSChild(targetChild, beanContextChildPeer);
 245:         children.put(targetChild, child);
 246:       }
 247:     synchronized (targetChild)
 248:       {
 249:         BeanContextChild bcChild = null;
 250:         if (targetChild instanceof BeanContextChild)
 251:           bcChild = (BeanContextChild) targetChild;
 252:         if (targetChild instanceof BeanContextProxy)
 253:           bcChild = ((BeanContextProxy) targetChild).getBeanContextProxy();
 254:         if (bcChild != null)
 255:           try
 256:         {
 257:           bcChild.setBeanContext(this);
 258:           bcChild.addVetoableChangeListener("beanContext", this);
 259:           bcChild.addPropertyChangeListener("beanContext", this);
 260:         }
 261:           catch (PropertyVetoException e)
 262:         {
 263:           synchronized (children)
 264:             {
 265:               children.remove(targetChild);
 266:             }
 267:           throw new IllegalStateException("The child refused to " +
 268:                           "associate itself with " +
 269:                           "this context.", e);
 270:         }
 271:         if (targetChild instanceof Visibility)
 272:           {
 273:         Visibility visibleChild = (Visibility) targetChild;
 274:         if (okToUseGui)
 275:           visibleChild.okToUseGui();
 276:         else
 277:           visibleChild.dontUseGui();
 278:           }
 279:         childJustAddedHook(targetChild, child);
 280:       }
 281:     fireChildrenAdded(new BeanContextMembershipEvent(this,
 282:                              new Object[]{ targetChild }));
 283:     return true;
 284:       }
 285:   }
 286: 
 287:   public boolean addAll (Collection c)
 288:   {
 289:     // Intentionally throws an exception.
 290:     throw new UnsupportedOperationException();
 291:   }
 292: 
 293:   public void addBeanContextMembershipListener
 294:     (BeanContextMembershipListener listener)
 295:   {
 296:     synchronized (bcmListeners)
 297:       {
 298:         if (! bcmListeners.contains(listener))
 299:           bcmListeners.add(listener);
 300:       }
 301:   }
 302: 
 303:   /**
 304:    * Returns true if this bean needs a GUI
 305:    * but is being prevented from using one.
 306:    *
 307:    * @return true if <code>needsGui()</code>
 308:    *              is true but the bean has been
 309:    *              told not to use it.
 310:    */
 311:   public boolean avoidingGui()
 312:     throws NotImplementedException
 313:   {
 314:     return needsGui() && (!okToUseGui);
 315:   }
 316: 
 317:   protected Iterator bcsChildren ()
 318:   {
 319:     synchronized (children)
 320:       {
 321:         return new BCSIterator(children.values().iterator());
 322:       }
 323:   }
 324: 
 325:   protected void bcsPreDeserializationHook (ObjectInputStream ois)
 326:     throws ClassNotFoundException, IOException, NotImplementedException
 327:   {
 328:     throw new Error ("Not implemented");
 329:   }
 330: 
 331:   protected void bcsPreSerializationHook (ObjectOutputStream oos)
 332:     throws IOException, NotImplementedException
 333:   {
 334:     throw new Error ("Not implemented");
 335:   }
 336: 
 337:   protected void childDeserializedHook (Object child, BeanContextSupport.BCSChild bcsc)
 338:     throws NotImplementedException
 339:   {
 340:     throw new Error ("Not implemented");
 341:   }
 342: 
 343:   protected void childJustAddedHook (Object child, BeanContextSupport.BCSChild bcsc)
 344:   {
 345:     // Do nothing in the base class.
 346:   }
 347: 
 348:   protected void childJustRemovedHook (Object child, BeanContextSupport.BCSChild bcsc)
 349:   {
 350:     // Do nothing in the base class.
 351:   }
 352: 
 353:   protected static final boolean classEquals (Class first, Class second)
 354:   {
 355:     // Lame function!
 356:     return (first == second || first.getName().equals(second.getName()));
 357:   }
 358: 
 359:   public void clear ()
 360:   {
 361:     // This is the right thing to do.
 362:     // The JDK docs are really bad here.
 363:     throw new UnsupportedOperationException();
 364:   }
 365: 
 366:   public boolean contains (Object o)
 367:   {
 368:     synchronized (children)
 369:       {
 370:         return children.containsKey(o);
 371:       }
 372:   }
 373: 
 374:   public boolean containsAll (Collection c)
 375:   {
 376:     synchronized (children)
 377:       {
 378:         Iterator it = c.iterator();
 379:         while (it.hasNext())
 380:           if (! children.containsKey(it.next()))
 381:             return false;
 382:       }
 383:     return true;
 384:   }
 385: 
 386:   public boolean containsKey (Object o)
 387:   {
 388:     synchronized (children)
 389:       {
 390:         return children.containsKey(o);
 391:       }
 392:   }
 393: 
 394:   protected final Object[] copyChildren ()
 395:   {
 396:     synchronized (children)
 397:       {
 398:         return children.keySet().toArray();
 399:       }
 400:   }
 401: 
 402:   protected BeanContextSupport.BCSChild createBCSChild (Object targetChild, Object peer)
 403:   {
 404:     return new BCSChild(targetChild, peer);
 405:   }
 406: 
 407:   protected final void deserialize (ObjectInputStream ois, Collection coll)
 408:     throws ClassNotFoundException, IOException, NotImplementedException
 409:   {
 410:     throw new Error ("Not implemented");
 411:   }
 412: 
 413:   /**
 414:    * Informs this bean that is should not make
 415:    * use of the GUI.
 416:    */
 417:   public void dontUseGui()
 418:   {
 419:     okToUseGui = false;
 420:   }
 421: 
 422:   protected final void fireChildrenAdded (BeanContextMembershipEvent bcme)
 423:   {
 424:     synchronized (bcmListeners)
 425:       {
 426:         Iterator it = bcmListeners.iterator();
 427:         while (it.hasNext())
 428:           {
 429:             BeanContextMembershipListener l
 430:               = (BeanContextMembershipListener) it.next();
 431:             l.childrenAdded(bcme);
 432:           }
 433:       }
 434:   }
 435: 
 436:   protected final void fireChildrenRemoved (BeanContextMembershipEvent bcme)
 437:   {
 438:     synchronized (bcmListeners)
 439:       {
 440:         Iterator it = bcmListeners.iterator();
 441:         while (it.hasNext())
 442:           {
 443:             BeanContextMembershipListener l
 444:             = (BeanContextMembershipListener) it.next();
 445:             l.childrenRemoved(bcme);
 446:           }
 447:       }
 448:   }
 449: 
 450:   public BeanContext getBeanContextPeer ()
 451:     throws NotImplementedException
 452:   {
 453:     throw new Error ("Not implemented");
 454:   }
 455: 
 456:   protected static final BeanContextChild getChildBeanContextChild (Object child)
 457:     throws NotImplementedException
 458:   {
 459:     throw new Error ("Not implemented");
 460:   }
 461: 
 462:   protected static final BeanContextMembershipListener getChildBeanContextMembershipListener (Object child)
 463:     throws NotImplementedException
 464:   {
 465:     throw new Error ("Not implemented");
 466:   }
 467: 
 468:   protected static final PropertyChangeListener getChildPropertyChangeListener (Object child)
 469:     throws NotImplementedException
 470:   {
 471:     throw new Error ("Not implemented");
 472:   }
 473: 
 474:   protected static final Serializable getChildSerializable (Object child)
 475:     throws NotImplementedException
 476:   {
 477:     throw new Error ("Not implemented");
 478:   }
 479: 
 480:   protected static final VetoableChangeListener getChildVetoableChangeListener (Object child)
 481:     throws NotImplementedException
 482:   {
 483:     throw new Error ("Not implemented");
 484:   }
 485: 
 486:   protected static final Visibility getChildVisibility (Object child)
 487:     throws NotImplementedException
 488:   {
 489:     throw new Error ("Not implemented");
 490:   }
 491: 
 492:   public Locale getLocale ()
 493:   {
 494:     return locale;
 495:   }
 496: 
 497:   public URL getResource (String name, BeanContextChild bcc)
 498:   {
 499:     if (! contains(bcc))
 500:       throw new IllegalArgumentException("argument not a child");
 501:     ClassLoader loader = bcc.getClass().getClassLoader();
 502:     return (loader == null ? ClassLoader.getSystemResource(name)
 503:             : loader.getResource(name));
 504:   }
 505: 
 506:   public InputStream getResourceAsStream (String name, BeanContextChild bcc)
 507:   {
 508:     if (! contains(bcc))
 509:       throw new IllegalArgumentException("argument not a child");
 510:     ClassLoader loader = bcc.getClass().getClassLoader();
 511:     return (loader == null ? ClassLoader.getSystemResourceAsStream(name)
 512:             : loader.getResourceAsStream(name));
 513:   }
 514: 
 515:   protected void initialize ()
 516:   {
 517:     bcmListeners = new ArrayList();
 518:     children = new HashMap();
 519:   }
 520: 
 521:   /**
 522:    * This is a convenience method for instantiating a bean inside this
 523:    * context.  It delegates to the appropriate method in
 524:    * <code>java.beans.Beans</code> using the context's classloader.
 525:    *
 526:    * @param beanName the name of the class of bean to instantiate.
 527:    * @throws IOException if an I/O error occurs in loading the class.
 528:    * @throws ClassNotFoundException if the class, <code>beanName</code>,
 529:    *                                can not be found.
 530:    */
 531:   public Object instantiateChild (String beanName)
 532:     throws IOException, ClassNotFoundException
 533:   {
 534:     return Beans.instantiate(getClass().getClassLoader(), beanName, this);
 535:   }
 536: 
 537:   public boolean isDesignTime ()
 538:   {
 539:     return designTime;
 540:   }
 541: 
 542:   /**
 543:    * Returns true if this bean context has no children.
 544:    *
 545:    * @return true if there are no children.
 546:    */
 547:   public boolean isEmpty ()
 548:   {
 549:     synchronized (children)
 550:       {
 551:         return children.isEmpty();
 552:       }
 553:   }
 554: 
 555:   public boolean isSerializing ()
 556:     throws NotImplementedException
 557:   {
 558:     throw new Error ("Not implemented");
 559:   }
 560: 
 561:   public Iterator iterator ()
 562:   {
 563:     synchronized (children)
 564:       {
 565:         return children.keySet().iterator();
 566:       }
 567:   }
 568: 
 569:   /**
 570:    * Returns false as this bean does not a
 571:    * GUI for its operation.
 572:    *
 573:    * @return false
 574:    */
 575:   public boolean needsGui()
 576:   {
 577:     return false;
 578:   }
 579: 
 580:   /**
 581:    * Informs this bean that it is okay to make use of
 582:    * the GUI.
 583:    */
 584:   public void okToUseGui ()
 585:   {
 586:     okToUseGui = true;
 587:   }
 588: 
 589:   /**
 590:    * Subclasses may use this method to catch property changes
 591:    * arising from the children of this context.  At present,
 592:    * we just listen for the beans being assigned to a different
 593:    * context and remove them from here if such an event occurs.
 594:    *
 595:    * @param pce the property change event.
 596:    */
 597:   public void propertyChange (PropertyChangeEvent pce)
 598:   {
 599:     if (pce.getNewValue() != this)
 600:       remove(pce.getSource(), false);
 601:   }
 602: 
 603:   public final void readChildren (ObjectInputStream ois)
 604:     throws IOException, ClassNotFoundException, NotImplementedException
 605:   {
 606:     throw new Error ("Not implemented");
 607:   }
 608: 
 609:   /**
 610:    * Remove the specified child from the context.  This is
 611:    * the same as calling <code>remove(Object,boolean)</code>
 612:    * with a request for the <code>setBeanContext()</code> method
 613:    * of the child to be called (i.e. the second argument is true).
 614:    *
 615:    * @param targetChild the child to remove.
 616:    */
 617:   public boolean remove (Object targetChild)
 618:   {
 619:     return remove(targetChild, true);
 620:   }
 621: 
 622:   /**
 623:    * <p>
 624:    * Removes a child from the bean context.  A child can be a simple
 625:    * <code>Object</code>, a <code>BeanContextChild</code>
 626:    * or another <code>BeanContext</code>.  If the given child is not
 627:    * a child of this context, this method returns <code>false</code>.
 628:    * </p>
 629:    * <p>
 630:    * If the child is a <code>BeanContextChild</code>, or a proxy
 631:    * for such a child, the <code>setBeanContext()</code> method
 632:    * is invoked on the child (if specified).  If this operation is vetoed
 633:    * by the child, via throwing a <code>PropertyVetoException</code>,
 634:    * then the current completion state of the <code>remove()</code>
 635:    * operation is rolled back and a <code>IllegalStateException</code>
 636:    * is thrown.  If the <code>BeanContextChild</code> is successfully
 637:    * removed, then the context deregisters with its
 638:    * <code>PropertyChangeListener</code> and
 639:    * <code>VetoableChangeListener</code> for "beanContext" events.
 640:    * </p>
 641:    * <p> 
 642:    * A <code>BeanContextMembershipEvent</code> is fired when the
 643:    * child is successfully removed from the bean context.
 644:    * </p>
 645:    * <p>
 646:    * This method is synchronized over the global hierarchy lock.
 647:    * </p>
 648:    *
 649:    * @param targetChild the child to add.
 650:    * @param callChildSetBC true if the <code>setBeanContext()</code>
 651:    *                       method of the child should be called.
 652:    * @return false if the child doesn't exist.
 653:    * @throws IllegalArgumentException if the child is null.
 654:    * @throws IllegalStateException if the child vetos the setting
 655:    *                               of its context.
 656:    */
 657:   protected boolean remove (Object targetChild, boolean callChildSetBC)
 658:   {
 659:     synchronized (globalHierarchyLock)
 660:       {
 661:     if (targetChild == null)
 662:       throw new IllegalArgumentException();
 663: 
 664:     BCSChild child;
 665:     synchronized (children)
 666:       {
 667:         if (!children.containsKey(targetChild)
 668:         || !validatePendingRemove(targetChild))
 669:           return false;
 670:         child = (BCSChild) children.remove(targetChild);
 671:       }
 672:     synchronized (targetChild)
 673:       {
 674:         BeanContextChild bcChild = null;
 675:         if (targetChild instanceof BeanContextChild)
 676:           bcChild = (BeanContextChild) targetChild;
 677:         if (targetChild instanceof BeanContextProxy)
 678:           bcChild = ((BeanContextProxy) targetChild).getBeanContextProxy();
 679:         if (bcChild != null)
 680:           try
 681:         {
 682:           if (callChildSetBC)
 683:             bcChild.setBeanContext(null);
 684:           bcChild.removeVetoableChangeListener("beanContext", this);
 685:           bcChild.removePropertyChangeListener("beanContext", this);
 686:         }
 687:           catch (PropertyVetoException e)
 688:         {
 689:           synchronized (children)
 690:             {
 691:               children.put(targetChild, child);
 692:             }
 693:           throw new IllegalStateException("The child refused to " +
 694:                           "disassociate itself with " +
 695:                           "this context.", e);
 696:         }
 697:         childJustRemovedHook(targetChild, child);
 698:       }
 699:     fireChildrenRemoved(new BeanContextMembershipEvent(this,
 700:                              new Object[]{ targetChild }));
 701:     return true;
 702:       }
 703:   }
 704: 
 705:   public boolean removeAll (Collection c)
 706:   {
 707:     // Intentionally throws an exception.
 708:     throw new UnsupportedOperationException();
 709:   }
 710: 
 711:   public void removeBeanContextMembershipListener (BeanContextMembershipListener bcml)
 712:   {
 713:     synchronized (bcmListeners)
 714:       {
 715:         bcmListeners.remove(bcml);
 716:       }
 717:   }
 718: 
 719:   public boolean retainAll (Collection c)
 720:   {
 721:     // Intentionally throws an exception.
 722:     throw new UnsupportedOperationException();
 723:   }
 724: 
 725:   protected final void serialize (ObjectOutputStream oos, Collection coll)
 726:     throws IOException, NotImplementedException
 727:   {
 728:     throw new Error ("Not implemented");
 729:   }
 730: 
 731:   public void setDesignTime (boolean dtime)
 732:   {
 733:     boolean save = designTime;
 734:     designTime = dtime;
 735:     firePropertyChange(DesignMode.PROPERTYNAME, Boolean.valueOf(save),
 736:                        Boolean.valueOf(dtime));
 737:   }
 738: 
 739:   public void setLocale (Locale newLocale)
 740:     throws PropertyVetoException
 741:   {
 742:     if (newLocale == null || locale == newLocale)
 743:       return;
 744:     fireVetoableChange("locale", locale, newLocale);
 745:     Locale oldLocale = locale;
 746:     locale = newLocale;
 747:     firePropertyChange("locale", oldLocale, newLocale);
 748:   }
 749: 
 750:   public int size ()
 751:   {
 752:     synchronized (children)
 753:       {
 754:         return children.size();
 755:       }
 756:   }
 757: 
 758:   public Object[] toArray ()
 759:   {
 760:     synchronized (children)
 761:       {
 762:         return children.keySet().toArray();
 763:       }
 764:   }
 765: 
 766:   public Object[] toArray(Object[] array)
 767:     throws NotImplementedException
 768:   {
 769:     // This implementation is incorrect, I think.
 770:     synchronized (children)
 771:       {
 772:         return children.keySet().toArray(array);
 773:       }
 774:   }
 775: 
 776:   protected boolean validatePendingAdd (Object targetChild)
 777:   {
 778:     return true;
 779:   }
 780: 
 781:   protected boolean validatePendingRemove (Object targetChild)
 782:   {
 783:     return true;
 784:   }
 785: 
 786:   /**
 787:    * Subclasses may use this method to veto changes arising
 788:    * from the children of this context.
 789:    *
 790:    * @param pce the vetoable property change event fired.
 791:    */
 792:   public void vetoableChange (PropertyChangeEvent pce)
 793:     throws PropertyVetoException
 794:   {
 795:     /* Purposefully left empty */
 796:   }
 797: 
 798:   public final void writeChildren (ObjectOutputStream oos)
 799:     throws IOException, NotImplementedException
 800:   {
 801:     throw new Error ("Not implemented");
 802:   }
 803: }