0N/A/*
2362N/A * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage java.beans.beancontext;
0N/A
0N/Aimport java.awt.Component;
0N/Aimport java.awt.Container;
0N/A
0N/Aimport java.beans.Beans;
0N/Aimport java.beans.AppletInitializer;
0N/A
0N/Aimport java.beans.DesignMode;
0N/A
0N/Aimport java.beans.PropertyChangeEvent;
0N/Aimport java.beans.PropertyChangeListener;
0N/Aimport java.beans.PropertyChangeSupport;
0N/A
0N/Aimport java.beans.VetoableChangeListener;
0N/Aimport java.beans.VetoableChangeSupport;
0N/Aimport java.beans.PropertyVetoException;
0N/A
0N/Aimport java.beans.Visibility;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.io.InputStream;
0N/Aimport java.io.ObjectInputStream;
0N/Aimport java.io.ObjectOutputStream;
0N/Aimport java.io.Serializable;
0N/A
0N/Aimport java.net.URL;
0N/A
0N/Aimport java.util.ArrayList;
0N/Aimport java.util.Collection;
0N/Aimport java.util.HashMap;
0N/Aimport java.util.Iterator;
0N/Aimport java.util.Locale;
0N/Aimport java.util.Map;
0N/A
0N/A
0N/A/**
0N/A * This helper class provides a utility implementation of the
0N/A * java.beans.beancontext.BeanContext interface.
0N/A * </p>
0N/A * <p>
0N/A * Since this class directly implements the BeanContext interface, the class
0N/A * can, and is intended to be used either by subclassing this implementation,
0N/A * or via ad-hoc delegation of an instance of this class from another.
0N/A * </p>
0N/A *
0N/A * @author Laurence P. G. Cable
0N/A * @since 1.2
0N/A */
0N/Apublic class BeanContextSupport extends BeanContextChildSupport
0N/A implements BeanContext,
0N/A Serializable,
0N/A PropertyChangeListener,
0N/A VetoableChangeListener {
0N/A
0N/A // Fix for bug 4282900 to pass JCK regression test
0N/A static final long serialVersionUID = -4879613978649577204L;
0N/A
0N/A /**
0N/A *
0N/A * Construct a BeanContextSupport instance
0N/A *
0N/A *
0N/A * @param peer The peer <tt>BeanContext</tt> we are
0N/A * supplying an implementation for,
0N/A * or <tt>null</tt>
0N/A * if this object is its own peer
0N/A * @param lcle The current Locale for this BeanContext. If
0N/A * <tt>lcle</tt> is <tt>null</tt>, the default locale
0N/A * is assigned to the <tt>BeanContext</tt> instance.
0N/A * @param dTime The initial state,
0N/A * <tt>true</tt> if in design mode,
0N/A * <tt>false</tt> if runtime.
0N/A * @param visible The initial visibility.
0N/A * @see java.util.Locale#getDefault()
0N/A * @see java.util.Locale#setDefault(java.util.Locale)
0N/A */
0N/A public BeanContextSupport(BeanContext peer, Locale lcle, boolean dTime, boolean visible) {
0N/A super(peer);
0N/A
0N/A locale = lcle != null ? lcle : Locale.getDefault();
0N/A designTime = dTime;
0N/A okToUseGui = visible;
0N/A
0N/A initialize();
0N/A }
0N/A
0N/A /**
0N/A * Create an instance using the specified Locale and design mode.
0N/A *
0N/A * @param peer The peer <tt>BeanContext</tt> we
0N/A * are supplying an implementation for,
0N/A * or <tt>null</tt> if this object is its own peer
0N/A * @param lcle The current Locale for this <tt>BeanContext</tt>. If
0N/A * <tt>lcle</tt> is <tt>null</tt>, the default locale
0N/A * is assigned to the <tt>BeanContext</tt> instance.
0N/A * @param dtime The initial state, <tt>true</tt>
0N/A * if in design mode,
0N/A * <tt>false</tt> if runtime.
0N/A * @see java.util.Locale#getDefault()
0N/A * @see java.util.Locale#setDefault(java.util.Locale)
0N/A */
0N/A public BeanContextSupport(BeanContext peer, Locale lcle, boolean dtime) {
0N/A this (peer, lcle, dtime, true);
0N/A }
0N/A
0N/A /**
0N/A * Create an instance using the specified locale
0N/A *
0N/A * @param peer The peer BeanContext we are
0N/A * supplying an implementation for,
0N/A * or <tt>null</tt> if this object
0N/A * is its own peer
0N/A * @param lcle The current Locale for this
0N/A * <tt>BeanContext</tt>. If
0N/A * <tt>lcle</tt> is <tt>null</tt>,
0N/A * the default locale
0N/A * is assigned to the <tt>BeanContext</tt>
0N/A * instance.
0N/A * @see java.util.Locale#getDefault()
0N/A * @see java.util.Locale#setDefault(java.util.Locale)
0N/A */
0N/A public BeanContextSupport(BeanContext peer, Locale lcle) {
0N/A this (peer, lcle, false, true);
0N/A }
0N/A
0N/A /**
0N/A * Create an instance using with a default locale
0N/A *
0N/A * @param peer The peer <tt>BeanContext</tt> we are
0N/A * supplying an implementation for,
0N/A * or <tt>null</tt> if this object
0N/A * is its own peer
0N/A */
0N/A public BeanContextSupport(BeanContext peer) {
0N/A this (peer, null, false, true);
0N/A }
0N/A
0N/A /**
0N/A * Create an instance that is not a delegate of another object
0N/A */
0N/A
0N/A public BeanContextSupport() {
0N/A this (null, null, false, true);
0N/A }
0N/A
0N/A /**
0N/A * Gets the instance of <tt>BeanContext</tt> that
0N/A * this object is providing the implementation for.
0N/A * @return the BeanContext instance
0N/A */
0N/A public BeanContext getBeanContextPeer() { return (BeanContext)getBeanContextChildPeer(); }
0N/A
0N/A /**
0N/A * <p>
0N/A * The instantiateChild method is a convenience hook
0N/A * in BeanContext to simplify
0N/A * the task of instantiating a Bean, nested,
0N/A * into a <tt>BeanContext</tt>.
0N/A * </p>
0N/A * <p>
0N/A * The semantics of the beanName parameter are defined by java.beans.Beans.instantate.
0N/A * </p>
0N/A *
0N/A * @param beanName the name of the Bean to instantiate within this BeanContext
0N/A * @throws IOException if there is an I/O error when the bean is being deserialized
0N/A * @throws ClassNotFoundException if the class
0N/A * identified by the beanName parameter is not found
0N/A * @return the new object
0N/A */
0N/A public Object instantiateChild(String beanName)
0N/A throws IOException, ClassNotFoundException {
0N/A BeanContext bc = getBeanContextPeer();
0N/A
0N/A return Beans.instantiate(bc.getClass().getClassLoader(), beanName, bc);
0N/A }
0N/A
0N/A /**
0N/A * Gets the number of children currently nested in
0N/A * this BeanContext.
0N/A *
0N/A * @return number of children
0N/A */
0N/A public int size() {
0N/A synchronized(children) {
0N/A return children.size();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Reports whether or not this
0N/A * <tt>BeanContext</tt> is empty.
0N/A * A <tt>BeanContext</tt> is considered
0N/A * empty when it contains zero
0N/A * nested children.
0N/A * @return if there are not children
0N/A */
0N/A public boolean isEmpty() {
0N/A synchronized(children) {
0N/A return children.isEmpty();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Determines whether or not the specified object
0N/A * is currently a child of this <tt>BeanContext</tt>.
0N/A * @param o the Object in question
0N/A * @return if this object is a child
0N/A */
0N/A public boolean contains(Object o) {
0N/A synchronized(children) {
0N/A return children.containsKey(o);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Determines whether or not the specified object
0N/A * is currently a child of this <tt>BeanContext</tt>.
0N/A * @param o the Object in question
0N/A * @return if this object is a child
0N/A */
0N/A public boolean containsKey(Object o) {
0N/A synchronized(children) {
0N/A return children.containsKey(o);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets all JavaBean or <tt>BeanContext</tt> instances
0N/A * currently nested in this <tt>BeanContext</tt>.
0N/A * @return an <tt>Iterator</tt> of the nested children
0N/A */
0N/A public Iterator iterator() {
0N/A synchronized(children) {
0N/A return new BCSIterator(children.keySet().iterator());
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets all JavaBean or <tt>BeanContext</tt>
0N/A * instances currently nested in this BeanContext.
0N/A */
0N/A public Object[] toArray() {
0N/A synchronized(children) {
0N/A return children.keySet().toArray();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets an array containing all children of
0N/A * this <tt>BeanContext</tt> that match
0N/A * the types contained in arry.
0N/A * @param arry The array of object
0N/A * types that are of interest.
0N/A * @return an array of children
0N/A */
0N/A public Object[] toArray(Object[] arry) {
0N/A synchronized(children) {
0N/A return children.keySet().toArray(arry);
0N/A }
0N/A }
0N/A
0N/A
0N/A /************************************************************************/
0N/A
0N/A /**
0N/A * protected final subclass that encapsulates an iterator but implements
0N/A * a noop remove() method.
0N/A */
0N/A
0N/A protected static final class BCSIterator implements Iterator {
0N/A BCSIterator(Iterator i) { super(); src = i; }
0N/A
0N/A public boolean hasNext() { return src.hasNext(); }
0N/A public Object next() { return src.next(); }
0N/A public void remove() { /* do nothing */ }
0N/A
0N/A private Iterator src;
0N/A }
0N/A
0N/A /************************************************************************/
0N/A
0N/A /*
0N/A * protected nested class containing per child information, an instance
0N/A * of which is associated with each child in the "children" hashtable.
0N/A * subclasses can extend this class to include their own per-child state.
0N/A *
0N/A * Note that this 'value' is serialized with the corresponding child 'key'
0N/A * when the BeanContextSupport is serialized.
0N/A */
0N/A
0N/A protected class BCSChild implements Serializable {
0N/A
0N/A private static final long serialVersionUID = -5815286101609939109L;
0N/A
0N/A BCSChild(Object bcc, Object peer) {
0N/A super();
0N/A
0N/A child = bcc;
0N/A proxyPeer = peer;
0N/A }
0N/A
0N/A Object getChild() { return child; }
0N/A
0N/A void setRemovePending(boolean v) { removePending = v; }
0N/A
0N/A boolean isRemovePending() { return removePending; }
0N/A
0N/A boolean isProxyPeer() { return proxyPeer != null; }
0N/A
0N/A Object getProxyPeer() { return proxyPeer; }
0N/A /*
0N/A * fields
0N/A */
0N/A
0N/A
0N/A private Object child;
0N/A private Object proxyPeer;
0N/A
0N/A private transient boolean removePending;
0N/A }
0N/A
0N/A /**
0N/A * <p>
0N/A * Subclasses can override this method to insert their own subclass
0N/A * of Child without having to override add() or the other Collection
0N/A * methods that add children to the set.
0N/A * </p>
0N/A *
0N/A * @param targetChild the child to create the Child on behalf of
0N/A * @param peer the peer if the tragetChild and the peer are related by an implementation of BeanContextProxy
0N/A */
0N/A
0N/A protected BCSChild createBCSChild(Object targetChild, Object peer) {
0N/A return new BCSChild(targetChild, peer);
0N/A }
0N/A
0N/A /************************************************************************/
0N/A
0N/A /**
0N/A * Adds/nests a child within this <tt>BeanContext</tt>.
0N/A * <p>
0N/A * Invoked as a side effect of java.beans.Beans.instantiate().
0N/A * If the child object is not valid for adding then this method
0N/A * throws an IllegalStateException.
0N/A * </p>
0N/A *
0N/A *
0N/A * @param targetChild The child objects to nest
0N/A * within this <tt>BeanContext</tt>
0N/A * @return true if the child was added successfully.
0N/A * @see #validatePendingAdd
0N/A */
0N/A public boolean add(Object targetChild) {
0N/A
0N/A if (targetChild == null) throw new IllegalArgumentException();
0N/A
0N/A // The specification requires that we do nothing if the child
0N/A // is already nested herein.
0N/A
0N/A if (children.containsKey(targetChild)) return false; // test before locking
0N/A
0N/A synchronized(BeanContext.globalHierarchyLock) {
0N/A if (children.containsKey(targetChild)) return false; // check again
0N/A
0N/A if (!validatePendingAdd(targetChild)) {
0N/A throw new IllegalStateException();
0N/A }
0N/A
0N/A
0N/A // The specification requires that we invoke setBeanContext() on the
0N/A // newly added child if it implements the java.beans.beancontext.BeanContextChild interface
0N/A
0N/A BeanContextChild cbcc = getChildBeanContextChild(targetChild);
0N/A BeanContextChild bccp = null;
0N/A
0N/A synchronized(targetChild) {
0N/A
0N/A if (targetChild instanceof BeanContextProxy) {
0N/A bccp = ((BeanContextProxy)targetChild).getBeanContextProxy();
0N/A
0N/A if (bccp == null) throw new NullPointerException("BeanContextPeer.getBeanContextProxy()");
0N/A }
0N/A
0N/A BCSChild bcsc = createBCSChild(targetChild, bccp);
0N/A BCSChild pbcsc = null;
0N/A
0N/A synchronized (children) {
0N/A children.put(targetChild, bcsc);
0N/A
0N/A if (bccp != null) children.put(bccp, pbcsc = createBCSChild(bccp, targetChild));
0N/A }
0N/A
0N/A if (cbcc != null) synchronized(cbcc) {
0N/A try {
0N/A cbcc.setBeanContext(getBeanContextPeer());
0N/A } catch (PropertyVetoException pve) {
0N/A
0N/A synchronized (children) {
0N/A children.remove(targetChild);
0N/A
0N/A if (bccp != null) children.remove(bccp);
0N/A }
0N/A
0N/A throw new IllegalStateException();
0N/A }
0N/A
0N/A cbcc.addPropertyChangeListener("beanContext", childPCL);
0N/A cbcc.addVetoableChangeListener("beanContext", childVCL);
0N/A }
0N/A
0N/A Visibility v = getChildVisibility(targetChild);
0N/A
0N/A if (v != null) {
0N/A if (okToUseGui)
0N/A v.okToUseGui();
0N/A else
0N/A v.dontUseGui();
0N/A }
0N/A
0N/A if (getChildSerializable(targetChild) != null) serializable++;
0N/A
0N/A childJustAddedHook(targetChild, bcsc);
0N/A
0N/A if (bccp != null) {
0N/A v = getChildVisibility(bccp);
0N/A
0N/A if (v != null) {
0N/A if (okToUseGui)
0N/A v.okToUseGui();
0N/A else
0N/A v.dontUseGui();
0N/A }
0N/A
0N/A if (getChildSerializable(bccp) != null) serializable++;
0N/A
0N/A childJustAddedHook(bccp, pbcsc);
0N/A }
0N/A
0N/A
0N/A }
0N/A
0N/A // The specification requires that we fire a notification of the change
0N/A
0N/A fireChildrenAdded(new BeanContextMembershipEvent(getBeanContextPeer(), bccp == null ? new Object[] { targetChild } : new Object[] { targetChild, bccp } ));
0N/A
0N/A }
0N/A
0N/A return true;
0N/A }
0N/A
0N/A /**
0N/A * Removes a child from this BeanContext. If the child object is not
0N/A * for adding then this method throws an IllegalStateException.
0N/A * @param targetChild The child objects to remove
0N/A * @see #validatePendingRemove
0N/A */
0N/A public boolean remove(Object targetChild) {
0N/A return remove(targetChild, true);
0N/A }
0N/A
0N/A /**
0N/A * internal remove used when removal caused by
0N/A * unexpected <tt>setBeanContext</tt> or
0N/A * by <tt>remove()</tt> invocation.
0N/A * @param targetChild the JavaBean, BeanContext, or Object to be removed
0N/A * @param callChildSetBC used to indicate that
0N/A * the child should be notified that it is no
0N/A * longer nested in this <tt>BeanContext</tt>.
0N/A */
0N/A protected boolean remove(Object targetChild, boolean callChildSetBC) {
0N/A
0N/A if (targetChild == null) throw new IllegalArgumentException();
0N/A
0N/A synchronized(BeanContext.globalHierarchyLock) {
0N/A if (!containsKey(targetChild)) return false;
0N/A
0N/A if (!validatePendingRemove(targetChild)) {
0N/A throw new IllegalStateException();
0N/A }
0N/A
0N/A BCSChild bcsc = (BCSChild)children.get(targetChild);
0N/A BCSChild pbcsc = null;
0N/A Object peer = null;
0N/A
0N/A // we are required to notify the child that it is no longer nested here if
0N/A // it implements java.beans.beancontext.BeanContextChild
0N/A
0N/A synchronized(targetChild) {
0N/A if (callChildSetBC) {
0N/A BeanContextChild cbcc = getChildBeanContextChild(targetChild);
0N/A if (cbcc != null) synchronized(cbcc) {
0N/A cbcc.removePropertyChangeListener("beanContext", childPCL);
0N/A cbcc.removeVetoableChangeListener("beanContext", childVCL);
0N/A
0N/A try {
0N/A cbcc.setBeanContext(null);
0N/A } catch (PropertyVetoException pve1) {
0N/A cbcc.addPropertyChangeListener("beanContext", childPCL);
0N/A cbcc.addVetoableChangeListener("beanContext", childVCL);
0N/A throw new IllegalStateException();
0N/A }
0N/A
0N/A }
0N/A }
0N/A
0N/A synchronized (children) {
0N/A children.remove(targetChild);
0N/A
0N/A if (bcsc.isProxyPeer()) {
0N/A pbcsc = (BCSChild)children.get(peer = bcsc.getProxyPeer());
0N/A children.remove(peer);
0N/A }
0N/A }
0N/A
0N/A if (getChildSerializable(targetChild) != null) serializable--;
0N/A
0N/A childJustRemovedHook(targetChild, bcsc);
0N/A
0N/A if (peer != null) {
0N/A if (getChildSerializable(peer) != null) serializable--;
0N/A
0N/A childJustRemovedHook(peer, pbcsc);
0N/A }
0N/A }
0N/A
0N/A fireChildrenRemoved(new BeanContextMembershipEvent(getBeanContextPeer(), peer == null ? new Object[] { targetChild } : new Object[] { targetChild, peer } ));
0N/A
0N/A }
0N/A
0N/A return true;
0N/A }
0N/A
0N/A /**
0N/A * Tests to see if all objects in the
0N/A * specified <tt>Collection</tt> are children of
0N/A * this <tt>BeanContext</tt>.
0N/A * @param c the specified <tt>Collection</tt>
0N/A *
0N/A * @return <tt>true</tt> if all objects
0N/A * in the collection are children of
0N/A * this <tt>BeanContext</tt>, false if not.
0N/A */
0N/A public boolean containsAll(Collection c) {
0N/A synchronized(children) {
0N/A Iterator i = c.iterator();
0N/A while (i.hasNext())
0N/A if(!contains(i.next()))
0N/A return false;
0N/A
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * add Collection to set of Children (Unsupported)
0N/A * implementations must synchronized on the hierarchy lock and "children" protected field
0N/A * @throws UnsupportedOperationException
0N/A */
0N/A public boolean addAll(Collection c) {
0N/A throw new UnsupportedOperationException();
0N/A }
0N/A
0N/A /**
0N/A * remove all specified children (Unsupported)
0N/A * implementations must synchronized on the hierarchy lock and "children" protected field
0N/A * @throws UnsupportedOperationException
0N/A */
0N/A public boolean removeAll(Collection c) {
0N/A throw new UnsupportedOperationException();
0N/A }
0N/A
0N/A
0N/A /**
0N/A * retain only specified children (Unsupported)
0N/A * implementations must synchronized on the hierarchy lock and "children" protected field
0N/A * @throws UnsupportedOperationException
0N/A */
0N/A public boolean retainAll(Collection c) {
0N/A throw new UnsupportedOperationException();
0N/A }
0N/A
0N/A /**
0N/A * clear the children (Unsupported)
0N/A * implementations must synchronized on the hierarchy lock and "children" protected field
0N/A * @throws UnsupportedOperationException
0N/A */
0N/A public void clear() {
0N/A throw new UnsupportedOperationException();
0N/A }
0N/A
0N/A /**
0N/A * Adds a BeanContextMembershipListener
0N/A *
0N/A * @param bcml the BeanContextMembershipListener to add
0N/A * @throws NullPointerException
0N/A */
0N/A
0N/A public void addBeanContextMembershipListener(BeanContextMembershipListener bcml) {
0N/A if (bcml == null) throw new NullPointerException("listener");
0N/A
0N/A synchronized(bcmListeners) {
0N/A if (bcmListeners.contains(bcml))
0N/A return;
0N/A else
0N/A bcmListeners.add(bcml);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Removes a BeanContextMembershipListener
0N/A *
0N/A * @param bcml the BeanContextMembershipListener to remove
0N/A * @throws NullPointerException
0N/A */
0N/A
0N/A public void removeBeanContextMembershipListener(BeanContextMembershipListener bcml) {
0N/A if (bcml == null) throw new NullPointerException("listener");
0N/A
0N/A synchronized(bcmListeners) {
0N/A if (!bcmListeners.contains(bcml))
0N/A return;
0N/A else
0N/A bcmListeners.remove(bcml);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * @param name the name of the resource requested.
0N/A * @param bcc the child object making the request.
0N/A *
0N/A * @return the requested resource as an InputStream
0N/A * @throws NullPointerException
0N/A */
0N/A
0N/A public InputStream getResourceAsStream(String name, BeanContextChild bcc) {
0N/A if (name == null) throw new NullPointerException("name");
0N/A if (bcc == null) throw new NullPointerException("bcc");
0N/A
0N/A if (containsKey(bcc)) {
0N/A ClassLoader cl = bcc.getClass().getClassLoader();
0N/A
0N/A return cl != null ? cl.getResourceAsStream(name)
0N/A : ClassLoader.getSystemResourceAsStream(name);
0N/A } else throw new IllegalArgumentException("Not a valid child");
0N/A }
0N/A
0N/A /**
0N/A * @param name the name of the resource requested.
0N/A * @param bcc the child object making the request.
0N/A *
0N/A * @return the requested resource as an InputStream
0N/A */
0N/A
0N/A public URL getResource(String name, BeanContextChild bcc) {
0N/A if (name == null) throw new NullPointerException("name");
0N/A if (bcc == null) throw new NullPointerException("bcc");
0N/A
0N/A if (containsKey(bcc)) {
0N/A ClassLoader cl = bcc.getClass().getClassLoader();
0N/A
0N/A return cl != null ? cl.getResource(name)
0N/A : ClassLoader.getSystemResource(name);
0N/A } else throw new IllegalArgumentException("Not a valid child");
0N/A }
0N/A
0N/A /**
0N/A * Sets the new design time value for this <tt>BeanContext</tt>.
0N/A * @param dTime the new designTime value
0N/A */
0N/A public synchronized void setDesignTime(boolean dTime) {
0N/A if (designTime != dTime) {
0N/A designTime = dTime;
0N/A
0N/A firePropertyChange("designMode", Boolean.valueOf(!dTime), Boolean.valueOf(dTime));
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Reports whether or not this object is in
0N/A * currently in design time mode.
0N/A * @return <tt>true</tt> if in design time mode,
0N/A * <tt>false</tt> if not
0N/A */
0N/A public synchronized boolean isDesignTime() { return designTime; }
0N/A
0N/A /**
0N/A * Sets the locale of this BeanContext.
0N/A * @param newLocale the new locale. This method call will have
0N/A * no effect if newLocale is <CODE>null</CODE>.
0N/A * @throws PropertyVetoException if the new value is rejected
0N/A */
0N/A public synchronized void setLocale(Locale newLocale) throws PropertyVetoException {
0N/A
0N/A if ((locale != null && !locale.equals(newLocale)) && newLocale != null) {
0N/A Locale old = locale;
0N/A
0N/A fireVetoableChange("locale", old, newLocale); // throws
0N/A
0N/A locale = newLocale;
0N/A
0N/A firePropertyChange("locale", old, newLocale);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the locale for this <tt>BeanContext</tt>.
0N/A *
0N/A * @return the current Locale of the <tt>BeanContext</tt>
0N/A */
0N/A public synchronized Locale getLocale() { return locale; }
0N/A
0N/A /**
0N/A * <p>
0N/A * This method is typically called from the environment in order to determine
0N/A * if the implementor "needs" a GUI.
0N/A * </p>
0N/A * <p>
0N/A * The algorithm used herein tests the BeanContextPeer, and its current children
0N/A * to determine if they are either Containers, Components, or if they implement
0N/A * Visibility and return needsGui() == true.
0N/A * </p>
0N/A * @return <tt>true</tt> if the implementor needs a GUI
0N/A */
0N/A public synchronized boolean needsGui() {
0N/A BeanContext bc = getBeanContextPeer();
0N/A
0N/A if (bc != this) {
0N/A if (bc instanceof Visibility) return ((Visibility)bc).needsGui();
0N/A
0N/A if (bc instanceof Container || bc instanceof Component)
0N/A return true;
0N/A }
0N/A
0N/A synchronized(children) {
0N/A for (Iterator i = children.keySet().iterator(); i.hasNext();) {
0N/A Object c = i.next();
0N/A
0N/A try {
0N/A return ((Visibility)c).needsGui();
0N/A } catch (ClassCastException cce) {
0N/A // do nothing ...
0N/A }
0N/A
0N/A if (c instanceof Container || c instanceof Component)
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * notify this instance that it may no longer render a GUI.
0N/A */
0N/A
0N/A public synchronized void dontUseGui() {
0N/A if (okToUseGui) {
0N/A okToUseGui = false;
0N/A
0N/A // lets also tell the Children that can that they may not use their GUI's
0N/A synchronized(children) {
0N/A for (Iterator i = children.keySet().iterator(); i.hasNext();) {
0N/A Visibility v = getChildVisibility(i.next());
0N/A
0N/A if (v != null) v.dontUseGui();
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Notify this instance that it may now render a GUI
0N/A */
0N/A
0N/A public synchronized void okToUseGui() {
0N/A if (!okToUseGui) {
0N/A okToUseGui = true;
0N/A
0N/A // lets also tell the Children that can that they may use their GUI's
0N/A synchronized(children) {
0N/A for (Iterator i = children.keySet().iterator(); i.hasNext();) {
0N/A Visibility v = getChildVisibility(i.next());
0N/A
0N/A if (v != null) v.okToUseGui();
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Used to determine if the <tt>BeanContext</tt>
0N/A * child is avoiding using its GUI.
0N/A * @return is this instance avoiding using its GUI?
0N/A * @see Visibility
0N/A */
0N/A public boolean avoidingGui() {
0N/A return !okToUseGui && needsGui();
0N/A }
0N/A
0N/A /**
0N/A * Is this <tt>BeanContext</tt> in the
0N/A * process of being serialized?
0N/A * @return if this <tt>BeanContext</tt> is
0N/A * currently being serialized
0N/A */
0N/A public boolean isSerializing() { return serializing; }
0N/A
0N/A /**
0N/A * Returns an iterator of all children
0N/A * of this <tt>BeanContext</tt>.
0N/A * @return an iterator for all the current BCSChild values
0N/A */
0N/A protected Iterator bcsChildren() { synchronized(children) { return children.values().iterator(); } }
0N/A
0N/A /**
0N/A * called by writeObject after defaultWriteObject() but prior to
0N/A * serialization of currently serializable children.
0N/A *
0N/A * This method may be overridden by subclasses to perform custom
0N/A * serialization of their state prior to this superclass serializing
0N/A * the children.
0N/A *
0N/A * This method should not however be used by subclasses to replace their
0N/A * own implementation (if any) of writeObject().
0N/A */
0N/A
0N/A protected void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
0N/A }
0N/A
0N/A /**
0N/A * called by readObject after defaultReadObject() but prior to
0N/A * deserialization of any children.
0N/A *
0N/A * This method may be overridden by subclasses to perform custom
0N/A * deserialization of their state prior to this superclass deserializing
0N/A * the children.
0N/A *
0N/A * This method should not however be used by subclasses to replace their
0N/A * own implementation (if any) of readObject().
0N/A */
0N/A
0N/A protected void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
0N/A }
0N/A
0N/A /**
0N/A * Called by readObject with the newly deserialized child and BCSChild.
0N/A * @param child the newly deserialized child
0N/A * @param bcsc the newly deserialized BCSChild
0N/A */
0N/A protected void childDeserializedHook(Object child, BCSChild bcsc) {
0N/A synchronized(children) {
0N/A children.put(child, bcsc);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Used by writeObject to serialize a Collection.
0N/A * @param oos the <tt>ObjectOutputStream</tt>
0N/A * to use during serialization
0N/A * @param coll the <tt>Collection</tt> to serialize
0N/A * @throws IOException if serialization failed
0N/A */
0N/A protected final void serialize(ObjectOutputStream oos, Collection coll) throws IOException {
0N/A int count = 0;
0N/A Object[] objects = coll.toArray();
0N/A
0N/A for (int i = 0; i < objects.length; i++) {
0N/A if (objects[i] instanceof Serializable)
0N/A count++;
0N/A else
0N/A objects[i] = null;
0N/A }
0N/A
0N/A oos.writeInt(count); // number of subsequent objects
0N/A
0N/A for (int i = 0; count > 0; i++) {
0N/A Object o = objects[i];
0N/A
0N/A if (o != null) {
0N/A oos.writeObject(o);
0N/A count--;
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * used by readObject to deserialize a collection.
0N/A * @param ois the ObjectInputStream to use
0N/A * @param coll the Collection
0N/A */
0N/A protected final void deserialize(ObjectInputStream ois, Collection coll) throws IOException, ClassNotFoundException {
0N/A int count = 0;
0N/A
0N/A count = ois.readInt();
0N/A
0N/A while (count-- > 0) {
0N/A coll.add(ois.readObject());
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Used to serialize all children of
0N/A * this <tt>BeanContext</tt>.
0N/A * @param oos the <tt>ObjectOutputStream</tt>
0N/A * to use during serialization
0N/A * @throws IOException if serialization failed
0N/A */
0N/A public final void writeChildren(ObjectOutputStream oos) throws IOException {
0N/A if (serializable <= 0) return;
0N/A
0N/A boolean prev = serializing;
0N/A
0N/A serializing = true;
0N/A
0N/A int count = 0;
0N/A
0N/A synchronized(children) {
0N/A Iterator i = children.entrySet().iterator();
0N/A
0N/A while (i.hasNext() && count < serializable) {
0N/A Map.Entry entry = (Map.Entry)i.next();
0N/A
0N/A if (entry.getKey() instanceof Serializable) {
0N/A try {
0N/A oos.writeObject(entry.getKey()); // child
0N/A oos.writeObject(entry.getValue()); // BCSChild
0N/A } catch (IOException ioe) {
0N/A serializing = prev;
0N/A throw ioe;
0N/A }
0N/A count++;
0N/A }
0N/A }
0N/A }
0N/A
0N/A serializing = prev;
0N/A
0N/A if (count != serializable) {
0N/A throw new IOException("wrote different number of children than expected");
0N/A }
0N/A
0N/A }
0N/A
0N/A /**
0N/A * Serialize the BeanContextSupport, if this instance has a distinct
0N/A * peer (that is this object is acting as a delegate for another) then
0N/A * the children of this instance are not serialized here due to a
0N/A * 'chicken and egg' problem that occurs on deserialization of the
0N/A * children at the same time as this instance.
0N/A *
0N/A * Therefore in situations where there is a distinct peer to this instance
0N/A * it should always call writeObject() followed by writeChildren() and
0N/A * readObject() followed by readChildren().
0N/A *
0N/A * @param oos the ObjectOutputStream
0N/A */
0N/A
0N/A private synchronized void writeObject(ObjectOutputStream oos) throws IOException, ClassNotFoundException {
0N/A serializing = true;
0N/A
0N/A synchronized (BeanContext.globalHierarchyLock) {
0N/A try {
0N/A oos.defaultWriteObject(); // serialize the BeanContextSupport object
0N/A
0N/A bcsPreSerializationHook(oos);
0N/A
0N/A if (serializable > 0 && this.equals(getBeanContextPeer()))
0N/A writeChildren(oos);
0N/A
0N/A serialize(oos, (Collection)bcmListeners);
0N/A } finally {
0N/A serializing = false;
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * When an instance of this class is used as a delegate for the
0N/A * implementation of the BeanContext protocols (and its subprotocols)
0N/A * there exists a 'chicken and egg' problem during deserialization
0N/A */
0N/A
0N/A public final void readChildren(ObjectInputStream ois) throws IOException, ClassNotFoundException {
0N/A int count = serializable;
0N/A
0N/A while (count-- > 0) {
0N/A Object child = null;
0N/A BeanContextSupport.BCSChild bscc = null;
0N/A
0N/A try {
0N/A child = ois.readObject();
0N/A bscc = (BeanContextSupport.BCSChild)ois.readObject();
0N/A } catch (IOException ioe) {
0N/A continue;
0N/A } catch (ClassNotFoundException cnfe) {
0N/A continue;
0N/A }
0N/A
0N/A
0N/A synchronized(child) {
0N/A BeanContextChild bcc = null;
0N/A
0N/A try {
0N/A bcc = (BeanContextChild)child;
0N/A } catch (ClassCastException cce) {
0N/A // do nothing;
0N/A }
0N/A
0N/A if (bcc != null) {
0N/A try {
0N/A bcc.setBeanContext(getBeanContextPeer());
0N/A
0N/A bcc.addPropertyChangeListener("beanContext", childPCL);
0N/A bcc.addVetoableChangeListener("beanContext", childVCL);
0N/A
0N/A } catch (PropertyVetoException pve) {
0N/A continue;
0N/A }
0N/A }
0N/A
0N/A childDeserializedHook(child, bscc);
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * deserialize contents ... if this instance has a distinct peer the
0N/A * children are *not* serialized here, the peer's readObject() must call
0N/A * readChildren() after deserializing this instance.
0N/A */
0N/A
0N/A private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
0N/A
0N/A synchronized(BeanContext.globalHierarchyLock) {
0N/A ois.defaultReadObject();
0N/A
0N/A initialize();
0N/A
0N/A bcsPreDeserializationHook(ois);
0N/A
0N/A if (serializable > 0 && this.equals(getBeanContextPeer()))
0N/A readChildren(ois);
0N/A
0N/A deserialize(ois, bcmListeners = new ArrayList(1));
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * subclasses may envelope to monitor veto child property changes.
0N/A */
0N/A
0N/A public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException {
0N/A String propertyName = pce.getPropertyName();
0N/A Object source = pce.getSource();
0N/A
0N/A synchronized(children) {
0N/A if ("beanContext".equals(propertyName) &&
0N/A containsKey(source) &&
0N/A !getBeanContextPeer().equals(pce.getNewValue())
0N/A ) {
0N/A if (!validatePendingRemove(source)) {
0N/A throw new PropertyVetoException("current BeanContext vetoes setBeanContext()", pce);
0N/A } else ((BCSChild)children.get(source)).setRemovePending(true);
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * subclasses may envelope to monitor child property changes.
0N/A */
0N/A
0N/A public void propertyChange(PropertyChangeEvent pce) {
0N/A String propertyName = pce.getPropertyName();
0N/A Object source = pce.getSource();
0N/A
0N/A synchronized(children) {
0N/A if ("beanContext".equals(propertyName) &&
0N/A containsKey(source) &&
0N/A ((BCSChild)children.get(source)).isRemovePending()) {
0N/A BeanContext bc = getBeanContextPeer();
0N/A
0N/A if (bc.equals(pce.getOldValue()) && !bc.equals(pce.getNewValue())) {
0N/A remove(source, false);
0N/A } else {
0N/A ((BCSChild)children.get(source)).setRemovePending(false);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * <p>
0N/A * Subclasses of this class may override, or envelope, this method to
0N/A * add validation behavior for the BeanContext to examine child objects
0N/A * immediately prior to their being added to the BeanContext.
0N/A * </p>
0N/A *
0N/A * @return true iff the child may be added to this BeanContext, otherwise false.
0N/A */
0N/A
0N/A protected boolean validatePendingAdd(Object targetChild) {
0N/A return true;
0N/A }
0N/A
0N/A /**
0N/A * <p>
0N/A * Subclasses of this class may override, or envelope, this method to
0N/A * add validation behavior for the BeanContext to examine child objects
0N/A * immediately prior to their being removed from the BeanContext.
0N/A * </p>
0N/A *
0N/A * @return true iff the child may be removed from this BeanContext, otherwise false.
0N/A */
0N/A
0N/A protected boolean validatePendingRemove(Object targetChild) {
0N/A return true;
0N/A }
0N/A
0N/A /**
0N/A * subclasses may override this method to simply extend add() semantics
0N/A * after the child has been added and before the event notification has
0N/A * occurred. The method is called with the child synchronized.
0N/A */
0N/A
0N/A protected void childJustAddedHook(Object child, BCSChild bcsc) {
0N/A }
0N/A
0N/A /**
0N/A * subclasses may override this method to simply extend remove() semantics
0N/A * after the child has been removed and before the event notification has
0N/A * occurred. The method is called with the child synchronized.
0N/A */
0N/A
0N/A protected void childJustRemovedHook(Object child, BCSChild bcsc) {
0N/A }
0N/A
0N/A /**
0N/A * Gets the Component (if any) associated with the specified child.
0N/A * @param child the specified child
0N/A * @return the Component (if any) associated with the specified child.
0N/A */
0N/A protected static final Visibility getChildVisibility(Object child) {
0N/A try {
0N/A return (Visibility)child;
0N/A } catch (ClassCastException cce) {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the Serializable (if any) associated with the specified Child
0N/A * @param child the specified child
0N/A * @return the Serializable (if any) associated with the specified Child
0N/A */
0N/A protected static final Serializable getChildSerializable(Object child) {
0N/A try {
0N/A return (Serializable)child;
0N/A } catch (ClassCastException cce) {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the PropertyChangeListener
0N/A * (if any) of the specified child
0N/A * @param child the specified child
0N/A * @return the PropertyChangeListener (if any) of the specified child
0N/A */
0N/A protected static final PropertyChangeListener getChildPropertyChangeListener(Object child) {
0N/A try {
0N/A return (PropertyChangeListener)child;
0N/A } catch (ClassCastException cce) {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the VetoableChangeListener
0N/A * (if any) of the specified child
0N/A * @param child the specified child
0N/A * @return the VetoableChangeListener (if any) of the specified child
0N/A */
0N/A protected static final VetoableChangeListener getChildVetoableChangeListener(Object child) {
0N/A try {
0N/A return (VetoableChangeListener)child;
0N/A } catch (ClassCastException cce) {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the BeanContextMembershipListener
0N/A * (if any) of the specified child
0N/A * @param child the specified child
0N/A * @return the BeanContextMembershipListener (if any) of the specified child
0N/A */
0N/A protected static final BeanContextMembershipListener getChildBeanContextMembershipListener(Object child) {
0N/A try {
0N/A return (BeanContextMembershipListener)child;
0N/A } catch (ClassCastException cce) {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Gets the BeanContextChild (if any) of the specified child
0N/A * @param child the specified child
0N/A * @return the BeanContextChild (if any) of the specified child
0N/A * @throws IllegalArgumentException if child implements both BeanContextChild and BeanContextProxy
0N/A */
0N/A protected static final BeanContextChild getChildBeanContextChild(Object child) {
0N/A try {
0N/A BeanContextChild bcc = (BeanContextChild)child;
0N/A
0N/A if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
0N/A throw new IllegalArgumentException("child cannot implement both BeanContextChild and BeanContextProxy");
0N/A else
0N/A return bcc;
0N/A } catch (ClassCastException cce) {
0N/A try {
0N/A return ((BeanContextProxy)child).getBeanContextProxy();
0N/A } catch (ClassCastException cce1) {
0N/A return null;
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
0N/A */
0N/A
0N/A protected final void fireChildrenAdded(BeanContextMembershipEvent bcme) {
0N/A Object[] copy;
0N/A
0N/A synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
0N/A
0N/A for (int i = 0; i < copy.length; i++)
0N/A ((BeanContextMembershipListener)copy[i]).childrenAdded(bcme);
0N/A }
0N/A
0N/A /**
0N/A * Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
0N/A */
0N/A
0N/A protected final void fireChildrenRemoved(BeanContextMembershipEvent bcme) {
0N/A Object[] copy;
0N/A
0N/A synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
0N/A
0N/A for (int i = 0; i < copy.length; i++)
0N/A ((BeanContextMembershipListener)copy[i]).childrenRemoved(bcme);
0N/A }
0N/A
0N/A /**
0N/A * protected method called from constructor and readObject to initialize
0N/A * transient state of BeanContextSupport instance.
0N/A *
0N/A * This class uses this method to instantiate inner class listeners used
0N/A * to monitor PropertyChange and VetoableChange events on children.
0N/A *
0N/A * subclasses may envelope this method to add their own initialization
0N/A * behavior
0N/A */
0N/A
0N/A protected synchronized void initialize() {
0N/A children = new HashMap(serializable + 1);
0N/A bcmListeners = new ArrayList(1);
0N/A
0N/A childPCL = new PropertyChangeListener() {
0N/A
0N/A /*
0N/A * this adaptor is used by the BeanContextSupport class to forward
0N/A * property changes from a child to the BeanContext, avoiding
0N/A * accidential serialization of the BeanContext by a badly
0N/A * behaved Serializable child.
0N/A */
0N/A
0N/A public void propertyChange(PropertyChangeEvent pce) {
0N/A BeanContextSupport.this.propertyChange(pce);
0N/A }
0N/A };
0N/A
0N/A childVCL = new VetoableChangeListener() {
0N/A
0N/A /*
0N/A * this adaptor is used by the BeanContextSupport class to forward
0N/A * vetoable changes from a child to the BeanContext, avoiding
0N/A * accidential serialization of the BeanContext by a badly
0N/A * behaved Serializable child.
0N/A */
0N/A
0N/A public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException {
0N/A BeanContextSupport.this.vetoableChange(pce);
0N/A }
0N/A };
0N/A }
0N/A
0N/A /**
0N/A * Gets a copy of the this BeanContext's children.
0N/A * @return a copy of the current nested children
0N/A */
0N/A protected final Object[] copyChildren() {
0N/A synchronized(children) { return children.keySet().toArray(); }
0N/A }
0N/A
0N/A /**
0N/A * Tests to see if two class objects,
0N/A * or their names are equal.
0N/A * @param first the first object
0N/A * @param second the second object
0N/A * @return true if equal, false if not
0N/A */
0N/A protected static final boolean classEquals(Class first, Class second) {
0N/A return first.equals(second) || first.getName().equals(second.getName());
0N/A }
0N/A
0N/A
0N/A /*
0N/A * fields
0N/A */
0N/A
0N/A
0N/A /**
0N/A * all accesses to the <code> protected HashMap children </code> field
0N/A * shall be synchronized on that object.
0N/A */
0N/A protected transient HashMap children;
0N/A
0N/A private int serializable = 0; // children serializable
0N/A
0N/A /**
0N/A * all accesses to the <code> protected ArrayList bcmListeners </code> field
0N/A * shall be synchronized on that object.
0N/A */
0N/A protected transient ArrayList bcmListeners;
0N/A
0N/A //
0N/A
0N/A /**
0N/A * The current locale of this BeanContext.
0N/A */
0N/A protected Locale locale;
0N/A
0N/A /**
0N/A * A <tt>boolean</tt> indicating if this
0N/A * instance may now render a GUI.
0N/A */
0N/A protected boolean okToUseGui;
0N/A
0N/A
0N/A /**
0N/A * A <tt>boolean</tt> indicating whether or not
0N/A * this object is currently in design time mode.
0N/A */
0N/A protected boolean designTime;
0N/A
0N/A /*
0N/A * transient
0N/A */
0N/A
0N/A private transient PropertyChangeListener childPCL;
0N/A
0N/A private transient VetoableChangeListener childVCL;
0N/A
0N/A private transient boolean serializing;
0N/A}