diff options
Diffstat (limited to 'libjava/classpath/java/beans/beancontext')
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> |