mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1080 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1080 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Java
		
	
	
	
/* BeanContextSupport.java --
 | 
						|
   Copyright (C) 2003, 2005, 2006  Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
 | 
						|
package java.beans.beancontext;
 | 
						|
 | 
						|
import java.beans.Beans;
 | 
						|
import java.beans.DesignMode;
 | 
						|
import java.beans.PropertyChangeEvent;
 | 
						|
import java.beans.PropertyChangeListener;
 | 
						|
import java.beans.PropertyVetoException;
 | 
						|
import java.beans.VetoableChangeListener;
 | 
						|
import java.beans.Visibility;
 | 
						|
import java.io.IOException;
 | 
						|
import java.io.InputStream;
 | 
						|
import java.io.ObjectInputStream;
 | 
						|
import java.io.ObjectOutputStream;
 | 
						|
import java.io.Serializable;
 | 
						|
import java.net.URL;
 | 
						|
import java.util.ArrayList;
 | 
						|
import java.util.Collection;
 | 
						|
import java.util.HashMap;
 | 
						|
import java.util.Iterator;
 | 
						|
import java.util.List;
 | 
						|
import java.util.Locale;
 | 
						|
 | 
						|
/**
 | 
						|
 * This is a helper class for implementing a bean context.  It is
 | 
						|
 * intended to be used either by subclassing or by calling methods
 | 
						|
 * of this implementation from another.
 | 
						|
 *
 | 
						|
 * @author Michael Koch
 | 
						|
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 | 
						|
 * @since 1.2
 | 
						|
 */
 | 
						|
