summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/beans/beancontext/BeanContextSupport.java
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/beans/beancontext/BeanContextSupport.java
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/java/beans/beancontext/BeanContextSupport.java')
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextSupport.java1079
1 files changed, 1079 insertions, 0 deletions
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextSupport.java b/libjava/classpath/java/beans/beancontext/BeanContextSupport.java
new file mode 100644
index 000000000..fdae387d4
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextSupport.java
@@ -0,0 +1,1079 @@
+/* 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());
+ }
+ }
+
+}