summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/beans/beancontext
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/beans/beancontext')
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContext.java272
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextChild.java174
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextChildComponentProxy.java60
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextChildSupport.java381
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextContainerProxy.java63
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextEvent.java110
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextMembershipEvent.java114
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextMembershipListener.java70
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextProxy.java65
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceAvailableEvent.java97
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceProvider.java138
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java60
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedEvent.java112
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedListener.java62
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServices.java216
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServicesListener.java56
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java896
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextSupport.java1079
-rw-r--r--libjava/classpath/java/beans/beancontext/package.html46
19 files changed, 4071 insertions, 0 deletions
diff --git a/libjava/classpath/java/beans/beancontext/BeanContext.java b/libjava/classpath/java/beans/beancontext/BeanContext.java
new file mode 100644
index 000000000..803cb36ff
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContext.java
@@ -0,0 +1,272 @@
+/* java.beans.beancontext.BeanContext
+ Copyright (C) 1999 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.DesignMode;
+import java.beans.Visibility;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+
+/**
+ * Acts as a container for sub-beans and as a sub-bean,
+ * so that an entire hierarchy of beans can be made up of
+ * <code>BeanContext</code>s.
+ * <P>
+ *
+ * Since I can't sprinkle the <code>Collections</code> interface
+ * documentation with special information for <code>BeanContext</code>
+ * implementors, I'll have to document special requirements for
+ * implementors of those functions here.
+ * <P>
+ *
+ * <code><strong>add()</strong></code> or <code>addAll()</code>:
+ * <br>
+ * <OL>
+ * <LI>
+ * May add any <code>Object</code> into the hierarchy as well as a
+ * <code>BeanContextChild</code>, <code>BeanContext</code> or
+ * <code>BeanContextProxy</code> object.
+ * This way, any Bean can be in the hierarchy.
+ * </LI>
+ * <LI>
+ * Must synchronize on <code>BeanContext.globalHierarchyLock</code>.
+ * </LI>
+ * <LI>
+ * Don't add the <code>Object</code> if it's already there (only once
+ * per <code>BeanContext</code>).
+ * </LI>
+ * <LI>
+ * If it is a <code>BeanContextChild</code> implementor, call
+ * <code>setBeanContext()</code> on it. If it's a
+ * <code>BeanContextProxy</code> implementor, call
+ * <code>getBeanContextProxy().setBeanContext()</code> on it.
+ * If <code>setBeanContext()</code> vetoes the change, back out
+ * all changes so far and throw <code>IllegalStateException</code>.
+ * </LI>
+ * <LI>
+ * If it (or its proxy) implements <code>Visibility</code>, call
+ * <code>dontUseGui()</code> or <code>okToUseGui()</code> on it,
+ * depending on whether you (the <code>BeanContext</code>) feel like
+ * allowing it to use the GUI or not.
+ * </LI>
+ * <LI>
+ * If it implements <code>BeanContextChild</code> or
+ * <code>BeanContextProxy</code>, register yourself (the
+ * <code>BeanContext</code>) as both a
+ * <code>PropertyChangeListener</code> and
+ * <code>VetoableChangeListener</code> on the "beanContext"
+ * property (it may also add itself on any other properties it wishes
+ * to).
+ * </LI>
+ * <LI>
+ * If it is a listener or event source that you (the
+ * <code>BeanContext</code>) are interested in, you may register
+ * yourself to it or register it to you.
+ * </LI>
+ * <LI>
+ * Fire a <code>java.beans.beancontext.BeanContextMembershipEvent</code>
+ * before exiting. <code>addAll()</code> should wait until everything
+ * is done changing before firing the event (or events) so that if a
+ * failure occurs, the backing-out process can proceed without any
+ * events being fired at all.
+ * </LI>
+ * </OL>
+ * <P>
+ *
+ * <code><strong>remove()</strong></code> or <code>removeAll()</code>:
+ * <br>
+ * <OL>
+ * <LI>
+ * Must synchronize on <code>BeanContext.globalHierarchyLock</code>.
+ * </LI>
+ * <LI>
+ * If the specified <code>Object</code> is not a child of this
+ * <code>BeanContext</code>, just exit without performing any actions.
+ * </LI>
+ * <LI>
+ * Remove the <code>Object</code> from your collection of children.
+ * </LI>
+ * <LI>
+ * If it is a <code>BeanContextChild</code> implementor, call
+ * <code>setBeanContext(null)</code> on it. If it's a
+ * <code>BeanContextProxy</code> implementor, call
+ * <code>getBeanContextProxy().setBeanContext(null)</code> on it.
+ * If <code>setBeanContext()</code> vetoes the change, back out
+ * all changes so far and throw <code>IllegalStateException</code>.
+ * </LI>
+ * <LI>
+ * If you registered the <code>Object</code> to listen to you or
+ * registered yourself as a listener on the <code>Object</code> during
+ * <code>add()</code> or <code>addAll()</code>, undo the registration
+ * bycalling the appropriate <code>removeListener()</code> method.
+ * </LI>
+ * <LI>
+ * Fire a <code>java.beans.beancontext.BeanContextMembershipEvent</code>
+ * before exiting. <code>removeAll()</code> should wait until
+ * everything is done changing before firing the event (or events) so
+ * that if a failure occurs, the backing-out process can proceed
+ * without any events being fired at all.
+ * </LI>
+ * </OL>
+ * <P>
+ *
+ * <code>addAll()</code>, <code>removeAll()</code>,
+ * <code>retainAll()</code> and <code>clear()</code> do not need to be
+ * implemented, but may be if so desired.
+ * <P>
+ *
+ * Similarly, <code>Visibility</code> and <code>DesignMode</code> methods
+ * should propagate changed values to children that implement interfaces
+ * of the same name.
+ * <P>
+ *
+ * A hierarchy of beans is mainly useful so that different sets of beans
+ * can be established, each with their own set of resources.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContext
+ extends Collection, BeanContextChild, Visibility, DesignMode {
+
+ /**
+ * The global lock on changing any BeanContext hierarchy.
+ * It kinda sucks that there is only one lock, since there can be
+ * multiple hierarchies. Oh well, I didn't design, I just code.
+ * <P>
+ *
+ * Methods that must (or do) synchronize on the global lock:
+ * <BR>
+ * <UL>
+ * <LI>
+ * Implementors of <CODE>BeanContext.add()</CODE> and <code>addAll()</code>
+ * </LI>
+ * </UL>
+ * @fixme fill in the rest of the methods which use the global lock.
+ */
+ Object globalHierarchyLock = new Object();
+
+ /**
+ * Instantiate a Bean using this Bean's <code>ClassLoader</code>
+ * and this <code>BeanContext</code> as the parent.
+ * <P>
+ *
+ * This method exists mainly so that <code>BeanContext</code>
+ * implementations can perform extra actions on Beans that are
+ * created within them.
+ *
+ * @param beanName the name of the bean to instantiate
+ * @return the created Bean
+ *
+ * @see java.beans.Beans#instantiate(java.lang.ClassLoader,java.lang.String)
+ * @see java.beans.Beans#instantiate(java.lang.ClassLoader,java.lang.String,java.beans.beancontext.BeanContext)
+ * @exception IOException if there is an I/O problem during
+ * instantiation.
+ * @exception ClassNotFoundException if a serialized Bean's class
+ * is not found.
+ */
+ Object instantiateChild(String beanName)
+ throws IOException,
+ ClassNotFoundException;
+
+ /**
+ * Get a resource. The <code>BeanContext</code> will typically
+ * call <code>ClassLoader.getResource()</code>, but may do it any
+ * way it wants to. This allows a <code>BeanContext</code> to
+ * have its own set of resources separate from the rest of the
+ * system.
+ * <P>
+ *
+ * Beans should call this method on their parent rather than the
+ * associated <code>ClassLoader</code> method.
+ * <P>
+ *
+ * I am assuming, but am not entirely sure, that if a
+ * <code>BeanContext</code> cannot find a resource, its
+ * responsibility is to call the <code>getResource</code> method
+ * of its parent <code>BeanContext</code>.
+ *
+ * @return a URL to the requested resource.
+ * @param resourceName the name of the resource requested.
+ * @param requestor a reference to the child requesting the resource.
+ * @see java.lang.ClassLoader#getResource(java.lang.String)
+ */
+ URL getResource(String resourceName, BeanContextChild requestor);
+
+ /**
+ * Get a resource as a stream. The <code>BeanContext</code> will
+ * typically call <code>ClassLoader.getResourceAsStream()</code>,
+ * but may do it any way it wants to. This allows a
+ * <code>BeanContext</code>'s children to have their own set of
+ * resources separate from the rest of the system.
+ * <P>
+ *
+ * Beans should call this method on their parent rather than the
+ * associated <code>ClassLoader</code> method.
+ * <P>
+ *
+ * I am assuming, but am not entirely sure, that if a
+ * <code>BeanContext</code> cannot find a resource, its
+ * responsibility is to call the <code>getResourceAsStream</code>
+ * method of its parent <code>BeanContext</code>.
+ *
+ * @return the requested resource as a stream.
+ * @param resourceName the name of the resource requested.
+ * @param requestor a reference to the child requesting the resource.
+ * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
+ */
+ InputStream getResourceAsStream(String resourceName, BeanContextChild requestor);
+
+ /**
+ * Add a listener on changes to the membership of this
+ * <code>BeanContext</code> object.
+ * @param listener the listener to add.
+ */
+ void addBeanContextMembershipListener(BeanContextMembershipListener listener);
+
+ /**
+ * Remove a listener on changes to the membership of this
+ * <code>BeanContext</code> object.
+ * @param listener the listener to remove.
+ */
+ void removeBeanContextMembershipListener(BeanContextMembershipListener listener);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextChild.java b/libjava/classpath/java/beans/beancontext/BeanContextChild.java
new file mode 100644
index 000000000..e2bdcf336
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextChild.java
@@ -0,0 +1,174 @@
+/* java.beans.beancontext.BeanContextChild
+ Copyright (C) 1999 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.PropertyChangeListener;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+
+/**
+ * Beans implement this to get information about the execution environment and
+ * its services and to be placed in the hierarchy.
+ * <P>
+ *
+ * The difference between a <code>BeanContext</code> and a
+ * <code>BeanContextChild</code>, mainly, is that a
+ * <code>BeanContext</code> may be a parent.
+ * <P>
+ *
+ * <code>BeanContextChild</code> instances will be serialized at some
+ * point in their life, but you need to make sure your bean context does
+ * not contain a serializable reference (directly or indirectly) to the
+ * parent <code>BeanContext</code>, to any of the other
+ * <code>BeanContext</code>s in the tree, or to any resources obtained
+ * via the <code>BeanContextServices</code> interface. One way to do this
+ * is to mark any fields that contain such references as
+ * <code>transient</code>. Another way is to use a custom serializer.
+ * <P>
+ *
+ * If you do not do this, when the <code>BeanContext</code> is serialized,
+ * all the other <code>BeanContext</code>s and other unnecessary things
+ * will be serialized along with it.
+ * <P>
+ *
+ * Before dying, a <code>BeanContextChild</code> should call
+ * <code>getBeanContext().remove(this)</code> to detach from the
+ * hierarchy and exit cleanly.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContext
+ */
+
+public interface BeanContextChild {
+ /**
+ * Set the parent <code>BeanContext</code>.
+ * <P>
+ *
+ * This method is called from <code>BeanContext.add()</code> and
+ * should not be called directly.
+ * <P>
+ *
+ * When this Object is being added to a new BeanContext or moved
+ * from an old one, a non-null value will be passed in.
+ * <P>
+ *
+ * When this Object is being removed from the current
+ * <code>BeanContext</code>, <code>setBeanContext()</code> will
+ * receive the parameter <code>null</code>.
+ * <P>
+ *
+ * When being removed from the current <code>BeanContext</code>,
+ * it is the <code>BeanContextChild</code>'s responsibility to
+ * release all services it has obtained.
+ * <P>
+ *
+ * This change should generate <code>PropertyChangeEvent</code>
+ * and <code>VetoableChangeEvent</code>s with the property name
+ * "beanContext". If the change is vetoed, it must re-throw the
+ * exception and not change anything. In this way, the parent
+ * <code>BeanContextChild</code>, who has registered himself with
+ * you, will have a chance to remove this child from its
+ * collection.
+ * <P>
+ *
+ * If the Bean does not wish to change the parent or be removed
+ * from one, it may throw the <code>PropertyVetoException</code>.
+ * If you veto a <code>setBeanContext(null)</code> call, then you
+ * should try your hardest to remedy whatever problem is keeping
+ * you from being removed from the <code>BeanContext</code> so
+ * that you can <em>not</em> veto it the next time.
+ * Otherwise, nasty pathological recursion stuff could occur in
+ * certain situations.
+ * <P>
+ *
+ * If you do veto the change, you must first back out any changes
+ * you made prior to the veto. Best not to make any such changes
+ * prior to the veto in the first place.
+ * <P>
+ *
+ * This method is called from <code>BeanContext.add()</code> and
+ * should not be called directly.
+ *
+ * @param parent the new parent for the <code>BeanContextChild</code>,
+ * or <code>null</code> to signify removal from a tree.
+ * @exception PropertyVetoException if the
+ * <code>BeanContextChild</code> implementor does not
+ * wish to have its parent changed.
+ */
+ void setBeanContext(BeanContext parent)
+ throws PropertyVetoException;
+
+ /**
+ * Get the parent <code>BeanContext</code>.
+ * @return the parent <code>BeanContext</code>.
+ */
+ BeanContext getBeanContext();
+
+ /**
+ * Add a listener that will be notified when a specific property changes.
+ * @param prop the name of the property to listen on
+ * @param listener the listener to listen on the property.
+ */
+ void addPropertyChangeListener(String prop, PropertyChangeListener listener);
+
+ /**
+ * Remove a listener to a certain property.
+ * @param prop the name of the property being listened on
+ * @param listener the listener listening on the property.
+ */
+ void removePropertyChangeListener(String prop, PropertyChangeListener listener);
+
+ /**
+ * Add a listener that will be notified when a specific property
+ * change is requested (a PropertyVetoException may be thrown) as
+ * well as after the change is successfully made.
+ *
+ * @param prop the name of the property to listen on
+ * @param listener the listener to listen on the property.
+ */
+ void addVetoableChangeListener(String prop, VetoableChangeListener listener);
+
+ /**
+ * Remove a listener to a certain property.
+ * @param prop the name of the property being listened on
+ * @param listener the listener listening on the property.
+ */
+ void removeVetoableChangeListener(String prop, VetoableChangeListener listener);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextChildComponentProxy.java b/libjava/classpath/java/beans/beancontext/BeanContextChildComponentProxy.java
new file mode 100644
index 000000000..cb75d508d
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextChildComponentProxy.java
@@ -0,0 +1,60 @@
+/* java.beans.beancontext.BeanContextChildComponentProxy
+ Copyright (C) 1999 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.awt.Component;
+
+/**
+ * Interface for <code>BeanContextChild</code>s which wish to associate an
+ * AWT component with them. The proxy is provided because the
+ * <code>addPropertyChangeListener()</code> method would conflict with
+ * <code>Component</code> if you tried to extend.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextChildComponentProxy {
+ /**
+ * Get the <code>Component</code> associated with this <code>BeanContextChild</code>.
+ * @return the <code>Component</code> associated with this
+ * <code>BeanContextChild</code>.
+ */
+ Component getComponent();
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextChildSupport.java b/libjava/classpath/java/beans/beancontext/BeanContextChildSupport.java
new file mode 100644
index 000000000..8cd887d0c
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextChildSupport.java
@@ -0,0 +1,381 @@
+/* java.beans.beancontext.BeanContextChildSupport
+ Copyright (C) 1999 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.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.VetoableChangeSupport;
+import java.io.Serializable;
+
+/**
+ * Support for creating a <code>BeanContextChild</code>.
+ * This class contains the most common implementations of the methods in
+ * the <code>BeanContextChild</code>
+ *
+ * @specnote This class is not very well specified. I had to "fill in the
+ * blanks" in most places with what I thought was reasonable
+ * behavior. If there are problems, let me know.
+ *
+ * @author John Keiser
+ * @since 1.2
+ * @see java.beans.beancontext.BeanContextChild
+ */
+public class BeanContextChildSupport
+ implements BeanContextChild, BeanContextServicesListener, Serializable
+{
+ static final long serialVersionUID = 6328947014421475877L;
+
+ /**
+ * The peer on which to perform <code>set</code> actions.
+ * This is here so that this class can be used as a peer.
+ * <P>
+ *
+ * When extending this class, this variable will be set to
+ * <code>this</code>.
+ */
+ public BeanContextChild beanContextChildPeer;
+
+ /**
+ * The parent <code>BeanContext</code>.
+ */
+ protected transient BeanContext beanContext;
+
+ /**
+ * If <code>setBeanContext()</code> was vetoed once before, this
+ * is set to <code>true</code> so that the next time, vetoes will
+ * be ignored.
+ */
+ protected transient boolean rejectedSetBCOnce;
+
+ /**
+ * Listeners are registered here and events are fired through here.
+ */
+ protected PropertyChangeSupport pcSupport;
+
+ /**
+ * Listeners are registered here and events are fired through here.
+ */
+ protected VetoableChangeSupport vcSupport;
+
+ /**
+ * Create a new <code>BeanContextChildSupport</code> with itself as the peer.
+ * This is meant to be used when you subclass
+ * <code>BeanContextChildSupport</code> to create your child.
+ */
+ public BeanContextChildSupport()
+ {
+ this (null);
+ }
+
+ /**
+ * Create a new <code>BeanContextChildSupport</code> with the specified peer.
+ * @param peer the peer to use, or <code>null</code> to specify
+ * <code>this</code>.
+ */
+ public BeanContextChildSupport (BeanContextChild peer)
+ {
+ if (peer == null)
+ {
+ peer = this;
+ }
+
+ beanContextChildPeer = peer;
+ pcSupport = new PropertyChangeSupport (peer);
+ vcSupport = new VetoableChangeSupport (peer);
+ }
+
+ /**
+ * Set the parent <code>BeanContext</code>.
+ * <P>
+ *
+ * When this Object is being added to a new BeanContext or moved
+ * from an old one, a non-null value will be passed in.
+ * <P>
+ *
+ * When this Object is being removed from the current
+ * <code>BeanContext</code>, <code>setBeanContext()</code> will
+ * receive the parameter <code>null</code>.
+ * <P>
+ *
+ * Order of events:
+ * <OL>
+ * <LI>
+ * If the new <code>BeanContext</code> is the same as the old
+ * one, nothing happens.
+ * </LI>
+ * <LI>
+ * If the change has not been rejected or vetoed before, call
+ * <code>validatePendingSetBeanContext()</code>. If this call
+ * returns <code>false</code>, the change is rejected and a
+ * <code>PropertyVetoException</code> is thrown.
+ * </LI>
+ * <LI>
+ * If the change has not been rejected or vetoed before,
+ * <code>VetoableChangeEvent</code>s are fired with the name
+ * <code>"beanContext"</code>, using the
+ * <code>fireVetoableChange()</code> method. If a veto
+ * occurs, reversion events are fired using the same method,
+ * the change is rejected, and the veto is rethrown.
+ * </LI>
+ * <LI>
+ * <code>releaseBeanContextResources()</code> is called.
+ * </LI>
+ * <LI>
+ * The change is made.
+ * </LI>
+ * <LI>
+ * <code>PropertyChangeEvent</code>s are fired using the
+ * <code>firePropertyChange()</code> method.
+ * </LI>
+ * <LI>
+ * <code>initializeBeanContextResources()</code> is called.
+ * </LI>
+ * </OL>
+ * <P>
+ *
+ * @param newBeanContext the new parent for the
+ * <code>BeanContextChild</code>, or <code>null</code> to
+ * signify removal from a tree.
+ * @exception PropertyVetoException if the
+ * <code>BeanContextChild</code> implementor does not
+ * wish to have its parent changed.
+ */
+ public void setBeanContext(BeanContext newBeanContext)
+ throws PropertyVetoException
+ {
+ synchronized (beanContextChildPeer)
+ {
+ if (newBeanContext == beanContext)
+ return;
+
+ if (!rejectedSetBCOnce)
+ {
+ if (!validatePendingSetBeanContext (newBeanContext))
+ {
+ rejectedSetBCOnce = true;
+ throw new PropertyVetoException ("validatePendingSetBeanContext() rejected change",
+ new PropertyChangeEvent(beanContextChildPeer, "beanContext", beanContext, newBeanContext));
+ }
+
+ try
+ {
+ fireVetoableChange ("beanContext", beanContext, newBeanContext);
+ }
+ catch (PropertyVetoException e)
+ {
+ rejectedSetBCOnce = true;
+ throw e;
+ }
+ }
+
+ releaseBeanContextResources ();
+
+ beanContext = newBeanContext;
+ rejectedSetBCOnce = false;
+
+ firePropertyChange ("beanContext", beanContext, newBeanContext);
+
+ initializeBeanContextResources ();
+ }
+ }
+
+ /**
+ * Get the parent <code>BeanContext</code>.
+ * @return the parent <code>BeanContext</code>.
+ */
+ public BeanContext getBeanContext()
+ {
+ return beanContext;
+ }
+
+ /**
+ * Get the peer (or <code>this</code> if there is no peer).
+ * @return the peer, or <code>this</code> if there is no peer.
+ */
+ public BeanContextChild getBeanContextChildPeer() {
+ return beanContextChildPeer;
+ }
+
+ /**
+ * Determine whether there is a peer.
+ * This is true iff <code>getBeanContextChildPeer() == this</code>.
+ * @return whether there is a peer.
+ */
+ public boolean isDelegated() {
+ return beanContextChildPeer == this;
+ }
+
+ /**
+ * Add a listener that will be notified when a specific property changes.
+ * @param propertyName the name of the property to listen on.
+ * @param listener the listener to listen on the property.
+ */
+ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ pcSupport.addPropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Remove a listener to a certain property.
+ *
+ * @param propertyName the name of the property being listened on.
+ * @param listener the listener listening on the property.
+ */
+ public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ pcSupport.removePropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Add a listener that will be notified when a specific property
+ * change is requested (a PropertyVetoException may be thrown) as
+ * well as after the change is successfully made.
+ *
+ * @param propertyName the name of the property to listen on.
+ * @param listener the listener to listen on the property.
+ */
+ public void addVetoableChangeListener(String propertyName, VetoableChangeListener listener) {
+ vcSupport.addVetoableChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Remove a listener to a certain property.
+ *
+ * @param propertyName the name of the property being listened on
+ * @param listener the listener listening on the property.
+ */
+ public void removeVetoableChangeListener(String propertyName, VetoableChangeListener listener) {
+ vcSupport.removeVetoableChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Fire a property change.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value of the property
+ * @param newVal the new value of the property
+ */
+ public void firePropertyChange(String propertyName, Object oldVal, Object newVal) {
+ pcSupport.firePropertyChange(propertyName, oldVal, newVal);
+ }
+
+ /**
+ * Fire a vetoable property change.
+ *
+ * @param propertyName the name of the property that changed
+ * @param oldVal the old value of the property
+ * @param newVal the new value of the property
+ * @exception PropertyVetoException if the change is vetoed.
+ */
+ public void fireVetoableChange(String propertyName, Object oldVal, Object newVal)
+ throws PropertyVetoException {
+ vcSupport.fireVetoableChange(propertyName, oldVal, newVal);
+ }
+
+ /**
+ * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked.
+ * If you have a reference to such a service, it should be
+ * discarded and may no longer function properly.
+ * <code>getService()</code> will no longer work on the specified
+ * service class after this event has been fired.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation does
+ * nothing.
+ *
+ * @param event the service revoked event.
+ * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean)
+ */
+ public void serviceRevoked(BeanContextServiceRevokedEvent event) {
+ }
+
+ /**
+ * Called by <code>BeanContextServices</code> whenever a service is made available.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation does
+ * nothing.
+ *
+ * @param event the service revoked event, with useful information
+ * about the new service.
+ */
+ public void serviceAvailable(BeanContextServiceAvailableEvent event) {
+ }
+
+ /**
+ * Called by <code>setBeanContext()</code> to determine whether the set should be rejected.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation simply
+ * returns <code>true</code>.
+ *
+ * @param newBeanContext the new parent.
+ * @return whether to allow the parent to be changed to the new
+ * value.
+ */
+ public boolean validatePendingSetBeanContext(BeanContext newBeanContext) {
+ return true;
+ }
+
+ /**
+ * Called by <code>setBeanContext()</code> to release resources of a what will soon no longer be the parent.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation does
+ * nothing.
+ */
+ protected void releaseBeanContextResources() {
+ }
+
+ /**
+ * Called by <code>setBeanContext()</code> to grab resources when the parent has been set.
+ * <P>
+ *
+ * <EM>This method is meant to be overriden.</EM>
+ * <code>BeanContextChildSupport</code>'s implementation does
+ * nothing.
+ */
+ protected void initializeBeanContextResources() {
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextContainerProxy.java b/libjava/classpath/java/beans/beancontext/BeanContextContainerProxy.java
new file mode 100644
index 000000000..962cb5fc9
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextContainerProxy.java
@@ -0,0 +1,63 @@
+/* java.beans.beancontext.BeanContextContainerProxy
+ Copyright (C) 1999 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.awt.Container;
+
+/**
+ * Interface for <code>BeanContext</code>s which wish to associate an
+ * AWT container with them. The proxy is provided because the
+ * <code>addPropertyChangeListener()</code> and <code>add()</code> methods
+ * would conflict with <code>Component</code> and <code>Container</code>
+ * if you tried to extend.
+ *
+ * @specnote It is unclear whether anything besides <code>BeanContext</code>s
+ * are allowed to implement this interface.
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextContainerProxy {
+ /**
+ * Get the <code>Container</code> associated with this <code>BeanContext</code>.
+ * @return the <code>Container</code> associated with this
+ * <code>BeanContext</code>.
+ */
+ Container getContainer();
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextEvent.java b/libjava/classpath/java/beans/beancontext/BeanContextEvent.java
new file mode 100644
index 000000000..959d54e58
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextEvent.java
@@ -0,0 +1,110 @@
+/* java.beans.beancontext.BeanContextEvent
+ Copyright (C) 1999 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.util.EventObject;
+
+/**
+ * Generic superclass for events fired by <code>BeanContext</code>s.
+ *
+ * @author John Keiser
+ * @since 1.2
+ */
+
+public abstract class BeanContextEvent extends EventObject
+{
+ private static final long serialVersionUID = 7267998073569045052L;
+
+ /**
+ * The <code>BeanContext</code> that most recently passed this
+ * event on.
+ */
+ protected BeanContext propagatedFrom;
+
+ /**
+ * Create a new event, from the specified <code>BeanContext</code>.
+ * <code>propagatedFrom</code> will be initialized to
+ * <code>null</code>.
+ *
+ * @param source the source of the event.
+ */
+ protected BeanContextEvent(BeanContext source)
+ {
+ super(source);
+ }
+
+ /**
+ * Get the <code>BeanContext</code> that originated this event.
+ * @return the originator of this event.
+ */
+ public BeanContext getBeanContext()
+ {
+ return (BeanContext)getSource();
+ }
+
+ /**
+ * Get the most recent propagator of this event.
+ * If this value is <code>null</code>, you have received the event
+ * straight from the source.
+ *
+ * @return the most recent propagator of this event.
+ */
+ public BeanContext getPropagatedFrom()
+ {
+ return propagatedFrom;
+ }
+
+ /**
+ * Tell whether this event has been propagated.
+ * @return <code>true</code> iff <code>getPropagatedFrom() != null</code>.
+ */
+ public boolean isPropagated()
+ {
+ return propagatedFrom != null;
+ }
+
+ /**
+ * Set the most recent propagator of this event.
+ * @param propagator the most recent propagator of this event.
+ */
+ public void setPropagatedFrom(BeanContext propagator)
+ {
+ propagatedFrom = propagator;
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextMembershipEvent.java b/libjava/classpath/java/beans/beancontext/BeanContextMembershipEvent.java
new file mode 100644
index 000000000..77b1be43e
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextMembershipEvent.java
@@ -0,0 +1,114 @@
+/* java.beans.beancontext.BeanContextMembershipEvent
+ Copyright (C) 1999, 2004 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.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Event fired when children are added to or removed from a <code>BeanContext</code>.
+ * Whether they were added or removed depends entirely on which method
+ * of the listener interface was called.
+ *
+ * @author John Keiser
+ * @since 1.2
+ * @see java.beans.beancontext.BeanContextMembershipListener
+ */
+public class BeanContextMembershipEvent extends BeanContextEvent {
+ private static final long serialVersionUID = 3499346510334590959L;
+
+ /**
+ * The children that were added or removed.
+ */
+ protected Collection children;
+
+ /**
+ * Create a new membership event.
+ * @param context the event source.
+ * @param children the children added to or removed from the source.
+ */
+ public BeanContextMembershipEvent(BeanContext context, Collection children) {
+ super(context);
+ this.children = children;
+ }
+
+ /**
+ * Create a new membership event.
+ * @param context the event source.
+ * @param children the children added to or removed from the source.
+ */
+ public BeanContextMembershipEvent(BeanContext context, Object[] children) {
+ super(context);
+ this.children = Arrays.asList(children);
+ }
+
+ /**
+ * The number of children removed or added.
+ * @return the number of children removed or added.
+ */
+ public int size() {
+ return children.size();
+ }
+
+ /**
+ * An iterator that will step through all the children.
+ * @return an iterator over all the children.
+ */
+ public Iterator iterator() {
+ return children.iterator();
+ }
+
+ /**
+ * An array of the children.
+ * @return an array of the children.
+ */
+ public Object[] toArray() {
+ return children.toArray();
+ }
+
+ /**
+ * Tell whether the <code>Object</code> is one of the children added or removed.
+ * @param child the child to check.
+ * @return whether the <code>Object</code> is added or removed.
+ */
+ public boolean contains(Object child) {
+ return children.contains(child);
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextMembershipListener.java b/libjava/classpath/java/beans/beancontext/BeanContextMembershipListener.java
new file mode 100644
index 000000000..cdb47c811
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextMembershipListener.java
@@ -0,0 +1,70 @@
+/* java.beans.beancontext.BeanContextMembershipListener
+ Copyright (C) 1999 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.util.EventListener;
+
+/**
+ * This is the interface to which <code>BeanContextMembershipEvent</code>s are sent.
+ * This happens when children are added to or removed from a
+ * <code>BeanContext</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextMembershipListener extends EventListener {
+ /**
+ * When beans are added to a <code>BeanContext</code>,
+ * this method is called to fire the event.
+ *
+ * @param event the event, including which children were added.
+ * @see java.beans.beancontext.BeanContext#add(java.lang.Object)
+ */
+ void childrenAdded(BeanContextMembershipEvent event);
+
+ /**
+ * When beans are removed from a <code>BeanContext</code>,
+ * this method is called to fire the event.
+ *
+ * @param event the event, including which children were removed.
+ * @see java.beans.beancontext.BeanContext#remove(java.lang.Object)
+ */
+ void childrenRemoved(BeanContextMembershipEvent event);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextProxy.java b/libjava/classpath/java/beans/beancontext/BeanContextProxy.java
new file mode 100644
index 000000000..53632e86b
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextProxy.java
@@ -0,0 +1,65 @@
+/* java.beans.beancontext.BeanContextProxy
+ Copyright (C) 1999 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;
+
+/**
+ * Beans that wish to have a <code>BeanContextChild</code> or <code>BeanContext</code> associated with them
+ * but do not wish to implement those interfaces directly, can implement this interface.
+ * <P>
+ *
+ * Don't shoot yourself in the foot: if you already implement
+ * <code>BeanContextChild</code>, directly or indirectly, the whole
+ * workings of this package will be unpredictable because it is
+ * indeterminate as to whether the <code>BeanContextChild</code> is used
+ * in preference to its proxy or vice versa.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextProxy {
+ /**
+ * Return the <code>BeanContextChild</code> associated with this
+ * <code>Object</code>.
+ *
+ * @return the <code>BeanContextChild</code> associated with this
+ * <code>Object</code>.
+ */
+ BeanContextChild getBeanContextProxy();
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceAvailableEvent.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceAvailableEvent.java
new file mode 100644
index 000000000..a2bdcdde7
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceAvailableEvent.java
@@ -0,0 +1,97 @@
+/* java.beans.beancontext.BeanContextServiceAvailableEvent
+ Copyright (C) 1999 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.util.Iterator;
+
+/**
+ * Event fired when new services become available through a <code>BeanContextServices</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextServicesListener
+ */
+
+public class BeanContextServiceAvailableEvent extends BeanContextEvent {
+ private static final long serialVersionUID = -5333985775656400778L;
+
+ /**
+ * The <code>Class</code> representing the service which is now
+ * available.
+ */
+ protected Class serviceClass;
+
+ /**
+ * Create a new service available event.
+ * @param services the <code>BeanContextServices</code> through
+ * which the service is available. This is also the source
+ * of the event.
+ * @param serviceClass the service class that is now available.
+ */
+ public BeanContextServiceAvailableEvent(BeanContextServices services, Class serviceClass) {
+ super(services);
+ this.serviceClass = serviceClass;
+ }
+
+ /**
+ * Get the current service selectors of the service class.
+ * This is identical to <code>getSourceAsBeanContextServices().getCurrentServiceSelectors(getServiceClass())</code>
+ * @return the current service selectors of the service class.
+ */
+ public Iterator getCurrentServiceSelectors() {
+ return getSourceAsBeanContextServices().getCurrentServiceSelectors(serviceClass);
+ }
+
+ /**
+ * Get the newly available service class.
+ * @return the service class.
+ */
+ public Class getServiceClass() {
+ return serviceClass;
+ }
+
+ /**
+ * Get the <code>BeanContextServices</code> through which the new service is available.
+ * @return the <code>BeanContextServices</code> through which the
+ * new service is available.
+ */
+ public BeanContextServices getSourceAsBeanContextServices() {
+ return (BeanContextServices)getSource();
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceProvider.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceProvider.java
new file mode 100644
index 000000000..7475a61bd
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceProvider.java
@@ -0,0 +1,138 @@
+/* java.beans.beancontext.BeanContextServiceProvider
+ Copyright (C) 1999 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.util.Iterator;
+
+/**
+ * An actual factory for services.
+ * <P>
+ *
+ * It is the <code>BeanContextServiceProvider</code>'s responsibility to
+ * register itself with whatever <code>BeanContextServices</code> object
+ * it wishes to provide services through using the
+ * <code>addService()</code> method.
+ * <P>
+ *
+ * If for some reason it can no longer provide services for a particular
+ * class, this class must invoke
+ * <code>BeanContextServices.revokeService(serviceClass,this,true)</code>
+ * for all the places it has registered the service.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServiceProvider {
+ /**
+ * Get a service.
+ * Called from <code>BeanContextServices.getService()</code>.
+ *
+ * <p>If the requested service class is not available, or if this
+ * <code>BeanContextServiceProvider</code> chooses not honor the
+ * request for some reason, then this method will return
+ * <code>null</code>.</p>
+ *
+ * This method may throw unchecked exceptions, so watch out.
+ *
+ * @param services the <code>BeanContextServices</code> that wants
+ * to get the service. Only weak references to this will
+ * be retained, and it will never be changed, only queried
+ * in a read-only manner.
+ * @param requestor the actual requestor of the service. Only
+ * weak references to this will be retained, and it will
+ * never be changed, only queried in a read-only manner.
+ * @param serviceClass the <code>Class</code> of the service being
+ * requested.
+ * @param serviceSelector a parameter to customize the service
+ * returned with.
+ * @return an instance of <code>serviceClass</code> (such that
+ * <code>instanceof</code> serviceClass is true), or
+ * <code>null</code>.
+ * @see java.beans.beancontext.BeanContextServices#getService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Class,java.lang.Object,java.beans.beancontext.BeanContextServiceRevokedListener)
+ */
+ Object getService(BeanContextServices services, Object requestor, Class serviceClass, Object serviceSelector);
+
+ /**
+ * Release the service.
+ * <P>
+ *
+ * Called by <code>BeanContextServices.releaseService()</code>.
+ * <P>
+ *
+ * Most <code>BeanContextServiceProvider</code>s won't have to do
+ * anything here.
+ *
+ * @param services the <code>BeanContextServices</code> that wants
+ * to release the service. Only weak references to this will
+ * be retained, and it will never be changed, only queried
+ * in a read-only manner.
+ * @param requestor the original requestor of the service.
+ * @param service the service to relinquish
+ * @see java.beans.beancontext.BeanContextServices#releaseService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Object)
+ */
+ void releaseService(BeanContextServices services, Object requestor, Object service);
+
+ /**
+ * Get a list of valid service selectors for the specified service class.
+ * This method is called from
+ * <code>BeanContextServices.getCurrentServiceSelectors()</code>.
+ * <P>
+ *
+ * If the specified service class does not have a finite number of
+ * valid service selectors, it should return <code>null</code>.
+ * If it takes a general <code>Integer</code> parameter, for
+ * example, you may as well return <code>null</code> or the poor
+ * soul who called this method will be iterating all day.
+ * <P>
+ *
+ * If it has no valid service selectors, it should still return an empty
+ * <code>Iterator</code>.
+ *
+ * @param services the <code>BeanContextServices</code> that wants
+ * to get the service selectors. Only weak references to this will
+ * be retained, and it will never be changed, only queried
+ * in a read-only manner.
+ * @param serviceClass the service class to get selectors for.
+ * @return a list of valid service selectors for the service
+ * class, or <code>null</code>.
+ * @see java.beans.beancontext.BeanContextServices#getCurrentServiceSelectors(java.lang.Class)
+ */
+ Iterator getCurrentServiceSelectors(BeanContextServices services, Class serviceClass);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java
new file mode 100644
index 000000000..78bfc200d
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceProviderBeanInfo.java
@@ -0,0 +1,60 @@
+/* java.beans.beancontext.BeanContextServiceProviderBeanInfo
+ Copyright (C) 1999 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.BeanInfo;
+
+/**
+ * <code>BeanContextServiceProvider</code>s implement this to provide information about all of the services they provide.
+ * <P>
+ *
+ * This is apparently so that you can import a bunch of services into a
+ * RAD tool and it will know about all of them and export them to the
+ * user in a readable manner.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+public interface BeanContextServiceProviderBeanInfo extends BeanInfo {
+ /**
+ * Get <code>BeanInfo</code>s for all of the service classes of this <code>BeanInfoServiceProvider</code>.
+ * @return <code>BeanInfo</code>s for all provided service classes.
+ */
+ BeanInfo[] getServicesBeanInfo();
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedEvent.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedEvent.java
new file mode 100644
index 000000000..b4f2fa856
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedEvent.java
@@ -0,0 +1,112 @@
+/* java.beans.beancontext.BeanContextServiceRevokedEvent
+ Copyright (C) 1999, 2000 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;
+
+/**
+ * Event fired when services are revoked from a <code>BeanContextServices</code>.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ * @see java.beans.beancontext.BeanContextServiceRevokedListener
+ */
+
+public class BeanContextServiceRevokedEvent extends BeanContextEvent {
+ private static final long serialVersionUID = -1295543154724961754L;
+
+ /**
+ * The <code>Class</code> representing the service which is now
+ * available.
+ */
+ protected Class serviceClass;
+ private boolean invalidateRefs;
+
+ /**
+ * Create a new service revoked event.
+ * @param services the <code>BeanContextServices</code> through
+ * which the service was available. This is also the source
+ * of the event.
+ * @param serviceClass the service class that is now revoked.
+ * @param revokeNow whether the revocation is immediate for all
+ * classes or just a suggestion.
+ */
+ public BeanContextServiceRevokedEvent(BeanContextServices services, Class serviceClass, boolean revokeNow) {
+ super(services);
+ this.serviceClass = serviceClass;
+ invalidateRefs = revokeNow;
+ }
+
+ /**
+ * Get the revoked service class.
+ * @return the service class.
+ */
+ public Class getServiceClass() {
+ return serviceClass;
+ }
+
+ /**
+ * Tell whether the revoked service class is the same as the specified class.
+ * Identical to <code>getServiceClass().equals(c)</code>.
+ * @param c the class to compare.
+ * @return whether the clases are equal.
+ */
+ public boolean isServiceClass(Class c) {
+ return serviceClass.equals(c);
+ }
+
+ /**
+ * Get the <code>BeanContextServices</code> through which the service was available.
+ * @return the <code>BeanContextServices</code> through which the
+ * service was available.
+ */
+ public BeanContextServices getSourceAsBeanContextServices() {
+ return (BeanContextServices)getSource();
+ }
+
+ /**
+ * Tell whether current instances of the revoked service are usable or not.
+ * This is determined by whether the service was revoked
+ * immediately.
+ *
+ * @return whether current instances of the revoked service are
+ * usable.
+ */
+ public boolean isCurrentServiceInvalidNow() {
+ return invalidateRefs;
+ }
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedListener.java b/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedListener.java
new file mode 100644
index 000000000..11b83dd65
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServiceRevokedListener.java
@@ -0,0 +1,62 @@
+/* java.beans.beancontext.BeanContextServiceRevokedListener
+ Copyright (C) 1999 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.util.EventListener;
+
+/**
+ * Listens for service revoke events.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServiceRevokedListener extends EventListener {
+ /**
+ * Called by <code>BeanContextServices.revokeService()</code> to indicate that a service has been revoked.
+ * If you have a reference to such a service, it should be
+ * discarded and may no longer function properly.
+ * <code>getService()</code> will no longer work on the specified
+ * service class after this event has been fired.
+ *
+ * @param event the service revoked event.
+ * @see java.beans.beancontext.BeanContextServices#revokeService(java.lang.Class,java.beans.beancontext.BeanContextServiceProvider,boolean)
+ */
+ void serviceRevoked(BeanContextServiceRevokedEvent event);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServices.java b/libjava/classpath/java/beans/beancontext/BeanContextServices.java
new file mode 100644
index 000000000..787618ad5
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServices.java
@@ -0,0 +1,216 @@
+/* java.beans.beancontext.BeanContextServices
+ Copyright (C) 1999 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.util.Iterator;
+import java.util.TooManyListenersException;
+
+/**
+ * Allows a <code>BeanContext</code> to provide services to its children.
+ *
+ * @specnote it is unclear whether a <code>BeanContextServices</code>
+ * should delegate unhandled requests to parents. I assume so.
+ * @author John Keiser
+ * @since 1.2
+ */
+
+public interface BeanContextServices
+ extends BeanContext, BeanContextServicesListener
+{
+ /**
+ * Register a service to make it available to others.
+ * This class may refuse to add the service based on whatever
+ * information it can gather, including whether the service
+ * provider is trusted.
+ *
+ * @param serviceClass the service class.
+ * @param provider the factory that will actually provide the service.
+ * @return whether the service was added or not.
+ */
+ boolean addService (Class serviceClass,
+ BeanContextServiceProvider provider);
+
+ /**
+ * Make it so that no one else can use this service.
+ * <P>
+ *
+ * If <code>revokeNow</code> is <code>false</code>, the only
+ * effect of this method is to make all subsequent calls to
+ * <code>getService()</code> on this service class fail.
+ * <P>
+ *
+ * If it is <code>true</code>, a message is also sent out to all
+ * listeners on the service and all references to it are released.
+ *
+ * @param serviceClass the service class to revoke.
+ * @param provider the service provider providing the service class.
+ * @param revokeNow whether to release all current references to
+ * the service.
+ */
+ void revokeService (Class serviceClass,
+ BeanContextServiceProvider provider,
+ boolean revokeNow);
+
+ /**
+ * Release your copy of this service.
+ * <P>
+ *
+ * If all copies of the service's class have been relinquished by
+ * the requestor, the <code>BeanContextServiceRevokedListener</code>
+ * previously registered by <code>getService()</code> will be
+ * unregistered.
+ *
+ * @param requestorChild the original <code>BeanContextChild</code>
+ * requesting the service.
+ * @param requestor the original requestor of the service.
+ * @param service the service to relinquish
+ * @see #getService(java.beans.beancontext.BeanContextChild,java.lang.Object,java.lang.Class,java.lang.Object,java.beans.beancontext.BeanContextServiceRevokedListener)
+ */
+ void releaseService (BeanContextChild requestorChild, Object requestor,
+ Object service);
+
+ /**
+ * Get a service from this <code>BeanContextServices</code>.
+ * <P>
+ *
+ * The specified listener will be registered to receive a
+ * revocation notice for the specified serviceClass. One
+ * notification per service class per requestor object will be
+ * sent.
+ * <P>
+ *
+ * The listener will be unregistered when all services that were
+ * obtained by that requestor for that service class are released.
+ * <P>
+ *
+ * If the requested service class is not available, or if this
+ * <code>BeanContextServices</code> object chooses not honor the
+ * request because the service class has been revoked or for some
+ * other reason, then this method will return <code>null</code>.
+ * <P>
+ *
+ * This method may throw unchecked exceptions, so watch out.
+ *
+ * @specnote it is not specified what happens when two subsequent
+ * calls are made to <code>getService()</code> with the
+ * same requestor object and service class but different
+ * listeners. Which listener is to be notified?
+ *
+ * @param requestorChild the <code>BeanContextChild</code>
+ * associated with the requestor. Typically this will be
+ * the same as the requestor itself, but since any
+ * <code>Object</code>, even one outside the hierarchy, may
+ * make a request, this parameter is necessary. Only weak
+ * references to this will be retained, and it will never
+ * be changed, only queried in a read-only manner.
+ * @param requestor the actual requestor of the service. Only
+ * weak references to this will be retained, and it will
+ * never be changed, only queried in a read-only manner.
+ * @param serviceClass the <code>Class</code> of the service being
+ * requested.
+ * @param serviceSelector a parameter to customize the service
+ * returned with.
+ * @param listener a listener that will be notified if the service
+ * being requested is revoked.
+ * @return an instance of <code>serviceClass</code> (such that
+ * <code>instanceof</code> serviceClass is true), or
+ * <code>null</code>.
+ */
+ Object getService (BeanContextChild requestorChild, Object requestor,
+ Class serviceClass, Object serviceSelector,
+ BeanContextServiceRevokedListener listener)
+ throws TooManyListenersException;
+
+ /**
+ * Get a list of all service classes supported.
+ * <P>
+ *
+ * This method must synchronize on
+ * <code>BeanContext.globalHierarchyLock</code>.
+ *
+ * @return a list of all service classes supported.
+ * @see java.beans.beancontext.BeanContext#globalHierarchyLock
+ */
+ Iterator getCurrentServiceClasses ();
+
+ /**
+ * Get a list of valid service selectors for the specified service class.
+ * <P>
+ *
+ * If the specified service class does not have a finite number of
+ * valid service selectors, it should return <code>null</code>.
+ * If it takes a general <code>Integer</code> parameter, for
+ * example, you may as well return <code>null</code> or the poor
+ * soul who called this method will be iterating all day.
+ * <P>
+ *
+ * If it has no valid service selectors, it should still return an empty
+ * <code>Iterator</code>.
+ *
+ * @param serviceClass the service class to get selectors for.
+ * @return a list of valid service selectors for the service
+ * class, or <code>null</code>.
+ */
+ Iterator getCurrentServiceSelectors (Class serviceClass);
+
+ /**
+ * Tell whether the specified service class is available.
+ * Iff getService() could return a non-null value for the
+ * specified service, this method will return <code>true</code>.
+ *
+ * @param serviceClass the service class to check on.
+ * @return whether the specified service class is available.
+ */
+ boolean hasService (Class serviceClass);
+
+ /**
+ * Add a listener on all adds and removes of services.
+ * @param listener the listener to add.
+ */
+ void addBeanContextServicesListener (BeanContextServicesListener listener);
+
+ /**
+ * Remove a listener on all adds and removes of services.
+ * @specnote it is not certain whether this should remove this
+ * listener if it was specified in
+ * <code>getService()</code>.
+ * @param listener the listener to add.
+ */
+ void removeBeanContextServicesListener (BeanContextServicesListener listener);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServicesListener.java b/libjava/classpath/java/beans/beancontext/BeanContextServicesListener.java
new file mode 100644
index 000000000..2081080dd
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServicesListener.java
@@ -0,0 +1,56 @@
+/* java.beans.beancontext.BeanContextServicesListener
+ Copyright (C) 1999 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;
+
+/**
+ * Listens for service add and revoke events.
+ *
+ * @author John Keiser
+ * @since JDK1.2
+ */
+
+public interface BeanContextServicesListener extends BeanContextServiceRevokedListener {
+ /**
+ * Called by <code>BeanContextServices</code> whenever a service is made available.
+ *
+ * @param event the service revoked event, with useful information
+ * about the new service.
+ */
+ void serviceAvailable(BeanContextServiceAvailableEvent event);
+}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java b/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java
new file mode 100644
index 000000000..30b4a6fbd
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java
@@ -0,0 +1,896 @@
+/* BeanContextServicesSupport.java --
+ Copyright (C) 2003, 2005 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.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TooManyListenersException;
+
+/**
+ * This is a helper class for implementing a bean context which
+ * supplies services. 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 BeanContextServicesSupport
+ extends BeanContextSupport
+ implements BeanContextServices
+{
+ private static final long serialVersionUID = -8494482757288719206L;
+
+ protected class BCSSChild
+ extends BeanContextSupport.BCSChild
+ {
+ private static final long serialVersionUID = -3263851306889194873L;
+
+ BCSSChild(Object targetChild, Object peer)
+ {
+ super(targetChild, peer);
+ }
+ }
+
+ protected class BCSSProxyServiceProvider
+ implements BeanContextServiceProvider,
+ BeanContextServiceRevokedListener
+ {
+ private static final long serialVersionUID = 7078212910685744490L;
+
+ private BeanContextServiceProvider provider;
+
+ BCSSProxyServiceProvider(BeanContextServiceProvider p)
+ {
+ provider = p;
+ }
+
+ public Iterator getCurrentServiceSelectors (BeanContextServices bcs,
+ Class serviceClass)
+ {
+ return provider.getCurrentServiceSelectors(bcs, serviceClass);
+ }
+
+ public Object getService (BeanContextServices bcs,
+ Object requestor,
+ Class serviceClass,
+ Object serviceSelector)
+ {
+ return provider.getService(bcs, requestor, serviceClass,
+ serviceSelector);
+ }
+
+ public void releaseService (BeanContextServices bcs,
+ Object requestor,
+ Object service)
+ {
+ provider.releaseService(bcs, requestor, service);
+ }
+
+ public void serviceRevoked (BeanContextServiceRevokedEvent bcsre)
+ {
+ if (provider instanceof BeanContextServiceRevokedListener)
+ ((BeanContextServiceRevokedListener) provider).serviceRevoked(bcsre);
+ }
+ }
+
+ protected static class BCSSServiceProvider
+ implements Serializable
+ {
+ private static final long serialVersionUID = 861278251667444782L;
+
+ protected BeanContextServiceProvider serviceProvider;
+
+ private Class serviceClass;
+
+ private BCSSServiceProvider(Class serviceClass,
+ BeanContextServiceProvider provider)
+ {
+ this.serviceClass = serviceClass;
+ serviceProvider = provider;
+ }
+
+ protected BeanContextServiceProvider getServiceProvider()
+ {
+ return serviceProvider;
+ }
+
+ private Class getServiceClass()
+ {
+ return serviceClass;
+ }
+
+ }
+
+ /**
+ * Represents a request for a service. This is
+ * a common superclass used by the classes which maintain
+ * the listener-requestor and service-requestor relationships.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static abstract class Request
+ {
+ private Object requestor;
+
+ public Request(Object requestor)
+ {
+ this.requestor = requestor;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof Request)
+ {
+ Request req = (Request) obj;
+ return req.getRequestor().equals(requestor);
+ }
+ return false;
+ }
+
+ public Object getRequestor()
+ {
+ return requestor;
+ }
+
+ }
+
+ /**
+ * Represents a relationship between a service requestor
+ * and a revocation listener.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class ServiceRequest
+ extends Request
+ {
+
+ private BeanContextServiceRevokedListener listener;
+
+ public ServiceRequest(Object requestor,
+ BeanContextServiceRevokedListener listener)
+ {
+ super(requestor);
+ this.listener = listener;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof ServiceRequest)
+ {
+ ServiceRequest sr = (ServiceRequest) obj;
+ return (super.equals(obj) &&
+ sr.getListener().equals(listener));
+ }
+ return false;
+ }
+
+ public BeanContextServiceRevokedListener getListener()
+ {
+ return listener;
+ }
+ }
+
+ /**
+ * Represents a relationship between a service requestor
+ * and a service instance.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class ServiceLease
+ extends Request
+ {
+
+ private Object service;
+
+ public ServiceLease(Object requestor, Object service)
+ {
+ super(requestor);
+ this.service = service;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof ServiceLease)
+ {
+ ServiceLease sl = (ServiceLease) obj;
+ return (super.equals(obj) &&
+ sl.getService().equals(service));
+ }
+ return false;
+ }
+
+ public Object getService()
+ {
+ return service;
+ }
+ }
+
+ /**
+ * A collection of listeners who receive availability
+ * and revocation notifications.
+ */
+ protected transient ArrayList bcsListeners;
+
+ protected transient BCSSProxyServiceProvider proxy;
+
+ /**
+ * The number of serializable service providers.
+ */
+ protected transient int serializable;
+
+ /**
+ * A map of registered services, linking the service
+ * class to its associated {@link BCSSServiceProvider}.
+ */
+ protected transient HashMap services;
+
+ /**
+ * A map of children to a list of services they
+ * have obtained.
+ */
+ private transient HashMap serviceUsers;
+
+ /**
+ * A map of services to {@link ServiceRequest}s.
+ */
+ private transient HashMap serviceRequests;
+
+ /**
+ * A map of {@link ServiceLease}s to providers.
+ */
+ private transient HashMap serviceLeases;
+
+ /**
+ * Construct a {@link BeanContextServicesSupport} instance.
+ */
+ public BeanContextServicesSupport ()
+ {
+ super();
+ }
+
+ /**
+ * Construct a {@link BeanContextServicesSupport} instance.
+ *
+ * @param peer the bean context services peer (<code>null</code> permitted).
+ */
+ public BeanContextServicesSupport (BeanContextServices peer)
+ {
+ super(peer);
+ }
+
+ /**
+ * Construct a {@link BeanContextServicesSupport} 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 BeanContextServicesSupport(BeanContextServices peer, Locale locale)
+ {
+ super(peer, locale);
+ }
+
+ /**
+ * Construct a {@link BeanContextServicesSupport} 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 BeanContextServicesSupport(BeanContextServices peer, Locale locale,
+ boolean dtime)
+ {
+ super(peer, locale, dtime);
+ }
+
+ /**
+ * Construct a {@link BeanContextServicesSupport} 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 BeanContextServicesSupport(BeanContextServices peer, Locale locale,
+ boolean dtime, boolean visible)
+ {
+ super(peer, locale, dtime, visible);
+ }
+
+ /**
+ * Adds a new listener for service availability and
+ * revocation events.
+ *
+ * @param listener the listener to add.
+ */
+ public void addBeanContextServicesListener
+ (BeanContextServicesListener listener)
+ {
+ synchronized (bcsListeners)
+ {
+ if (! bcsListeners.contains(listener))
+ bcsListeners.add(listener);
+ }
+ }
+
+ /**
+ * Registers a new service from the specified service provider.
+ * The service is internally associated with the service provider
+ * and a <code>BeanContextServiceAvailableEvent</code> is fired. If
+ * the service is already registered, then this method instead
+ * returns <code>false</code>. This is equivalent to calling
+ * <code>addService(serviceClass, bcsp, true)</code>.
+ *
+ * @param serviceClass the class of the service to be registered.
+ * @param bcsp the provider of the given service.
+ * @return true if the service was registered successfully.
+ * @see #addService(Class, BeanContextServiceProvider, boolean)
+ */
+ public boolean addService (Class serviceClass,
+ BeanContextServiceProvider bcsp)
+ {
+ return addService(serviceClass, bcsp, true);
+ }
+
+ /**
+ * Registers a new service from the specified service provider.
+ * The service is internally associated with the service provider
+ * and (if <code>fireEvent</code> is true) a
+ * <code>BeanContextServiceAvailableEvent</code> is fired. If
+ * the service is already registered, then this method instead
+ * returns <code>false</code>.
+ *
+ * @param serviceClass the class of the service to be registered.
+ * @param bcsp the provider of the given service.
+ * @param fireEvent true if a service availability event should
+ * be fired.
+ * @return true if the service was registered successfully.
+ */
+ protected boolean addService (Class serviceClass,
+ BeanContextServiceProvider bcsp,
+ boolean fireEvent)
+ {
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ if (services.containsKey(serviceClass))
+ return false;
+ services.put(serviceClass,
+ createBCSSServiceProvider(serviceClass, bcsp));
+ if (bcsp instanceof Serializable)
+ ++serializable;
+ if (fireEvent)
+ fireServiceAdded(serviceClass);
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Deserializes any service providers which are serializable. This
+ * method is called by the <code>readObject</code> method of
+ * {@link BeanContextSupport} prior to deserialization of the children.
+ * Subclasses may envelope its behaviour in order to read further
+ * serialized data to the stream.
+ *
+ * @param ois the stream from which data is being deserialized.
+ * @throws IOException if an I/O error occurs.
+ * @throws ClassNotFoundException if the class of a deserialized object
+ * can not be found.
+ */
+ protected void bcsPreDeserializationHook (ObjectInputStream ois)
+ throws ClassNotFoundException, IOException
+ {
+ serializable = ois.readInt();
+ for (int a = 0; a < serializable; ++a)
+ {
+ BCSSServiceProvider bcsssp = (BCSSServiceProvider) ois.readObject();
+ addService(bcsssp.getServiceClass(), bcsssp.getServiceProvider());
+ }
+ }
+
+ /**
+ * Serializes any service providers which are serializable. This
+ * method is called by the <code>writeObject</code> method of
+ * {@link BeanContextSupport} prior to serialization of the children.
+ * Subclasses may envelope its behaviour in order to add further
+ * serialized data to the stream.
+ *
+ * @param oos the stream to which data is being serialized.
+ * @throws IOException if an I/O error occurs.
+ */
+ protected void bcsPreSerializationHook (ObjectOutputStream oos)
+ throws IOException
+ {
+ oos.writeInt(serializable);
+ synchronized (services)
+ {
+ Iterator i = services.values().iterator();
+ while (i.hasNext())
+ {
+ BCSSServiceProvider bcsssp = (BCSSServiceProvider) i.next();
+ if (bcsssp.getServiceProvider() instanceof Serializable)
+ oos.writeObject(bcsssp);
+ }
+ }
+ }
+
+ /**
+ * Revokes any services used by a child that has just been removed.
+ * The superclass ({@link BeanContextSupport}) calls this method
+ * when a child has just been successfully removed. Subclasses can
+ * extend this method in order to perform additional operations
+ * on child removal.
+ *
+ * @param child the child being removed.
+ * @param bcsc the support object for the child.
+ */
+ protected void childJustRemovedHook (Object child,
+ BeanContextSupport.BCSChild bcsc)
+ {
+ if (child instanceof BeanContextChild)
+ {
+ BeanContextChild bcchild = (BeanContextChild) child;
+ Iterator childServices = ((List) serviceUsers.get(bcchild)).iterator();
+ while (childServices.hasNext())
+ releaseService(bcchild, this, childServices.next());
+ serviceUsers.remove(bcchild);
+ }
+ }
+
+ /**
+ * Overrides the {@link BeanContextSupport#createBCSChild} method
+ * so as to use a {@link BCSSChild} instead.
+ *
+ * @param targetChild the child to create the child for.
+ * @param peer the peer which relates to the child if a proxy is used.
+ * @return a new instance of {@link BCSSChild}.
+ */
+ protected BeanContextSupport.BCSChild createBCSChild (Object targetChild,
+ Object peer)
+ {
+ return new BCSSChild(targetChild, peer);
+ }
+
+ /**
+ * Provides a hook so that subclasses can replace the
+ * {@link BCSSServiceProvider} class, used to store registered
+ * service providers, with a subclass without replacing the
+ * {@link #addService(Class, BeanContextServiceProvider)} method.
+ *
+ * @param sc the class of service being registered.
+ * @param bcsp the provider of the service.
+ * @return a instance of {@link BCSSServiceProvider} wrapping the provider.
+ */
+ protected BeanContextServicesSupport.BCSSServiceProvider
+ createBCSSServiceProvider (Class sc, BeanContextServiceProvider bcsp)
+ {
+ return new BCSSServiceProvider(sc, bcsp);
+ }
+
+ /**
+ * Sends a <code>BeanContextServiceAvailableEvent</code> to all
+ * registered listeners.
+ *
+ * @param bcssae the event to send.
+ */
+ protected final void fireServiceAdded (BeanContextServiceAvailableEvent bcssae)
+ {
+ synchronized (bcsListeners)
+ {
+ int size = bcsListeners.size();
+ for (int i = 0; i < size; ++i)
+ {
+ BeanContextServicesListener bcsl
+ = (BeanContextServicesListener) bcsListeners.get(i);
+ bcsl.serviceAvailable(bcssae);
+ }
+ }
+ }
+
+ /**
+ * Sends a <code>BeanContextServiceAvailableEvent</code> to all
+ * registered listeners.
+ *
+ * @param serviceClass the service that is now available.
+ * @see #fireServiceAdded(BeanContextServiceAvailableEvent)
+ */
+ protected final void fireServiceAdded (Class serviceClass)
+ {
+ fireServiceAdded(new BeanContextServiceAvailableEvent(this,
+ serviceClass));
+ }
+
+ /**
+ * Sends a <code>BeanContextServiceRevokedEvent</code> to all
+ * registered listeners.
+ *
+ * @param event the event to send.
+ */
+ protected final void fireServiceRevoked(BeanContextServiceRevokedEvent event)
+ {
+ synchronized (bcsListeners)
+ {
+ int size = bcsListeners.size();
+ for (int i = 0; i < size; ++i)
+ {
+ BeanContextServicesListener bcsl
+ = (BeanContextServicesListener) bcsListeners.get(i);
+ bcsl.serviceRevoked(event);
+ }
+ List requests = (List) serviceRequests.get(event.getServiceClass());
+ if (requests != null)
+ {
+ Iterator i = requests.iterator();
+ while (i.hasNext())
+ {
+ ServiceRequest r = (ServiceRequest) i.next();
+ r.getListener().serviceRevoked(event);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sends a <code>BeanContextServiceRevokedEvent</code> to all
+ * registered listeners.
+ *
+ * @param serviceClass the service that has been revoked.
+ * @see #fireServiceRevoked(BeanContextServiceRevokedEvent)
+ */
+ protected final void fireServiceRevoked (Class serviceClass,
+ boolean revokeNow)
+ {
+ fireServiceRevoked(new BeanContextServiceRevokedEvent(this, serviceClass,
+ revokeNow));
+ }
+
+ /**
+ * Returns the services peer given at construction time,
+ * or <code>null</code> if no peer was given.
+ *
+ * @return the {@link BeanContextServices} peer.
+ */
+ public BeanContextServices getBeanContextServicesPeer ()
+ {
+ return (BeanContextServices) beanContextChildPeer;
+ }
+
+ /**
+ * Returns <code>child</code> as an instance of
+ * {@link BeanContextServicesListener}, 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 BeanContextServicesListener}.
+ */
+ protected static final BeanContextServicesListener
+ getChildBeanContextServicesListener(Object child)
+ {
+ if (child instanceof BeanContextServicesListener)
+ return (BeanContextServicesListener) child;
+ else
+ return null;
+ }
+
+ /**
+ * Returns an iterator over the currently available
+ * services.
+ *
+ * @return an iterator over the currently available services.
+ */
+ public Iterator getCurrentServiceClasses ()
+ {
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ return services.keySet().iterator();
+ }
+ }
+ }
+
+ /**
+ * Returns an iterator over the service selectors of the service
+ * provider for the given service. The iterator is actually
+ * obtained by calling the
+ * {@link BeanContextServiceProvider#getCurrentServiceSelectors}
+ * of the provider itself. If the specified service is not available,
+ * <code>null</code> is returned.
+ *
+ * @param serviceClass the service whose provider's selectors should
+ * be iterated over.
+ * @return an {@link Iterator} over the service selectors of the
+ * provider of the given service.
+ */
+ public Iterator getCurrentServiceSelectors (Class serviceClass)
+ {
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ BeanContextServiceProvider bcsp
+ = ((BCSSServiceProvider)
+ services.get(serviceClass)).getServiceProvider();
+ if (bcsp == null)
+ return null;
+ else
+ return bcsp.getCurrentServiceSelectors(this, serviceClass);
+ }
+ }
+ }
+
+ /**
+ * Retrieves the specified service. If a provider for the service
+ * is registered in this context, then the request is passed on to
+ * the provider and the service returned. Otherwise, the request
+ * is delegated to a parent {@link BeanContextServices}, if possible.
+ * If the service can not be found at all, then <code>null</code>
+ * is returned.
+ *
+ * @param child the child obtaining the reference.
+ * @param requestor the requestor of the service, which may be the
+ * child itself.
+ * @param serviceClass the service being requested.
+ * @param serviceSelector an additional service-dependent parameter
+ * (may be <code>null</code> if not appropriate).
+ * @param bcsrl a listener used to notify the requestor that the service
+ * has since been revoked.
+ * @return a reference to the service requested, or <code>null</code>.
+ * @throws TooManyListenersException according to Sun's documentation.
+ */
+ public Object getService (BeanContextChild child, Object requestor,
+ Class serviceClass, Object serviceSelector,
+ BeanContextServiceRevokedListener bcsrl)
+ throws TooManyListenersException
+ {
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ Object service;
+ BeanContextServiceProvider provider = ((BCSSServiceProvider)
+ services.get(serviceClass)).getServiceProvider();
+ if (provider != null)
+ {
+ service = provider.getService(this, requestor, serviceClass,
+ serviceSelector);
+ List childServices = (List) serviceUsers.get(child);
+ if (childServices == null)
+ {
+ childServices = new ArrayList();
+ serviceUsers.put(child, childServices);
+ }
+ childServices.add(serviceClass);
+ }
+ else
+ {
+ BeanContextServices peer = getBeanContextServicesPeer();
+ if (peer != null)
+ service = peer.getService(child, requestor, serviceClass,
+ serviceSelector, bcsrl);
+ else
+ service = null;
+ }
+ if (service != null)
+ {
+ ServiceRequest request = new ServiceRequest(requestor, bcsrl);
+ Set requests = (Set) serviceRequests.get(serviceClass);
+ if (requests == null)
+ {
+ requests = new HashSet();
+ serviceRequests.put(serviceClass, requests);
+ }
+ requests.add(request);
+ ServiceLease lease = new ServiceLease(requestor, service);
+ serviceLeases.put(lease, provider);
+ }
+ return service;
+ }
+ }
+ }
+
+ /**
+ * Returns true if the specified service is available.
+ *
+ * @param serviceClass the service to check for.
+ * @return true if the service is available.
+ */
+ public boolean hasService (Class serviceClass)
+ {
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ return services.containsKey(serviceClass);
+ }
+ }
+ }
+
+ public void initialize ()
+ {
+ super.initialize();
+
+ bcsListeners = new ArrayList();
+ services = new HashMap();
+ serviceUsers = new HashMap();
+ serviceRequests = new HashMap();
+ serviceLeases = new HashMap();
+ }
+
+ /**
+ * Subclasses may override this method to allocate resources
+ * from the nesting bean context.
+ */
+ protected void initializeBeanContextResources()
+ {
+ /* Purposefully left empty */
+ }
+
+ /**
+ * Relinquishes any resources obtained from the parent context.
+ * Specifically, those services obtained from the parent are revoked.
+ * Subclasses may override this method to deallocate resources
+ * from the nesting bean context.
+ */
+ protected void releaseBeanContextResources()
+ {
+ /* Purposefully left empty */
+ }
+
+ /**
+ * Releases the reference to a service held by a
+ * {@link BeanContextChild} (or an arbitrary object associated
+ * with it). It simply calls the appropriate method on the
+ * underlying provider.
+ *
+ * @param child the child who holds the reference.
+ * @param requestor the object that requested the reference.
+ * @param service the service being released.
+ */
+ public void releaseService (BeanContextChild child, Object requestor,
+ Object service)
+ {
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ ServiceLease lease = new ServiceLease(requestor, service);
+ BeanContextServiceProvider provider = (BeanContextServiceProvider)
+ serviceLeases.get(lease);
+ if (provider != null)
+ provider.releaseService(this, requestor, service);
+ else
+ {
+ BeanContextServices peer = getBeanContextServicesPeer();
+ if (peer != null)
+ peer.releaseService(child, requestor, service);
+ }
+ serviceLeases.remove(lease);
+ }
+ }
+ }
+
+ public void removeBeanContextServicesListener
+ (BeanContextServicesListener listener)
+ {
+ synchronized (bcsListeners)
+ {
+ bcsListeners.remove(listener);
+ }
+ }
+
+ /**
+ * Revokes the given service. A {@link BeanContextServiceRevokedEvent} is
+ * emitted to all registered {@link BeanContextServiceRevokedListener}s
+ * and {@link BeanContextServiceListener}s. If <code>revokeCurrentServicesNow</code>
+ * is true, termination of the service is immediate. Otherwise, prior
+ * acquisitions of the service by requestors remain valid.
+ *
+ * @param serviceClass the service to revoke.
+ * @param bcsp the provider of the revoked service.
+ * @param revokeCurrentServicesNow true if this is an exceptional circumstance
+ * where service should be immediately revoked.
+ */
+ public void revokeService (Class serviceClass, BeanContextServiceProvider bcsp,
+ boolean revokeCurrentServicesNow)
+ {
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
+ services.remove(serviceClass);
+ if (bcsp instanceof Serializable)
+ --serializable;
+ }
+ }
+ }
+
+ public void serviceAvailable (BeanContextServiceAvailableEvent bcssae)
+ {
+ synchronized (services)
+ {
+ Class klass = bcssae.getServiceClass();
+ if (services.containsKey(klass))
+ return;
+ Iterator it = bcsChildren();
+ while (it.hasNext())
+ {
+ Object obj = it.next();
+ if (obj instanceof BeanContextServices)
+ ((BeanContextServices) obj).serviceAvailable(bcssae);
+ }
+ }
+ }
+
+ public void serviceRevoked (BeanContextServiceRevokedEvent bcssre)
+ {
+ synchronized (services)
+ {
+ Class klass = bcssre.getServiceClass();
+ if (services.containsKey(klass))
+ return;
+ Iterator it = bcsChildren();
+ while (it.hasNext())
+ {
+ Object obj = it.next();
+ if (obj instanceof BeanContextServices)
+ ((BeanContextServices) obj).serviceRevoked(bcssre);
+ }
+ }
+ }
+}
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());
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/beans/beancontext/package.html b/libjava/classpath/java/beans/beancontext/package.html
new file mode 100644
index 000000000..55e3bd723
--- /dev/null
+++ b/libjava/classpath/java/beans/beancontext/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.beans.beancontext package.
+ Copyright (C) 2002 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. -->
+
+<html>
+<head><title>GNU Classpath - java.beans.beancontext</title></head>
+
+<body>
+<p>Containers and execution environments for beans.</p>
+
+</body>
+</html>