public class BeanContextSupport extends BeanContextChildSupport
 | 
						|
  implements BeanContext, Serializable, PropertyChangeListener,
 | 
						|
  VetoableChangeListener
 | 
						|
{
 | 
						|
  private static final long serialVersionUID = -4879613978649577204L;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Deserializes a stored bean context.  Hook methods are provided to allow
 | 
						|
   * subclasses to perform their own deserialization after the default
 | 
						|
   * deserialization but prior to the deserialization of the children.  Note that
 | 
						|
   * {@link #readChildren(ObjectInputStream)} is only called if there
 | 
						|
   * is no distinct peer.  If there is, the peer is expected to call
 | 
						|
   * the method instead.
 | 
						|
   *
 | 
						|
   * @param s the stream to deserialize.
 | 
						|
   * @throws ClassNotFoundException if the class of an object being deserialized
 | 
						|
   *                                could not be found.
 | 
						|
   * @throws IOException if an I/O error occurs.
 | 
						|
   */
 | 
						|
  private void readObject (ObjectInputStream s)
 | 
						|
    throws ClassNotFoundException, IOException
 | 
						|
  {
 | 
						|
    s.defaultReadObject();
 | 
						|
    bcsPreDeserializationHook(s);
 | 
						|
    BeanContext peer = getBeanContextPeer();
 | 
						|
    if (peer == null || peer == this)
 | 
						|
      readChildren(s);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Serializes a bean context.  Hook methods are provided to allow
 | 
						|
   * subclasses to perform their own serialization after the default
 | 
						|
   * serialization but prior to serialization of the children.  Note that
 | 
						|
   * {@link #writeChildren(ObjectOutputStream)} is only called if there
 | 
						|
   * is no distinct peer.  If there is, the peer is expected to call
 | 
						|
   * the method instead.
 | 
						|
   *
 | 
						|
   * @param s the stream to serialize.
 | 
						|
   * @throws ClassNotFoundException if the class of an object being deserialized
 | 
						|
   *                                could not be found.
 | 
						|
   * @throws IOException if an I/O error occurs.
 | 
						|
   */
 | 
						|
  private void writeObject (ObjectOutputStream s)
 | 
						|
    throws ClassNotFoundException, IOException
 | 
						|
  {
 | 
						|
    serializing = true;
 | 
						|
    s.defaultWriteObject();
 | 
						|
    bcsPreSerializationHook(s);
 | 
						|
    BeanContext peer = getBeanContextPeer();
 | 
						|
    if (peer == null || peer == this)
 | 
						|
      writeChildren(s);
 | 
						|
    serializing = false;
 | 
						|
  }
 | 
						|
 | 
						|
  protected class BCSChild implements Serializable
 | 
						|
  {
 | 
						|
    private static final long serialVersionUID = -5815286101609939109L;
 | 
						|
 | 
						|
    private Object targetChild;
 | 
						|
    private Object peer;
 | 
						|
 | 
						|
    BCSChild(Object targetChild, Object peer)
 | 
						|
    {
 | 
						|
      this.targetChild = targetChild;
 | 
						|
      this.peer = peer;
 | 
						|
    }
 | 
						|
 | 
						|
    private Object getTargetChild()
 | 
						|
    {
 | 
						|
      return targetChild;
 | 
						|
    }
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  protected static final class BCSIterator implements Iterator
 | 
						|
  {
 | 
						|
    private Iterator child;
 | 
						|
 | 
						|
    BCSIterator(Iterator child)
 | 
						|
    {
 | 
						|
      this.child = child;
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean hasNext ()
 | 
						|
    {
 | 
						|
      return child.hasNext();
 | 
						|
    }
 | 
						|
 | 
						|
    public Object next ()
 | 
						|
    {
 | 
						|
      return child.next();
 | 
						|
    }
 | 
						|
 | 
						|
    public void remove ()
 | 
						|
    {
 | 
						|
      // This must be a noop remove operation.
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  protected transient ArrayList bcmListeners;
 | 
						|
 | 
						|
  protected transient HashMap children;
 | 
						|
 | 
						|
  protected transient boolean designTime;
 | 
						|
 | 
						|
  protected transient Locale locale;
 | 
						|
 | 
						|
  protected transient boolean okToUseGui;
 | 
						|
 | 
						|
  private transient boolean serializing;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Construct a BeanContextSupport instance.
 | 
						|
   */
 | 
						|
  public BeanContextSupport ()
 | 
						|
  {
 | 
						|
    this (null, null, false, true);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Construct a BeanContextSupport instance.
 | 
						|
   *
 | 
						|
   * @param peer  the bean context peer (<code>null</code> permitted).
 | 
						|
   */
 | 
						|
  public BeanContextSupport(BeanContext peer)
 | 
						|
  {
 | 
						|
    this (peer, null, false, true);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Construct a BeanContextSupport instance.
 | 
						|
   *
 | 
						|
   * @param peer  the bean context peer (<code>null</code> permitted).
 | 
						|
   * @param locale  the locale (<code>null</code> permitted, equivalent to
 | 
						|
   *     the default locale).
 | 
						|
   */
 | 
						|
  public BeanContextSupport (BeanContext peer, Locale locale)
 | 
						|
  {
 | 
						|
    this (peer, locale, false, true);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Construct a BeanContextSupport instance.
 | 
						|
   *
 | 
						|
   * @param peer  the bean context peer (<code>null</code> permitted).
 | 
						|
   * @param locale  the locale (<code>null</code> permitted, equivalent to
 | 
						|
   *     the default locale).
 | 
						|
   * @param dtime  a flag indicating whether or not the bean context is in
 | 
						|
   *     design time mode.
 | 
						|
   */
 | 
						|
  public BeanContextSupport (BeanContext peer, Locale locale, boolean dtime)
 | 
						|
  {
 | 
						|
    this (peer, locale, dtime, true);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Construct a BeanContextSupport instance.
 | 
						|
   *
 | 
						|
   * @param peer  the bean context peer (<code>null</code> permitted).
 | 
						|
   * @param locale  the locale (<code>null</code> permitted, equivalent to
 | 
						|
   *     the default locale).
 | 
						|
   * @param dtime  a flag indicating whether or not the bean context is in
 | 
						|
   *     design time mode.
 | 
						|
   * @param visible  initial value of the <code>okToUseGui</code> flag.
 | 
						|
   */
 | 
						|
  public BeanContextSupport (BeanContext peer, Locale locale, boolean dtime,
 | 
						|
                             boolean visible)
 | 
						|
  {
 | 
						|
    super(peer);
 | 
						|
 | 
						|
    this.locale = locale == null ? Locale.getDefault() : locale;
 | 
						|
    designTime = dtime;
 | 
						|
    okToUseGui = visible;
 | 
						|
 | 
						|
    initialize ();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Add a child to the bean context.  A child can be a simple
 | 
						|
   * <code>Object</code>, a <code>BeanContextChild</code>
 | 
						|
   * or another <code>BeanContext</code>.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * The children of a <code>BeanContext</code> form a set.  As
 | 
						|
   * a result, this method returns <code>false</code> if the given
 | 
						|
   * object is already a child of this context.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * If the child is a <code>BeanContextChild</code>, or a proxy
 | 
						|
   * for such a child, the <code>setBeanContext()</code> method
 | 
						|
   * is invoked on the child.  If this operation is vetoed by the
 | 
						|
   * child, via throwing a <code>PropertyVetoException</code>,
 | 
						|
   * then the current completion state of the <code>add()</code>
 | 
						|
   * operation is rolled back and a <code>IllegalStateException</code>
 | 
						|
   * is thrown.  If the <code>BeanContextChild</code> is successfully
 | 
						|
   * added, then the context registers with its
 | 
						|
   * <code>PropertyChangeListener</code> and
 | 
						|
   * <code>VetoableChangeListener</code> for "beanContext" events.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * If the child implements <code>java.beans.Visibility</code>,
 | 
						|
   * then its ability to use a GUI is set based on that of
 | 
						|
   * this context.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * A <code>BeanContextMembershipEvent</code> is fired when the
 | 
						|
   * child is successfully added to the bean context.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * This method is synchronized over the global hierarchy lock.
 | 
						|
   * </p>
 | 
						|
   *
 | 
						|
   * @param targetChild the child to add.
 | 
						|
   * @return false if the child has already been added.
 | 
						|
   * @throws IllegalArgumentException if the child is null.
 | 
						|
   * @throws IllegalStateException if the child vetos the setting
 | 
						|
   *                               of its context.
 | 
						|
   */
 | 
						|
  public boolean add(Object targetChild)
 | 
						|
  {
 | 
						|
    synchronized (globalHierarchyLock)
 | 
						|
      {
 | 
						|
        if (targetChild == null)
 | 
						|
          throw new IllegalArgumentException();
 | 
						|
 | 
						|
        BCSChild child;
 | 
						|
        synchronized (children)
 | 
						|
          {
 | 
						|
            if (children.containsKey(targetChild)
 | 
						|
                || ! validatePendingAdd(targetChild))
 | 
						|
              return false;
 | 
						|
            child = createBCSChild(targetChild, beanContextChildPeer);
 | 
						|
            children.put(targetChild, child);
 | 
						|
          }
 | 
						|
        synchronized (targetChild)
 | 
						|
          {
 | 
						|
            BeanContextChild bcChild = null;
 | 
						|
            if (targetChild instanceof BeanContextChild)
 | 
						|
              bcChild = (BeanContextChild) targetChild;
 | 
						|
            if (targetChild instanceof BeanContextProxy)
 | 
						|
              bcChild = ((BeanContextProxy) targetChild).getBeanContextProxy();
 | 
						|
            if (bcChild != null)
 | 
						|
              try
 | 
						|
                {
 | 
						|
                  bcChild.setBeanContext(this);
 | 
						|
                  bcChild.addVetoableChangeListener("beanContext", this);
 | 
						|
                  bcChild.addPropertyChangeListener("beanContext", this);
 | 
						|
                }
 | 
						|
              catch (PropertyVetoException e)
 | 
						|
                {
 | 
						|
                  synchronized (children)
 | 
						|
                    {
 | 
						|
                      children.remove(targetChild);
 | 
						|
                    }
 | 
						|
                  throw new IllegalStateException("The child refused to " +
 | 
						|
                                                  "associate itself with " +
 | 
						|
                                                  "this context.", e);
 | 
						|
                }
 | 
						|
            if (targetChild instanceof Visibility)
 | 
						|
              {
 | 
						|
                Visibility visibleChild = (Visibility) targetChild;
 | 
						|
                if (okToUseGui)
 | 
						|
                  visibleChild.okToUseGui();
 | 
						|
                else
 | 
						|
                  visibleChild.dontUseGui();
 | 
						|
              }
 | 
						|
            childJustAddedHook(targetChild, child);
 | 
						|
          }
 | 
						|
        fireChildrenAdded(new BeanContextMembershipEvent(this,
 | 
						|
                                                         new Object[]{ targetChild }));
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean addAll (Collection c)
 | 
						|
  {
 | 
						|
    // Intentionally throws an exception.
 | 
						|
    throw new UnsupportedOperationException();
 | 
						|
  }
 | 
						|
 | 
						|
  public void addBeanContextMembershipListener
 | 
						|
    (BeanContextMembershipListener listener)
 | 
						|
  {
 | 
						|
    synchronized (bcmListeners)
 | 
						|
      {
 | 
						|
        if (! bcmListeners.contains(listener))
 | 
						|
          bcmListeners.add(listener);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns true if this bean needs a GUI
 | 
						|
   * but is being prevented from using one.
 | 
						|
   *
 | 
						|
   * @return true if <code>needsGui()</code>
 | 
						|
   *              is true but the bean has been
 | 
						|
   *              told not to use it.
 | 
						|
   */
 | 
						|
  public boolean avoidingGui()
 | 
						|
  {
 | 
						|
    return needsGui() && (!okToUseGui);
 | 
						|
  }
 | 
						|
 | 
						|
  protected Iterator bcsChildren ()
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return new BCSIterator(children.values().iterator());
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Subclasses may use this method to perform their own deserialization
 | 
						|
   * after the default deserialization process has taken place, but
 | 
						|
   * prior to the deserialization of the children.  It should not
 | 
						|
   * be used to replace the implementation of <code>readObject</code>
 | 
						|
   * in the subclass.
 | 
						|
   *
 | 
						|
   * @param ois the input stream.
 | 
						|
   * @throws ClassNotFoundException if the class of an object being deserialized
 | 
						|
   *                                could not be found.
 | 
						|
   * @throws IOException if an I/O error occurs.
 | 
						|
   */
 | 
						|
  protected void bcsPreDeserializationHook (ObjectInputStream ois)
 | 
						|
    throws ClassNotFoundException, IOException
 | 
						|
  {
 | 
						|
    /* Purposefully left empty */
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Subclasses may use this method to perform their own serialization
 | 
						|
   * after the default serialization process has taken place, but
 | 
						|
   * prior to the serialization of the children.  It should not
 | 
						|
   * be used to replace the implementation of <code>writeObject</code>
 | 
						|
   * in the subclass.
 | 
						|
   *
 | 
						|
   * @param oos the output stream.
 | 
						|
   * @throws IOException if an I/O error occurs.
 | 
						|
   */
 | 
						|
  protected void bcsPreSerializationHook (ObjectOutputStream oos)
 | 
						|
    throws IOException
 | 
						|
  {
 | 
						|
    /* Purposefully left empty */
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Called when a child is deserialized.
 | 
						|
   *
 | 
						|
   * @param child the deserialized child.
 | 
						|
   * @param bcsc the deserialized context wrapper for the child.
 | 
						|
   */
 | 
						|
  protected void childDeserializedHook (Object child, BeanContextSupport.BCSChild bcsc)
 | 
						|
  {
 | 
						|
    // Do nothing in the base class.
 | 
						|
  }
 | 
						|
 | 
						|
  protected void childJustAddedHook (Object child, BeanContextSupport.BCSChild bcsc)
 | 
						|
  {
 | 
						|
    // Do nothing in the base class.
 | 
						|
  }
 | 
						|
 | 
						|
  protected void childJustRemovedHook (Object child, BeanContextSupport.BCSChild bcsc)
 | 
						|
  {
 | 
						|
    // Do nothing in the base class.
 | 
						|
  }
 | 
						|
 | 
						|
  protected static final boolean classEquals (Class first, Class second)
 | 
						|
  {
 | 
						|
    // Lame function!
 | 
						|
    return (first == second || first.getName().equals(second.getName()));
 | 
						|
  }
 | 
						|
 | 
						|
  public void clear ()
 | 
						|
  {
 | 
						|
    // This is the right thing to do.
 | 
						|
    // The JDK docs are really bad here.
 | 
						|
    throw new UnsupportedOperationException();
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean contains (Object o)
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return children.containsKey(o);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean containsAll (Collection c)
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        Iterator it = c.iterator();
 | 
						|
        while (it.hasNext())
 | 
						|
          if (! children.containsKey(it.next()))
 | 
						|
            return false;
 | 
						|
      }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean containsKey (Object o)
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return children.containsKey(o);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  protected final Object[] copyChildren ()
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return children.keySet().toArray();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  protected BeanContextSupport.BCSChild createBCSChild (Object targetChild, Object peer)
 | 
						|
  {
 | 
						|
    return new BCSChild(targetChild, peer);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Deserializes objects (written by {@link #serialize(ObjectOutputStream,
 | 
						|
   * Collection)}) and adds them to the specified collection.
 | 
						|
   *
 | 
						|
   * @param ois  the input stream (<code>null</code> not permitted).
 | 
						|
   * @param coll  the collection to add the objects to (<code>null</code> not
 | 
						|
   *     permitted).
 | 
						|
   *
 | 
						|
   * @throws ClassNotFoundException
 | 
						|
   * @throws IOException
 | 
						|
   *
 | 
						|
   * @see #serialize(ObjectOutputStream, Collection)
 | 
						|
   */
 | 
						|
  protected final void deserialize (ObjectInputStream ois, Collection coll)
 | 
						|
    throws ClassNotFoundException, IOException
 | 
						|
  {
 | 
						|
    int itemCount = ois.readInt();
 | 
						|
    for (int i = 0; i < itemCount; i++)
 | 
						|
      coll.add(ois.readObject());
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Informs this bean that is should not make
 | 
						|
   * use of the GUI.
 | 
						|
   */
 | 
						|
  public void dontUseGui()
 | 
						|
  {
 | 
						|
    okToUseGui = false;
 | 
						|
  }
 | 
						|
 | 
						|
  protected final void fireChildrenAdded (BeanContextMembershipEvent bcme)
 | 
						|
  {
 | 
						|
    synchronized (bcmListeners)
 | 
						|
      {
 | 
						|
        Iterator it = bcmListeners.iterator();
 | 
						|
        while (it.hasNext())
 | 
						|
          {
 | 
						|
            BeanContextMembershipListener l
 | 
						|
              = (BeanContextMembershipListener) it.next();
 | 
						|
            l.childrenAdded(bcme);
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  protected final void fireChildrenRemoved (BeanContextMembershipEvent bcme)
 | 
						|
  {
 | 
						|
    synchronized (bcmListeners)
 | 
						|
      {
 | 
						|
        Iterator it = bcmListeners.iterator();
 | 
						|
        while (it.hasNext())
 | 
						|
          {
 | 
						|
            BeanContextMembershipListener l
 | 
						|
            = (BeanContextMembershipListener) it.next();
 | 
						|
            l.childrenRemoved(bcme);
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the bean context peer.
 | 
						|
   *
 | 
						|
   * @return The bean context peer.
 | 
						|
   *
 | 
						|
   * @see BeanContextChildSupport#beanContextChildPeer
 | 
						|
   */
 | 
						|
  public BeanContext getBeanContextPeer()
 | 
						|
  {
 | 
						|
    return (BeanContext) beanContextChildPeer;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the {@link BeanContextChild} implementation for the given child.
 | 
						|
   *
 | 
						|
   * @param child  the child (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * @return The bean context child.
 | 
						|
   *
 | 
						|
   * @throws IllegalArgumentException if <code>child</code> implements both
 | 
						|
   *     the {@link BeanContextChild} and {@link BeanContextProxy} interfaces.
 | 
						|
   */
 | 
						|
  protected static final BeanContextChild getChildBeanContextChild(Object child)
 | 
						|
  {
 | 
						|
    if (child == null)
 | 
						|
      return null;
 | 
						|
    if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
 | 
						|
      throw new IllegalArgumentException("Child cannot implement "
 | 
						|
          + "BeanContextChild and BeanContextProxy simultaneously.");
 | 
						|
    if (child instanceof BeanContextChild)
 | 
						|
      return (BeanContextChild) child;
 | 
						|
    if (child instanceof BeanContextProxy)
 | 
						|
      return ((BeanContextProxy) child).getBeanContextProxy();
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>child</code> as an instance of
 | 
						|
   * {@link BeanContextMembershipListener}, or <code>null</code> if
 | 
						|
   * <code>child</code> does not implement that interface.
 | 
						|
   *
 | 
						|
   * @param child  the child (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * @return The child cast to {@link BeanContextMembershipListener}.
 | 
						|
   */
 | 
						|
  protected static final BeanContextMembershipListener
 | 
						|
      getChildBeanContextMembershipListener(Object child)
 | 
						|
  {
 | 
						|
    if (child instanceof BeanContextMembershipListener)
 | 
						|
      return (BeanContextMembershipListener) child;
 | 
						|
    else
 | 
						|
      return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>child</code> as an instance of
 | 
						|
   * {@link PropertyChangeListener}, or <code>null</code> if <code>child</code>
 | 
						|
   * does not implement that interface.
 | 
						|
   *
 | 
						|
   * @param child  the child (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * @return The child cast to {@link PropertyChangeListener}.
 | 
						|
   */
 | 
						|
  protected static final PropertyChangeListener getChildPropertyChangeListener(
 | 
						|
      Object child)
 | 
						|
  {
 | 
						|
    if (child instanceof PropertyChangeListener)
 | 
						|
      return (PropertyChangeListener) child;
 | 
						|
    else
 | 
						|
      return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>child</code> as an instance of {@link Serializable}, or
 | 
						|
   * <code>null</code> if <code>child</code> does not implement that
 | 
						|
   * interface.
 | 
						|
   *
 | 
						|
   * @param child  the child (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * @return The child cast to {@link Serializable}.
 | 
						|
   */
 | 
						|
  protected static final Serializable getChildSerializable(Object child)
 | 
						|
  {
 | 
						|
    if (child instanceof Serializable)
 | 
						|
      return (Serializable) child;
 | 
						|
    else
 | 
						|
      return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>child</code> as an instance of
 | 
						|
   * {@link VetoableChangeListener}, or <code>null</code> if <code>child</code>
 | 
						|
   * does not implement that interface.
 | 
						|
   *
 | 
						|
   * @param child  the child (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * @return The child cast to {@link VetoableChangeListener}.
 | 
						|
   */
 | 
						|
  protected static final VetoableChangeListener getChildVetoableChangeListener(
 | 
						|
      Object child)
 | 
						|
  {
 | 
						|
    if (child instanceof VetoableChangeListener)
 | 
						|
      return (VetoableChangeListener) child;
 | 
						|
    else
 | 
						|
      return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>child</code> as an instance of {@link Visibility}, or
 | 
						|
   * <code>null</code> if <code>child</code> does not implement that interface.
 | 
						|
   *
 | 
						|
   * @param child  the child (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * @return The child cast to {@link Visibility}.
 | 
						|
   */
 | 
						|
  protected static final Visibility getChildVisibility(Object child)
 | 
						|
  {
 | 
						|
    if (child instanceof Visibility)
 | 
						|
      return (Visibility) child;
 | 
						|
    else
 | 
						|
      return null;
 | 
						|
  }
 | 
						|
 | 
						|
  public Locale getLocale ()
 | 
						|
  {
 | 
						|
    return locale;
 | 
						|
  }
 | 
						|
 | 
						|
  public URL getResource (String name, BeanContextChild bcc)
 | 
						|
  {
 | 
						|
    if (! contains(bcc))
 | 
						|
      throw new IllegalArgumentException("argument not a child");
 | 
						|
    ClassLoader loader = bcc.getClass().getClassLoader();
 | 
						|
    return (loader == null ? ClassLoader.getSystemResource(name)
 | 
						|
            : loader.getResource(name));
 | 
						|
  }
 | 
						|
 | 
						|
  public InputStream getResourceAsStream (String name, BeanContextChild bcc)
 | 
						|
  {
 | 
						|
    if (! contains(bcc))
 | 
						|
      throw new IllegalArgumentException("argument not a child");
 | 
						|
    ClassLoader loader = bcc.getClass().getClassLoader();
 | 
						|
    return (loader == null ? ClassLoader.getSystemResourceAsStream(name)
 | 
						|
            : loader.getResourceAsStream(name));
 | 
						|
  }
 | 
						|
 | 
						|
  protected void initialize ()
 | 
						|
  {
 | 
						|
    bcmListeners = new ArrayList();
 | 
						|
    children = new HashMap();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * This is a convenience method for instantiating a bean inside this
 | 
						|
   * context.  It delegates to the appropriate method in
 | 
						|
   * <code>java.beans.Beans</code> using the context's classloader.
 | 
						|
   *
 | 
						|
   * @param beanName the name of the class of bean to instantiate.
 | 
						|
   * @throws IOException if an I/O error occurs in loading the class.
 | 
						|
   * @throws ClassNotFoundException if the class, <code>beanName</code>,
 | 
						|
   *                                can not be found.
 | 
						|
   */
 | 
						|
  public Object instantiateChild (String beanName)
 | 
						|
    throws IOException, ClassNotFoundException
 | 
						|
  {
 | 
						|
    return Beans.instantiate(getClass().getClassLoader(), beanName, this);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns <code>true</code> if the <code>BeanContext</code> is in
 | 
						|
   * design time mode, and <code>false</code> if it is in runtime mode.
 | 
						|
   *
 | 
						|
   * @return A boolean.
 | 
						|
   *
 | 
						|
   * @see #setDesignTime(boolean)
 | 
						|
   */
 | 
						|
  public boolean isDesignTime()
 | 
						|
  {
 | 
						|
    return designTime;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns true if this bean context has no children.
 | 
						|
   *
 | 
						|
   * @return true if there are no children.
 | 
						|
   */
 | 
						|
  public boolean isEmpty ()
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return children.isEmpty();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns true if the bean context is in the process
 | 
						|
   * of being serialized.
 | 
						|
   *
 | 
						|
   * @return true if the context is being serialized.
 | 
						|
   */
 | 
						|
  public boolean isSerializing()
 | 
						|
  {
 | 
						|
    return serializing;
 | 
						|
  }
 | 
						|
 | 
						|
  public Iterator iterator ()
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return children.keySet().iterator();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns false as this bean does not a
 | 
						|
   * GUI for its operation.
 | 
						|
   *
 | 
						|
   * @return false
 | 
						|
   */
 | 
						|
  public boolean needsGui()
 | 
						|
  {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Informs this bean that it is okay to make use of
 | 
						|
   * the GUI.
 | 
						|
   */
 | 
						|
  public void okToUseGui ()
 | 
						|
  {
 | 
						|
    okToUseGui = true;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Subclasses may use this method to catch property changes
 | 
						|
   * arising from the children of this context.  At present,
 | 
						|
   * we just listen for the beans being assigned to a different
 | 
						|
   * context and remove them from here if such an event occurs.
 | 
						|
   *
 | 
						|
   * @param pce the property change event.
 | 
						|
   */
 | 
						|
  public void propertyChange (PropertyChangeEvent pce)
 | 
						|
  {
 | 
						|
    if (pce.getNewValue() != this)
 | 
						|
      remove(pce.getSource(), false);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Deserializes the children using the
 | 
						|
   * {@link #deserialize(ObjectInputStream, Collection} method
 | 
						|
   * and then calls {@link childDeserializedHook(Object, BCSChild)}
 | 
						|
   * for each child deserialized.
 | 
						|
   *
 | 
						|
   * @param ois the input stream.
 | 
						|
   * @throws IOException if an I/O error occurs.
 | 
						|
   */
 | 
						|
  public final void readChildren (ObjectInputStream ois)
 | 
						|
    throws IOException, ClassNotFoundException
 | 
						|
  {
 | 
						|
    List temp = new ArrayList();
 | 
						|
    deserialize(ois, temp);
 | 
						|
    Iterator i = temp.iterator();
 | 
						|
    synchronized (globalHierarchyLock)
 | 
						|
      {
 | 
						|
        synchronized (children)
 | 
						|
          {
 | 
						|
            while (i.hasNext())
 | 
						|
              {
 | 
						|
                BCSChild bcs = (BCSChild) i.next();
 | 
						|
                childDeserializedHook(bcs.getTargetChild(), bcs);
 | 
						|
                children.put(bcs.getTargetChild(), bcs);
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Remove the specified child from the context.  This is
 | 
						|
   * the same as calling <code>remove(Object,boolean)</code>
 | 
						|
   * with a request for the <code>setBeanContext()</code> method
 | 
						|
   * of the child to be called (i.e. the second argument is true).
 | 
						|
   *
 | 
						|
   * @param targetChild the child to remove.
 | 
						|
   */
 | 
						|
  public boolean remove (Object targetChild)
 | 
						|
  {
 | 
						|
    return remove(targetChild, true);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * <p>
 | 
						|
   * Removes a child from the bean context.  A child can be a simple
 | 
						|
   * <code>Object</code>, a <code>BeanContextChild</code>
 | 
						|
   * or another <code>BeanContext</code>.  If the given child is not
 | 
						|
   * a child of this context, this method returns <code>false</code>.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * If the child is a <code>BeanContextChild</code>, or a proxy
 | 
						|
   * for such a child, the <code>setBeanContext()</code> method
 | 
						|
   * is invoked on the child (if specified).  If this operation is vetoed
 | 
						|
   * by the child, via throwing a <code>PropertyVetoException</code>,
 | 
						|
   * then the current completion state of the <code>remove()</code>
 | 
						|
   * operation is rolled back and a <code>IllegalStateException</code>
 | 
						|
   * is thrown.  If the <code>BeanContextChild</code> is successfully
 | 
						|
   * removed, then the context deregisters with its
 | 
						|
   * <code>PropertyChangeListener</code> and
 | 
						|
   * <code>VetoableChangeListener</code> for "beanContext" events.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * A <code>BeanContextMembershipEvent</code> is fired when the
 | 
						|
   * child is successfully removed from the bean context.
 | 
						|
   * </p>
 | 
						|
   * <p>
 | 
						|
   * This method is synchronized over the global hierarchy lock.
 | 
						|
   * </p>
 | 
						|
   *
 | 
						|
   * @param targetChild the child to remove.
 | 
						|
   * @param callChildSetBC true if the <code>setBeanContext()</code>
 | 
						|
   *                       method of the child should be called.
 | 
						|
   * @return false if the child doesn't exist.
 | 
						|
   * @throws IllegalArgumentException if the child is null.
 | 
						|
   * @throws IllegalStateException if the child vetos the setting
 | 
						|
   *                               of its context.
 | 
						|
   */
 | 
						|
  protected boolean remove (Object targetChild, boolean callChildSetBC)
 | 
						|
  {
 | 
						|
    synchronized (globalHierarchyLock)
 | 
						|
      {
 | 
						|
        if (targetChild == null)
 | 
						|
          throw new IllegalArgumentException();
 | 
						|
 | 
						|
        BCSChild child;
 | 
						|
        synchronized (children)
 | 
						|
          {
 | 
						|
            if (!children.containsKey(targetChild)
 | 
						|
                || !validatePendingRemove(targetChild))
 | 
						|
              return false;
 | 
						|
            child = (BCSChild) children.remove(targetChild);
 | 
						|
          }
 | 
						|
        synchronized (targetChild)
 | 
						|
          {
 | 
						|
            BeanContextChild bcChild = null;
 | 
						|
            if (targetChild instanceof BeanContextChild)
 | 
						|
              bcChild = (BeanContextChild) targetChild;
 | 
						|
            if (targetChild instanceof BeanContextProxy)
 | 
						|
              bcChild = ((BeanContextProxy) targetChild).getBeanContextProxy();
 | 
						|
            if (bcChild != null)
 | 
						|
              try
 | 
						|
                {
 | 
						|
                  if (callChildSetBC)
 | 
						|
                    bcChild.setBeanContext(null);
 | 
						|
                  bcChild.removeVetoableChangeListener("beanContext", this);
 | 
						|
                  bcChild.removePropertyChangeListener("beanContext", this);
 | 
						|
                }
 | 
						|
              catch (PropertyVetoException e)
 | 
						|
                {
 | 
						|
                  synchronized (children)
 | 
						|
                    {
 | 
						|
                      children.put(targetChild, child);
 | 
						|
                    }
 | 
						|
                  throw new IllegalStateException("The child refused to " +
 | 
						|
                                                  "disassociate itself with " +
 | 
						|
                                                  "this context.", e);
 | 
						|
                }
 | 
						|
            childJustRemovedHook(targetChild, child);
 | 
						|
          }
 | 
						|
        fireChildrenRemoved(new BeanContextMembershipEvent(this,
 | 
						|
                                                         new Object[]{ targetChild }));
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean removeAll (Collection c)
 | 
						|
  {
 | 
						|
    // Intentionally throws an exception.
 | 
						|
    throw new UnsupportedOperationException();
 | 
						|
  }
 | 
						|
 | 
						|
  public void removeBeanContextMembershipListener (BeanContextMembershipListener bcml)
 | 
						|
  {
 | 
						|
    synchronized (bcmListeners)
 | 
						|
      {
 | 
						|
        bcmListeners.remove(bcml);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public boolean retainAll (Collection c)
 | 
						|
  {
 | 
						|
    // Intentionally throws an exception.
 | 
						|
    throw new UnsupportedOperationException();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Writes the items in the collection to the specified output stream.  Items
 | 
						|
   * in the collection that are not instances of {@link Serializable}
 | 
						|
   * (this includes <code>null</code>) are simply ignored.
 | 
						|
   *
 | 
						|
   * @param oos  the output stream (<code>null</code> not permitted).
 | 
						|
   * @param coll  the collection (<code>null</code> not permitted).
 | 
						|
   *
 | 
						|
   * @throws IOException
 | 
						|
   *
 | 
						|
   * @see #deserialize(ObjectInputStream, Collection)
 | 
						|
   */
 | 
						|
  protected final void serialize(ObjectOutputStream oos, Collection coll)
 | 
						|
    throws IOException
 | 
						|
  {
 | 
						|
    Object[] items = coll.toArray();
 | 
						|
    int itemCount = 0;
 | 
						|
    for (int i = 0; i < items.length; i++)
 | 
						|
      {
 | 
						|
        if (items[i] instanceof Serializable)
 | 
						|
          itemCount++;
 | 
						|
      }
 | 
						|
    oos.writeInt(itemCount);
 | 
						|
    for (int i = 0; i < items.length; i++)
 | 
						|
      {
 | 
						|
        if (items[i] instanceof Serializable)
 | 
						|
          oos.writeObject(items[i]);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Sets the flag that indicates whether or not the
 | 
						|
   * <code>BeanContext</code> is in design mode.  If the flag changes
 | 
						|
   * value, a {@link PropertyChangeEvent} (with the property name 'designMode')
 | 
						|
   * is sent to registered listeners.  Note that the property name used here
 | 
						|
   * does NOT match the specification in the {@link DesignMode} interface, we
 | 
						|
   * match the reference implementation instead - see bug parade entry 4295174.
 | 
						|
   *
 | 
						|
   * @param dtime  the new value for the flag.
 | 
						|
   *
 | 
						|
   * @see #isDesignTime()
 | 
						|
   */
 | 
						|
  public void setDesignTime(boolean dtime)
 | 
						|
  {
 | 
						|
    boolean save = designTime;
 | 
						|
    designTime = dtime;
 | 
						|
    // note that we use the same property name as Sun's implementation,
 | 
						|
    // even though this is a known bug: see bug parade entry 4295174
 | 
						|
    firePropertyChange("designMode", Boolean.valueOf(save),
 | 
						|
                       Boolean.valueOf(dtime));
 | 
						|
  }
 | 
						|
 | 
						|
  public void setLocale (Locale newLocale)
 | 
						|
    throws PropertyVetoException
 | 
						|
  {
 | 
						|
    if (newLocale == null || locale == newLocale)
 | 
						|
      return;
 | 
						|
    fireVetoableChange("locale", locale, newLocale);
 | 
						|
    Locale oldLocale = locale;
 | 
						|
    locale = newLocale;
 | 
						|
    firePropertyChange("locale", oldLocale, newLocale);
 | 
						|
  }
 | 
						|
 | 
						|
  public int size ()
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return children.size();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns an array containing the children of this <code>BeanContext</code>.
 | 
						|
   *
 | 
						|
   * @return An array containing the children.
 | 
						|
   */
 | 
						|
  public Object[] toArray()
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return children.keySet().toArray();
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Populates, then returns, the supplied array with the children of this
 | 
						|
   * <code>BeanContext</code>.  If the array is too short to hold the
 | 
						|
   * children, a new array is allocated and returned.  If the array is too
 | 
						|
   * long, it is padded with <code>null</code> items at the end.
 | 
						|
   *
 | 
						|
   * @param array  an array to populate (<code>null</code> not permitted).
 | 
						|
   */
 | 
						|
  public Object[] toArray(Object[] array)
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        return children.keySet().toArray(array);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  protected boolean validatePendingAdd (Object targetChild)
 | 
						|
  {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  protected boolean validatePendingRemove (Object targetChild)
 | 
						|
  {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Subclasses may use this method to veto changes arising
 | 
						|
   * from the children of this context.
 | 
						|
   *
 | 
						|
   * @param pce the vetoable property change event fired.
 | 
						|
   */
 | 
						|
  public void vetoableChange (PropertyChangeEvent pce)
 | 
						|
    throws PropertyVetoException
 | 
						|
  {
 | 
						|
    /* Purposefully left empty */
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Serializes the children using the
 | 
						|
   * {@link #serialize(ObjectOutputStream, Collection} method.
 | 
						|
   *
 | 
						|
   * @param oos the output stream.
 | 
						|
   * @throws IOException if an I/O error occurs.
 | 
						|
   */
 | 
						|
  public final void writeChildren (ObjectOutputStream oos)
 | 
						|
    throws IOException
 | 
						|
  {
 | 
						|
    synchronized (children)
 | 
						|
      {
 | 
						|
        serialize(oos, children.values());
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
}
 |