You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by cs...@apache.org on 2006/04/26 17:22:52 UTC
svn commit: r397220 - in /beehive/trunk/controls:
src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/
test/src/junit-tests/org/apache/beehive/controls/test/junit/
Author: cschoett
Date: Wed Apr 26 08:22:50 2006
New Revision: 397220
URL: http://svn.apache.org/viewcvs?rev=397220&view=rev
Log:
Fixed a bug in handling BeanContext children which implement the BeanContextProxy interface. Only the Proxy was being added as a child instead of both the proxy and BCC it references.
Updated unit tests for this change.
Modified:
beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextServicesSupport.java
beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextSupport.java
beehive/trunk/controls/test/src/junit-tests/org/apache/beehive/controls/test/junit/ControlBeanContextSupportTest.java
Modified: beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextServicesSupport.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextServicesSupport.java?rev=397220&r1=397219&r2=397220&view=diff
==============================================================================
--- beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextServicesSupport.java (original)
+++ beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextServicesSupport.java Wed Apr 26 08:22:50 2006
@@ -258,6 +258,9 @@
ServiceProvider sp = _serviceProviders.get(serviceClass);
sp.removeChildReference(requestor);
+ // if this is a delegated service, delegate the release request
+ // delegated services are removed from the _serviceProviders table
+ // as soon as their reference count drops to zero
if (sp.isDelegated()) {
BeanContextServices bcs = (BeanContextServices) getBeanContext();
bcs.releaseService(this, requestor, service);
@@ -386,8 +389,8 @@
/**
* Initialize data structures.
*/
- protected void init() {
- super.init();
+ protected void initialize() {
+ super.initialize();
_serviceProviders = Collections.synchronizedMap(new HashMap<Class, ServiceProvider>());
_bcsListeners = Collections.synchronizedList(new ArrayList<BeanContextServicesListener>());
}
Modified: beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextSupport.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextSupport.java?rev=397220&r1=397219&r2=397220&view=diff
==============================================================================
--- beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextSupport.java (original)
+++ beehive/trunk/controls/src/runtime/org/apache/beehive/controls/runtime/bean/webcontext/ControlBeanContextSupport.java Wed Apr 26 08:22:50 2006
@@ -25,10 +25,10 @@
import java.beans.VetoableChangeListener;
import java.beans.Visibility;
import java.beans.beancontext.BeanContext;
-import java.beans.beancontext.BeanContextChild;
import java.beans.beancontext.BeanContextMembershipEvent;
import java.beans.beancontext.BeanContextMembershipListener;
import java.beans.beancontext.BeanContextProxy;
+import java.beans.beancontext.BeanContextChild;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
@@ -37,9 +37,10 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
/**
* BeanContext implementation for Beehive Controls.
@@ -49,8 +50,8 @@
private static final long serialVersionUID = 1L;
- private transient List _children;
- private transient HashSet<BeanContextMembershipListener> _bcMembershipListeners;
+ private transient Map<Object, BCChild> _children;
+ private transient List<BeanContextMembershipListener> _bcMembershipListeners;
private boolean _designTime = false;
private boolean _mayUseGui = false;
@@ -60,7 +61,7 @@
*/
public ControlBeanContextSupport() {
super();
- init();
+ initialize();
}
/**
@@ -68,9 +69,9 @@
*
* @param bcc
*/
- public ControlBeanContextSupport(BeanContextChild bcc) {
+ public ControlBeanContextSupport(java.beans.beancontext.BeanContextChild bcc) {
super(bcc);
- init();
+ initialize();
}
/**
@@ -88,7 +89,7 @@
* by the beanName parameter is not found
*/
public Object instantiateChild(String beanName) throws IOException, ClassNotFoundException {
- BeanContextChild bcc = getBCCDelegate();
+ java.beans.beancontext.BeanContextChild bcc = getBCCDelegate();
return Beans.instantiate(bcc.getClass().getClassLoader(), beanName, (BeanContext) bcc);
}
@@ -105,7 +106,7 @@
* be found.
* @throws IllegalArgumentException if the resource is not valid
*/
- public InputStream getResourceAsStream(String name, BeanContextChild bcc) throws IllegalArgumentException {
+ public InputStream getResourceAsStream(String name, java.beans.beancontext.BeanContextChild bcc) throws IllegalArgumentException {
// bcc must be a child of this context
if (!contains(bcc)) {
@@ -132,7 +133,7 @@
* resource for the specified child
* @throws IllegalArgumentException if the resource is not valid
*/
- public URL getResource(String name, BeanContextChild bcc) throws IllegalArgumentException {
+ public URL getResource(String name, java.beans.beancontext.BeanContextChild bcc) throws IllegalArgumentException {
// bcc must be a child of this context
if (!contains(bcc)) {
@@ -206,26 +207,21 @@
* collection does not support null elements (optional).
*/
public boolean contains(Object o) {
- return _children.contains(o);
+ return _children.containsKey(o);
}
/**
- * Returns an iterator over the elements in this collection. There are no
- * guarantees concerning the order in which the elements are returned
- * (unless this collection is an instance of some class that provides a
- * guarantee).
+ * Returns an iterator over the elements in this collection. The
+ * iterator's collection is non-modifiable.
*
* @return an <tt>Iterator</tt> over the elements in this collection
*/
public Iterator iterator() {
- return Collections.unmodifiableList(_children).iterator();
+ return Collections.unmodifiableSet(_children.keySet()).iterator();
}
/**
- * Returns an array containing all of the elements in this collection. If
- * the collection makes any guarantees as to what order its elements are
- * returned by its iterator, this method must return the elements in the
- * same order.<p>
+ * Returns an array containing all of the elements in this collection.
* <p/>
* The returned array will be "safe" in that no references to it are
* maintained by this collection. (In other words, this method must
@@ -238,7 +234,7 @@
* @return an array containing all of the elements in this collection
*/
public Object[] toArray() {
- return _children.toArray();
+ return _children.keySet().toArray();
}
/**
@@ -277,14 +273,20 @@
if (contains(o)) return false;
// todo: for multithreaded usage this block needs to be synchronized
- // spec says if the object being added implements BeanContextChild or BeanContextProxy
+ // spec: if the object being added implements BeanContextChild or BeanContextProxy
// need to set the bean context of the object to this bean context.
- BeanContextChild bcc = null;
+ java.beans.beancontext.BeanContextChild bcc = null;
+ BeanContextProxy bcp = null;
+
if (o instanceof BeanContextProxy) {
- bcc = ((BeanContextProxy) o).getBeanContextProxy();
+ if (o instanceof BeanContext) {
+ throw new IllegalArgumentException("May not implement both BeanContextProxy and BeanContext!!");
+ }
+ bcp = (BeanContextProxy)o;
+ bcc = bcp.getBeanContextProxy();
}
- else if (o instanceof BeanContextChild) {
- bcc = (BeanContextChild) o;
+ else if (o instanceof java.beans.beancontext.BeanContextChild) {
+ bcc = (java.beans.beancontext.BeanContextChild) o;
}
if (bcc != null) {
@@ -312,7 +314,12 @@
addBeanContextMembershipListener((BeanContextMembershipListener) o);
}
- _children.add(o);
+ if (bcp == null) {
+ _children.put(o, new BCChild(o));
+ } else {
+ _children.put(o, new BCChild(bcp, bcc, true));
+ _children.put(bcc, new BCChild(bcp, bcc, false));
+ }
BeanContextMembershipEvent bcme = new BeanContextMembershipEvent(this, new Object[]{o});
fireMembershipEvent(bcme, true);
@@ -344,27 +351,9 @@
}
/**
- * Adds all of the elements in the specified collection to this collection
- * (optional operation). The behavior of this operation is undefined if
- * the specified collection is modified while the operation is in progress.
- * (This implies that the behavior of this call is undefined if the
- * specified collection is this collection, and this collection is
- * nonempty.)
+ * Not supported.
*
- * @param c elements to be inserted into this collection.
- * @return <tt>true</tt> if this collection changed as a result of the
- * call
- * @throws UnsupportedOperationException if this collection does not
- * support the <tt>addAll</tt> method.
- * @throws ClassCastException if the class of an element of the specified
- * collection prevents it from being added to this collection.
- * @throws NullPointerException if the specified collection contains one
- * or more null elements and this collection does not support null
- * elements, or if the specified collection is <tt>null</tt>.
- * @throws IllegalArgumentException some aspect of an element of the
- * specified collection prevents it from being added to this
- * collection.
- * @see #add(Object)
+ * @throws UnsupportedOperationException
*/
public boolean addAll(Collection c) {
// NOOP : Not Supported
@@ -372,12 +361,9 @@
}
/**
- * Removes all of the elements from this collection (optional operation).
- * This collection will be empty after this method returns unless it
- * throws an exception.
+ * Not supported.
*
- * @throws UnsupportedOperationException if the <tt>clear</tt> method is
- * not supported by this collection.
+ * @throws UnsupportedOperationException
*/
public void clear() {
// NOOP: Not supported
@@ -385,26 +371,9 @@
}
/**
- * Retains only the elements in this collection that are contained in the
- * specified collection (optional operation). In other words, removes from
- * this collection all of its elements that are not contained in the
- * specified collection.
+ * Not supported.
*
- * @param c elements to be retained in this collection.
- * @return <tt>true</tt> if this collection changed as a result of the
- * call
- * @throws UnsupportedOperationException if the <tt>retainAll</tt> method
- * is not supported by this Collection.
- * @throws ClassCastException if the types of one or more elements
- * in this collection are incompatible with the specified
- * collection (optional).
- * @throws NullPointerException if this collection contains one or more
- * null elements and the specified collection does not support null
- * elements (optional).
- * @throws NullPointerException if the specified collection is
- * <tt>null</tt>.
- * @see #remove(Object)
- * @see #contains(Object)
+ * @throws UnsupportedOperationException
*/
public boolean retainAll(Collection c) {
// NOOP: Not supported
@@ -412,26 +381,9 @@
}
/**
- * Removes all this collection's elements that are also contained in the
- * specified collection (optional operation). After this call returns,
- * this collection will contain no elements in common with the specified
- * collection.
+ * Not supported.
*
- * @param c elements to be removed from this collection.
- * @return <tt>true</tt> if this collection changed as a result of the
- * call
- * @throws UnsupportedOperationException if the <tt>removeAll</tt> method
- * is not supported by this collection.
- * @throws ClassCastException if the types of one or more elements
- * in this collection are incompatible with the specified
- * collection (optional).
- * @throws NullPointerException if this collection contains one or more
- * null elements and the specified collection does not support
- * null elements (optional).
- * @throws NullPointerException if the specified collection is
- * <tt>null</tt>.
- * @see #remove(Object)
- * @see #contains(Object)
+ * @throws UnsupportedOperationException
*/
public boolean removeAll(Collection c) {
throw new UnsupportedOperationException();
@@ -455,7 +407,7 @@
* @see #contains(Object)
*/
public boolean containsAll(Collection c) {
- return _children.containsAll(c);
+ return _children.keySet().containsAll(c);
}
/**
@@ -502,7 +454,7 @@
* @throws NullPointerException if the specified array is <tt>null</tt>.
*/
public Object[] toArray(Object[] a) {
- return _children.toArray(a);
+ return _children.keySet().toArray(a);
}
/**
@@ -537,7 +489,6 @@
*
* @return the current "value" of the "designTime" property.
*/
-
public boolean isDesignTime() {
return _designTime;
}
@@ -549,13 +500,13 @@
* order to get its work done.
*/
public boolean needsGui() {
- BeanContextChild bcc = getBCCDelegate();
+ java.beans.beancontext.BeanContextChild bcc = getBCCDelegate();
if (bcc != this && bcc instanceof Visibility) {
return ((Visibility) bcc).needsGui();
}
// check children
- for (Object o : _children) {
+ for (Object o : _children.keySet()) {
if (o instanceof Visibility) {
if (((Visibility) o).needsGui()) {
return true;
@@ -573,7 +524,7 @@
_mayUseGui = false;
- for (Object o : _children) {
+ for (Object o : _children.keySet()) {
if (o instanceof Visibility) {
((Visibility) o).dontUseGui();
}
@@ -588,7 +539,7 @@
_mayUseGui = true;
- for (Object o : _children) {
+ for (Object o : _children.keySet()) {
if (o instanceof Visibility) {
((Visibility) o).okToUseGui();
}
@@ -646,9 +597,9 @@
/**
* Init this classes data structures.
*/
- protected void init() {
- _bcMembershipListeners = new HashSet<BeanContextMembershipListener>();
- _children = Collections.synchronizedList(new ArrayList<Object>());
+ protected void initialize() {
+ _bcMembershipListeners = new ArrayList<BeanContextMembershipListener>();
+ _children = Collections.synchronizedMap(new HashMap<Object, BCChild>());
}
/**
@@ -682,12 +633,14 @@
if (!contains(o)) return false;
// todo: for multithreaded usage this block needs to be synchronized
- BeanContextChild bcc = null;
+ java.beans.beancontext.BeanContextChild bcc = null;
+ BeanContextProxy bcp = null;
if (o instanceof BeanContextProxy) {
- bcc = ((BeanContextProxy) o).getBeanContextProxy();
+ bcp = (BeanContextProxy)o;
+ bcc = bcp.getBeanContextProxy();
}
else if (o instanceof BeanContextChild) {
- bcc = (BeanContextChild) o;
+ bcc = (java.beans.beancontext.BeanContextChild) o;
}
if (bcc != null) {
@@ -721,7 +674,18 @@
removeBeanContextMembershipListener((BeanContextMembershipListener) o);
}
- _children.remove(o);
+ if (bcp != null) {
+ // need to remove the peer as well
+ BCChild c = _children.get(bcp);
+ _children.remove(c.getChild());
+ _children.remove(o);
+ } else {
+ BCChild c = _children.get(o);
+ if (c.hasProxy()) {
+ _children.remove(c.getProxy());
+ }
+ _children.remove(o);
+ }
BeanContextMembershipEvent bcme = new BeanContextMembershipEvent(this, new Object[]{o});
fireMembershipEvent(bcme, false);
@@ -740,22 +704,24 @@
out.defaultWriteObject();
// spec: only write children if not using a delegate
- int serializable = 0;
- for (Object child : _children) {
- if (child instanceof Serializable) serializable++;
+ ArrayList<Object> serChildren = new ArrayList<Object>();
+ for (Object child : _children.keySet()) {
+ BCChild bcc = _children.get(child);
+ // only write children which do not have a proxy / or directly implement the BeanContextProxy interface
+ if ((!bcc.hasProxy() || bcc.hasProxy() && bcc.isProxy()) && bcc.isSerializable()) {
+ serChildren.add(child);
+ }
}
- out.writeInt(serializable);
+ out.writeInt(serChildren.size());
if (this.equals(getBCCDelegate())) {
- for (Object child : _children) {
- if (child instanceof Serializable) {
- out.writeObject(child);
- }
+ for (Object child : serChildren) {
+ out.writeObject(child);
}
}
// write event handlers
- serializable = 0;
+ int serializable = 0;
for (BeanContextMembershipListener listener : _bcMembershipListeners) {
if (listener instanceof Serializable) serializable++;
}
@@ -780,7 +746,7 @@
// todo: for multithreaded usage this block needs to be synchronized
in.defaultReadObject();
- init();
+ initialize();
int childCount = in.readInt();
for (int i = 0; i < childCount; i++) {
@@ -797,5 +763,86 @@
addBeanContextMembershipListener((BeanContextMembershipListener) in.readObject());
}
// end synchronized block
+ }
+
+ /**
+ * A child of this BeanContext. This class is used to manage the relationship
+ * between a BeanContextProxy and its BeanContextChild. When a BeanContextProxy
+ * is added or removed from this context the BeanContextChild it references must
+ * also be added or removed. This requires that both the BeanContextChild and
+ * BeanContextProxy are added/removed to the list of children. This class
+ * is used to map from the proxy -> child and child -> proxy.
+ *
+ * The _child field is always guarenteed to be non-null, the proxy field may
+ * be null if this child does not have a proxy.
+ */
+ private final static class BCChild {
+
+ private Object _child;
+ private BeanContextProxy _proxy;
+ private boolean _isProxy;
+
+ /**
+ * Construct a new BCChild for a child which is not related to a BeanContextProxy.
+ * @param child child to add -- must not be an instance of BeanContextProxy.
+ */
+ protected BCChild(Object child) {
+ assert child != null;
+ assert !(child instanceof BeanContextProxy);
+
+ _child = child;
+ _proxy = null;
+ _isProxy = false;
+ }
+
+ /**
+ * Construct a new BCChild for a proxy -> child relationship.
+ * @param proxy BeanContextProxy
+ * @param child BeanContextChild
+ * @param isProxy true if this will be entered into the child map keyed on the proxy.
+ */
+ protected BCChild(BeanContextProxy proxy, BeanContextChild child, boolean isProxy) {
+ assert child != null;
+ assert proxy != null;
+
+ _child = child;
+ _proxy = proxy;
+ _isProxy = isProxy;
+ }
+
+ /**
+ * Get the proxy.
+ */
+ protected BeanContextProxy getProxy() {
+ return _proxy;
+ }
+
+ /**
+ * Get the child.
+ */
+ protected Object getChild() {
+ return _child;
+ }
+
+ /**
+ * True if a proxy was set for this child.
+ */
+ protected boolean hasProxy() {
+ return _proxy != null;
+ }
+
+ /**
+ * True if this child was keyed by its proxy in the child map.
+ */
+ protected boolean isProxy() {
+ return _isProxy;
+ }
+
+ /**
+ * True if this BCChild is serializable.
+ */
+ protected boolean isSerializable() {
+ return (_proxy != null) ? _proxy instanceof Serializable && _child instanceof Serializable : _child instanceof Serializable;
+ }
}
}
Modified: beehive/trunk/controls/test/src/junit-tests/org/apache/beehive/controls/test/junit/ControlBeanContextSupportTest.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/controls/test/src/junit-tests/org/apache/beehive/controls/test/junit/ControlBeanContextSupportTest.java?rev=397220&r1=397219&r2=397220&view=diff
==============================================================================
--- beehive/trunk/controls/test/src/junit-tests/org/apache/beehive/controls/test/junit/ControlBeanContextSupportTest.java (original)
+++ beehive/trunk/controls/test/src/junit-tests/org/apache/beehive/controls/test/junit/ControlBeanContextSupportTest.java Wed Apr 26 08:22:50 2006
@@ -177,24 +177,20 @@
/**
* Test interator() collection api. Iterator returned should not
- * allow for removal of items.
+ * allow for removal of items. NOTE: ControlBeanContextSupport
+ * uses a Map to store its children so the iteration order
+ * is not predictable.
*/
public void testIterator() {
ControlBeanContextSupport cbcs = getContext();
ControlBeanContextChildSupport child1 = new ControlBeanContextChildSupport();
- ControlBeanContextChildSupport child2 = new ControlBeanContextChildSupport();
-
assertTrue(cbcs.add(child1));
- assertTrue(cbcs.add(child2));
Iterator i = cbcs.iterator();
assertTrue(i.hasNext());
assertEquals(child1, i.next());
- assertTrue(i.hasNext());
- assertEquals(child2, i.next());
-
try {
i.remove();
}
@@ -305,10 +301,10 @@
assertNull(pce[0].getOldValue());
assertEquals(cbcs, pce[0].getNewValue());
- // that the child was added to the collection
+ // test that the proxy as well as the bcc it references were added to the bean context
+ // as children -- may seem a bit odd but the spec says it should work this way!
Object[] children = cbcs.toArray();
- assertEquals(1, children.length);
- assertEquals(proxy, children[0]);
+ assertEquals(2, children.length);
}
/**
@@ -433,7 +429,7 @@
assertNull(pce[0].getNewValue());
assertEquals(cbcs, pce[0].getOldValue());
- // that the child was added to the collection
+ // that the child was removed from the collection
Object[] children = cbcs.toArray();
assertEquals(0, children.length);
}