- /*
- * @(#)BeanContextServicesSupport.java 1.16 00/02/02
- *
- * Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the proprietary information of Sun Microsystems, Inc.
- * Use is subject to license terms.
- *
- */
-
- package java.beans.beancontext;
-
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Map.Entry;
-
- import java.io.IOException;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.io.Serializable;
-
- import java.util.TooManyListenersException;
-
- import java.util.Locale;
-
- /**
- * <p>
- * This helper class provides a utility implementation of the
- * java.beans.beancontext.BeanContextServices interface.
- * </p>
- * <p>
- * Since this class directly implements the BeanContextServices interface,
- * the class can, and is intended to be used either by subclassing this
- * implementation, or via delegation of an instance of this class
- * from another through the BeanContextProxy interface.
- * </p>
- *
- * @author Laurence P. G. Cable
- * @version 1.16, 02/02/00
- * @since 1.2
- */
-
- public class BeanContextServicesSupport extends BeanContextSupport
- implements BeanContextServices {
-
- /**
- * <p>
- * Construct a BeanContextServicesSupport instance
- * </p>
- *
- * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
- * @param lcle The current Locale for this BeanContext.
- * @param dtime The initial state, true if in design mode, false if runtime.
- * @param visible The initial visibility.
- *
- */
-
- public BeanContextServicesSupport(BeanContextServices peer, Locale lcle, boolean dTime, boolean visible) {
- super(peer, lcle, dTime, visible);
- }
-
- /**
- * Create an instance using the specified Locale and design mode.
- *
- * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
- * @param lcle The current Locale for this BeanContext.
- * @param dtime The initial state, true if in design mode, false if runtime.
- */
-
- public BeanContextServicesSupport(BeanContextServices peer, Locale lcle, boolean dtime) {
- this (peer, lcle, dtime, true);
- }
-
- /**
- * Create an instance using the specified locale
- *
- * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
- * @param lcle The current Locale for this BeanContext.
- */
-
- public BeanContextServicesSupport(BeanContextServices peer, Locale lcle) {
- this (peer, lcle, false, true);
- }
-
- /**
- * Create an instance with a peer
- *
- * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
- */
-
- public BeanContextServicesSupport(BeanContextServices peer) {
- this (peer, null, false, true);
- }
-
- /**
- * Create an instance that is not a delegate of another object
- */
-
- public BeanContextServicesSupport() {
- this (null, null, false, true);
- }
-
- /**
- * called by BeanContextSupport superclass during construction and
- * deserialization to initialize subclass transient state.
- *
- * subclasses may envelope this method, but should not override it or
- * call it directly.
- */
-
- public void initialize() {
- super.initialize();
-
- services = new HashMap(serializable + 1);
- bcsListeners = new ArrayList(1);
- }
-
- /**
- * Gets the <tt>BeanContextServices</tt> associated with this
- * <tt>BeanContextServicesSupport</tt>.
- *
- * @return the instance of <tt>BeanContext</tt>
- * this object is providing the implementation for.
- */
- public BeanContextServices getBeanContextServicesPeer() {
- return (BeanContextServices)getBeanContextChildPeer();
- }
-
- /************************************************************************/
-
- /*
- * protected nested class containing per child information, an instance
- * of which is associated with each child in the "children" hashtable.
- * subclasses can extend this class to include their own per-child state.
- *
- * Note that this 'value' is serialized with the corresponding child 'key'
- * when the BeanContextSupport is serialized.
- */
-
- protected class BCSSChild extends BeanContextSupport.BCSChild {
-
- /*
- * private nested class to map serviceClass to Provider and requestors
- * listeners.
- */
-
- class BCSSCServiceClassRef {
-
- // create an instance of a service ref
-
- BCSSCServiceClassRef(Class sc, BeanContextServiceProvider bcsp, boolean delegated) {
- super();
-
- serviceClass = sc;
-
- if (delegated)
- delegateProvider = bcsp;
- else
- serviceProvider = bcsp;
- }
-
- // add a requestor and assoc listener
-
- void addRequestor(Object requestor, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
- BeanContextServiceRevokedListener cbcsrl = (BeanContextServiceRevokedListener)requestors.get(requestor);
-
- if (cbcsrl != null && !cbcsrl.equals(bcsrl))
- throw new TooManyListenersException();
-
- requestors.put(requestor, bcsrl);
- }
-
- // remove a requestor
-
- void removeRequestor(Object requestor) {
- requestors.remove(requestor);
- }
-
- // check a requestors listener
-
- void verifyRequestor(Object requestor, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
- BeanContextServiceRevokedListener cbcsrl = (BeanContextServiceRevokedListener)requestors.get(requestor);
-
- if (cbcsrl != null && !cbcsrl.equals(bcsrl))
- throw new TooManyListenersException();
- }
-
- void verifyAndMaybeSetProvider(BeanContextServiceProvider bcsp, boolean isDelegated) {
- BeanContextServiceProvider current;
-
- if (isDelegated) { // the provider is delegated
- current = delegateProvider;
-
- if (current == null || bcsp == null) {
- delegateProvider = bcsp;
- return;
- }
- } else { // the provider is registered with this BCS
- current = serviceProvider;
-
- if (current == null || bcsp == null) {
- serviceProvider = bcsp;
- return;
- }
- }
-
- if (!current.equals(bcsp))
- throw new UnsupportedOperationException("existing service reference obtained from different BeanContextServiceProvider not supported");
-
- }
-
- Iterator cloneOfEntries() {
- return ((HashMap)requestors.clone()).entrySet().iterator();
- }
-
- Iterator entries() { return requestors.entrySet().iterator(); }
-
- boolean isEmpty() { return requestors.isEmpty(); }
-
- Class getServiceClass() { return serviceClass; }
-
- BeanContextServiceProvider getServiceProvider() {
- return serviceProvider;
- }
-
- BeanContextServiceProvider getDelegateProvider() {
- return delegateProvider;
- }
-
- boolean isDelegated() { return delegateProvider != null; }
-
- void addRef(boolean delegated) {
- if (delegated)
- delegateRefs++;
- else
- serviceRefs++;
- }
-
-
- void releaseRef(boolean delegated) {
- if (delegated)
- if (--delegateRefs == 0) delegateProvider = null;
- else
- if (--serviceRefs <= 0) serviceProvider = null;
- }
-
- int getRefs() { return serviceRefs + delegateRefs; }
-
- int getDelegateRefs() { return delegateRefs; }
-
- int getServiceRefs() { return serviceRefs; }
-
- /*
- * fields
- */
-
- Class serviceClass;
-
- BeanContextServiceProvider serviceProvider;
- int serviceRefs;
-
- BeanContextServiceProvider delegateProvider; // proxy
- int delegateRefs;
-
- HashMap requestors = new HashMap(1);
- }
-
- /*
- * per service reference info ...
- */
-
- class BCSSCServiceRef {
- BCSSCServiceRef(BCSSCServiceClassRef scref, boolean isDelegated) {
- serviceClassRef = scref;
- delegated = isDelegated;
- }
-
- void addRef() { refCnt++; }
- int release() { return --refCnt; }
-
- BCSSCServiceClassRef getServiceClassRef() { return serviceClassRef; }
-
- boolean isDelegated() { return delegated; }
-
- /*
- * fields
- */
-
- BCSSCServiceClassRef serviceClassRef;
- int refCnt = 1;
- boolean delegated = false;
- }
-
- BCSSChild(Object bcc, Object peer) { super(bcc, peer); }
-
- // note usage of service per requestor, per service
-
- synchronized void usingService(Object requestor, Object service, Class serviceClass, BeanContextServiceProvider bcsp, boolean isDelegated, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException, UnsupportedOperationException {
-
- // first, process mapping from serviceClass to requestor(s)
-
- BCSSCServiceClassRef serviceClassRef = null;
-
- if (serviceClasses == null)
- serviceClasses = new HashMap(1);
- else
- serviceClassRef = (BCSSCServiceClassRef)serviceClasses.get(serviceClass);
-
- if (serviceClassRef == null) { // new service being used ...
- serviceClassRef = new BCSSCServiceClassRef(serviceClass, bcsp, isDelegated);
- serviceClasses.put(serviceClass, serviceClassRef);
-
- } else { // existing service ...
- serviceClassRef.verifyAndMaybeSetProvider(bcsp, isDelegated); // throws
- serviceClassRef.verifyRequestor(requestor, bcsrl); // throws
- }
-
- serviceClassRef.addRequestor(requestor, bcsrl);
- serviceClassRef.addRef(isDelegated);
-
- // now handle mapping from requestor to service(s)
-
- BCSSCServiceRef serviceRef = null;
- Map services = null;
-
- if (serviceRequestors == null) {
- serviceRequestors = new HashMap(1);
- } else {
- services = (Map)serviceRequestors.get(requestor);
- }
-
- if (services == null) {
- services = new HashMap(1);
-
- serviceRequestors.put(requestor, services);
- } else
- serviceRef = (BCSSCServiceRef)services.get(service);
-
- if (serviceRef == null) {
- serviceRef = new BCSSCServiceRef(serviceClassRef, isDelegated);
-
- services.put(service, serviceRef);
- } else {
- serviceRef.addRef();
- }
- }
-
- // release a service reference
-
- synchronized void releaseService(Object requestor, Object service) {
- if (serviceRequestors == null) return;
-
- Map services = (Map)serviceRequestors.get(requestor);
-
- if (services == null) return; // oops its not there anymore!
-
- BCSSCServiceRef serviceRef = (BCSSCServiceRef)services.get(service);
-
- if (serviceRef == null) return; // oops its not there anymore!
-
- BCSSCServiceClassRef serviceClassRef = serviceRef.getServiceClassRef();
- boolean isDelegated = serviceRef.isDelegated();
- BeanContextServiceProvider bcsp = isDelegated ? serviceClassRef.getDelegateProvider() : serviceClassRef.getServiceProvider();
-
- bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);
-
- serviceClassRef.releaseRef(isDelegated);
-
- if (serviceRef.release() == 0) {
-
- services.remove(service);
-
- if (services.isEmpty()) {
- serviceRequestors.remove(requestor);
- serviceClassRef.removeRequestor(requestor);
- }
-
- if (serviceRequestors.isEmpty()) {
- serviceRequestors = null;
- }
-
- if (serviceClassRef.isEmpty()) {
- serviceClasses.remove(serviceClassRef.getServiceClass());
- }
-
- if (serviceClasses.isEmpty())
- serviceClasses = null;
- }
- }
-
- // revoke a service
-
- synchronized void revokeService(Class serviceClass, boolean isDelegated, boolean revokeNow) {
- if (serviceClasses == null) return;
-
- BCSSCServiceClassRef serviceClassRef = (BCSSCServiceClassRef)serviceClasses.get(serviceClass);
-
- if (serviceClassRef == null) return;
-
- Iterator i = serviceClassRef.cloneOfEntries();
-
- BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClass, revokeNow);
- boolean noMoreRefs = false;
-
- while (i.hasNext()) {
- Map.Entry entry = (Map.Entry)i.next();
- BeanContextServiceRevokedListener listener = (BeanContextServiceRevokedListener)entry.getValue();
-
- if (revokeNow) {
- Object requestor = entry.getKey();
- Map services = (Map)serviceRequestors.get(requestor);
-
- if (services != null) {
- Iterator i1 = services.entrySet().iterator();
-
- while (i1.hasNext()) {
- Map.Entry tmp = (Map.Entry)i1.next();
-
- BCSSCServiceRef serviceRef = (BCSSCServiceRef)tmp.getValue();
- if (serviceRef.getServiceClassRef().equals(serviceClassRef) && isDelegated == serviceRef.isDelegated()) {
- i1.remove();
- }
- }
-
- if (noMoreRefs = services.isEmpty()) {
- serviceRequestors.remove(requestor);
- }
- }
-
- if (noMoreRefs) serviceClassRef.removeRequestor(requestor);
- }
-
- listener.serviceRevoked(bcsre);
- }
-
- if (revokeNow && serviceClasses != null) {
- if (serviceClassRef.isEmpty())
- serviceClasses.remove(serviceClass);
-
- if (serviceClasses.isEmpty())
- serviceClasses = null;
- }
-
- if (serviceRequestors != null && serviceRequestors.isEmpty())
- serviceRequestors = null;
- }
-
- // release all references for this child since it has been unnested.
-
- void cleanupReferences() {
-
- if (serviceRequestors == null) return;
-
- Iterator requestors = serviceRequestors.entrySet().iterator();
-
- while(requestors.hasNext()) {
- Map.Entry tmp = (Map.Entry)requestors.next();
- Object requestor = tmp.getKey();
- Iterator services = ((Map)tmp.getValue()).entrySet().iterator();
-
- requestors.remove();
-
- while (services.hasNext()) {
- Map.Entry entry = (Map.Entry)services.next();
- Object service = entry.getKey();
- BCSSCServiceRef sref = (BCSSCServiceRef)entry.getValue();
-
- BCSSCServiceClassRef scref = sref.getServiceClassRef();
-
- BeanContextServiceProvider bcsp = sref.isDelegated() ? scref.getDelegateProvider() : scref.getServiceProvider();
-
- scref.removeRequestor(requestor);
- services.remove();
-
- while (sref.release() >= 0) {
- bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);
- }
- }
- }
-
- serviceRequestors = null;
- serviceClasses = null;
- }
-
- void revokeAllDelegatedServicesNow() {
- if (serviceClasses == null) return;
-
- Iterator serviceClassRefs =
- new HashSet(serviceClasses.values()).iterator();
-
- while (serviceClassRefs.hasNext()) {
- BCSSCServiceClassRef serviceClassRef = (BCSSCServiceClassRef)serviceClassRefs.next();
-
- if (!serviceClassRef.isDelegated()) continue;
-
- Iterator i = serviceClassRef.cloneOfEntries();
- BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClassRef.getServiceClass(), true);
- boolean noMoreRefs = false;
-
- while (i.hasNext()) {
- Map.Entry entry = (Map.Entry)i.next();
- BeanContextServiceRevokedListener listener = (BeanContextServiceRevokedListener)entry.getValue();
-
- Object requestor = entry.getKey();
- Map services = (Map)serviceRequestors.get(requestor);
-
- if (services != null) {
- Iterator i1 = services.entrySet().iterator();
-
- while (i1.hasNext()) {
- Map.Entry tmp = (Map.Entry)i1.next();
-
- BCSSCServiceRef serviceRef = (BCSSCServiceRef)tmp.getValue();
- if (serviceRef.getServiceClassRef().equals(serviceClassRef) && serviceRef.isDelegated()) {
- i1.remove();
- }
- }
-
- if (noMoreRefs = services.isEmpty()) {
- serviceRequestors.remove(requestor);
- }
- }
-
- if (noMoreRefs) serviceClassRef.removeRequestor(requestor);
-
- listener.serviceRevoked(bcsre);
-
- if (serviceClassRef.isEmpty())
- serviceClasses.remove(serviceClassRef.getServiceClass());
- }
- }
-
- if (serviceClasses.isEmpty()) serviceClasses = null;
-
- if (serviceRequestors != null && serviceRequestors.isEmpty())
- serviceRequestors = null;
- }
-
- /*
- * fields
- */
-
- private transient HashMap serviceClasses;
- private transient HashMap serviceRequestors;
- }
-
- /**
- * <p>
- * Subclasses can override this method to insert their own subclass
- * of Child without having to override add() or the other Collection
- * methods that add children to the set.
- * </p>
- *
- * @param targetChild the child to create the Child on behalf of
- * @param peer the peer if the targetChild and peer are related by BeanContextProxy
- */
-
- protected BCSChild createBCSChild(Object targetChild, Object peer) {
- return new BCSSChild(targetChild, peer);
- }
-
- /************************************************************************/
-
- /**
- * subclasses may subclass this nested class to add behaviors for
- * each BeanContextServicesProvider.
- */
-
- protected static class BCSSServiceProvider implements Serializable {
-
- BCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp) {
- super();
-
- serviceProvider = bcsp;
- }
-
- protected BeanContextServiceProvider getServiceProvider() {
- return serviceProvider;
- }
-
- /*
- * fields
- */
-
- protected BeanContextServiceProvider serviceProvider;
- }
-
- /**
- * subclasses can override this method to create new subclasses of
- * BCSSServiceProvider without having to overrride addService() in
- * order to instantiate.
- */
-
- protected BCSSServiceProvider createBCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp) {
- return new BCSSServiceProvider(sc, bcsp);
- }
-
- /************************************************************************/
-
- /**
- * add a BeanContextServicesListener
- *
- * @throw new NullPointerException
- */
-
- public void addBeanContextServicesListener(BeanContextServicesListener bcsl) {
- if (bcsl == null) throw new NullPointerException("bcsl");
-
- synchronized(bcsListeners) {
- if (bcsListeners.contains(bcsl))
- return;
- else
- bcsListeners.add(bcsl);
- }
- }
-
- /**
- * remove a BeanContextServicesListener
- */
-
- public void removeBeanContextServicesListener(BeanContextServicesListener bcsl) {
- if (bcsl == null) throw new NullPointerException("bcsl");
-
- synchronized(bcsListeners) {
- if (!bcsListeners.contains(bcsl))
- return;
- else
- bcsListeners.remove(bcsl);
- }
- }
-
- /**
- * add a service
- */
-
- public boolean addService(Class serviceClass, BeanContextServiceProvider bcsp) {
- return addService(serviceClass, bcsp, true);
- }
-
- /**
- * add a service
- */
-
- protected boolean addService(Class serviceClass, BeanContextServiceProvider bcsp, boolean fireEvent) {
-
- if (serviceClass == null) throw new NullPointerException("serviceClass");
- if (bcsp == null) throw new NullPointerException("bcsp");
-
- synchronized(BeanContext.globalHierarchyLock) {
- if (services.containsKey(serviceClass))
- return false;
- else {
- services.put(serviceClass, createBCSSServiceProvider(serviceClass, bcsp));
-
- if (bcsp instanceof Serializable) serializable++;
-
- if (!fireEvent) return true;
-
-
- BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);
-
- fireServiceAdded(bcssae);
-
- synchronized(children) {
- Iterator i = children.keySet().iterator();
-
- while (i.hasNext()) {
- Object c = i.next();
-
- if (c instanceof BeanContextServices) {
- ((BeanContextServicesListener)c).serviceAvailable(bcssae);
- }
- }
- }
-
- return true;
- }
- }
- }
-
- /**
- * remove a service
- */
-
- public void revokeService(Class serviceClass, BeanContextServiceProvider bcsp, boolean revokeCurrentServicesNow) {
-
- if (serviceClass == null) throw new NullPointerException("serviceClass");
- if (bcsp == null) throw new NullPointerException("bcsp");
-
- synchronized(BeanContext.globalHierarchyLock) {
- if (!services.containsKey(serviceClass)) return;
-
- BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
-
- if (!bcsssp.getServiceProvider().equals(bcsp))
- throw new IllegalArgumentException("service provider mismatch");
-
- services.remove(serviceClass);
-
- if (bcsp instanceof Serializable) serializable--;
-
- Iterator i = bcsChildren(); // get the BCSChild values.
-
- while (i.hasNext()) {
- ((BCSSChild)i.next()).revokeService(serviceClass, false, revokeCurrentServicesNow);
- }
-
- fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
- }
- }
-
- /**
- * has a service, which may be delegated
- */
-
- public synchronized boolean hasService(Class serviceClass) {
- if (serviceClass == null) throw new NullPointerException("serviceClass");
-
- synchronized(BeanContext.globalHierarchyLock) {
- if (services.containsKey(serviceClass)) return true;
-
- BeanContextServices bcs = null;
-
- try {
- bcs = (BeanContextServices)getBeanContext();
- } catch (ClassCastException cce) {
- return false;
- }
-
- return bcs == null ? false : bcs.hasService(serviceClass);
- }
- }
-
- /************************************************************************/
-
- /*
- * a nested subclass used to represent a proxy for serviceClasses delegated
- * to an enclosing BeanContext.
- */
-
- protected class BCSSProxyServiceProvider implements BeanContextServiceProvider, BeanContextServiceRevokedListener {
-
- BCSSProxyServiceProvider(BeanContextServices bcs) {
- super();
-
- nestingCtxt = bcs;
- }
-
- public Object getService(BeanContextServices bcs, Object requestor, Class serviceClass, Object serviceSelector) {
- Object service = null;
-
- try {
- service = nestingCtxt.getService(bcs, requestor, serviceClass, serviceSelector, this);
- } catch (TooManyListenersException tmle) {
- return null;
- }
-
- return service;
- }
-
- public void releaseService(BeanContextServices bcs, Object requestor, Object service) {
- nestingCtxt.releaseService(bcs, requestor, service);
- }
-
- public Iterator getCurrentServiceSelectors(BeanContextServices bcs, Class serviceClass) {
- return nestingCtxt.getCurrentServiceSelectors(serviceClass);
- }
-
- public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
- Iterator i = bcsChildren(); // get the BCSChild values.
-
- while (i.hasNext()) {
- ((BCSSChild)i.next()).revokeService(bcsre.getServiceClass(), true, bcsre.isCurrentServiceInvalidNow());
- }
- }
-
- /*
- * fields
- */
-
- private BeanContextServices nestingCtxt;
- }
-
- /************************************************************************/
-
- /**
- * obtain a service which may be delegated
- */
-
- public Object getService(BeanContextChild child, Object requestor, Class serviceClass, Object serviceSelector, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
- if (child == null) throw new NullPointerException("child");
- if (serviceClass == null) throw new NullPointerException("serviceClass");
- if (requestor == null) throw new NullPointerException("requestor");
- if (bcsrl == null) throw new NullPointerException("bcsrl");
-
- Object service = null;
- BCSSChild bcsc;
- BeanContextServices bcssp = getBeanContextServicesPeer();
-
- synchronized(BeanContext.globalHierarchyLock) {
- synchronized(children) { bcsc = (BCSSChild)children.get(child); }
-
- if (bcsc == null) throw new IllegalArgumentException("not a child of this context"); // not a child ...
-
- BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
-
- if (bcsssp != null) {
- BeanContextServiceProvider bcsp = bcsssp.getServiceProvider();
- service = bcsp.getService(bcssp, requestor, serviceClass, serviceSelector);
- if (service != null) { // do bookkeeping ...
- try {
- bcsc.usingService(requestor, service, serviceClass, bcsp, false, bcsrl);
- } catch (TooManyListenersException tmle) {
- bcsp.releaseService(bcssp, requestor, service);
- throw tmle;
- } catch (UnsupportedOperationException uope) {
- bcsp.releaseService(bcssp, requestor, service);
- throw uope; // unchecked rt exception
- }
-
- return service;
- }
- }
-
-
- if (proxy != null) {
-
- // try to delegate ...
-
- service = proxy.getService(bcssp, requestor, serviceClass, serviceSelector);
-
- if (service != null) { // do bookkeeping ...
- try {
- bcsc.usingService(requestor, service, serviceClass, proxy, true, bcsrl);
- } catch (TooManyListenersException tmle) {
- proxy.releaseService(bcssp, requestor, service);
- throw tmle;
- } catch (UnsupportedOperationException uope) {
- proxy.releaseService(bcssp, requestor, service);
- throw uope; // unchecked rt exception
- }
-
- return service;
- }
- }
- }
-
- return null;
- }
-
- /**
- * release a service
- */
-
- public void releaseService(BeanContextChild child, Object requestor, Object service) {
- if (child == null) throw new NullPointerException("child");
- if (requestor == null) throw new NullPointerException("requestor");
- if (service == null) throw new NullPointerException("service");
-
- BCSSChild bcsc;
-
- synchronized(BeanContext.globalHierarchyLock) {
- synchronized(children) { bcsc = (BCSSChild)children.get(child); }
-
- if (bcsc != null)
- bcsc.releaseService(requestor, service);
- else
- throw new IllegalArgumentException("child actual is not a child of this BeanContext");
- }
- }
-
- /**
- * @return an iterator for all the currently registered service classes.
- */
-
- public Iterator getCurrentServiceClasses() {
- return new BCSIterator(services.keySet().iterator());
- }
-
- /**
- * @return an iterator for all the currently available service selectors
- * (if any) available for the specified service.
- */
-
- public Iterator getCurrentServiceSelectors(Class serviceClass) {
-
- BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
-
- return bcsssp != null ? new BCSIterator(bcsssp.getServiceProvider().getCurrentServiceSelectors(getBeanContextServicesPeer(), serviceClass)) : null;
- }
-
- /**
- * BeanContextServicesListener callback, propagates event to all
- * currently registered listeners and BeanContextServices children,
- * if this BeanContextService does not already implement this service
- * itself.
- *
- * subclasses may override or envelope this method to implement their
- * own propagation semantics.
- */
-
- public void serviceAvailable(BeanContextServiceAvailableEvent bcssae) {
- synchronized(BeanContext.globalHierarchyLock) {
- if (services.containsKey(bcssae.getServiceClass())) return;
-
- fireServiceAdded(bcssae);
-
- Iterator i;
-
- synchronized(children) {
- i = children.keySet().iterator();
- }
-
- while (i.hasNext()) {
- Object c = i.next();
-
- if (c instanceof BeanContextServices) {
- ((BeanContextServicesListener)c).serviceAvailable(bcssae);
- }
- }
- }
- }
-
- /**
- * BeanContextServicesListener callback, propagates event to all
- * currently registered listeners and BeanContextServices children,
- * if this BeanContextService does not already implement this service
- * itself.
- *
- * subclasses may override or envelope this method to implement their
- * own propagation semantics.
- */
-
- public void serviceRevoked(BeanContextServiceRevokedEvent bcssre) {
- synchronized(BeanContext.globalHierarchyLock) {
- if (services.containsKey(bcssre.getServiceClass())) return;
-
- fireServiceRevoked(bcssre);
-
- Iterator i;
-
- synchronized(children) {
- i = children.keySet().iterator();
- }
-
- while (i.hasNext()) {
- Object c = i.next();
-
- if (c instanceof BeanContextServices) {
- ((BeanContextServicesListener)c).serviceRevoked(bcssre);
- }
- }
- }
- }
-
- /**
- * Gets the <tt>BeanContextServicesListener</tt> (if any) of the specified
- * child.
- *
- * @param child the specified child
- * @return the BeanContextServicesListener (if any) of the specified child
- */
- protected static final BeanContextServicesListener getChildBeanContextServicesListener(Object child) {
- try {
- return (BeanContextServicesListener)child;
- } catch (ClassCastException cce) {
- return null;
- }
- }
-
- /**
- * called from superclass child removal operations after a child
- * has been successfully removed. called with child synchronized.
- *
- * This subclass uses this hook to immediately revoke any services
- * being used by this child if it is a BeanContextChild.
- *
- * subclasses may envelope this method in order to implement their
- * own child removal side-effects.
- */
-
- protected void childJustRemovedHook(Object child, BCSChild bcsc) {
- BCSSChild bcssc = (BCSSChild)bcsc;
-
- bcssc.cleanupReferences();
- }
-
- /**
- * called from setBeanContext to notify a BeanContextChild
- * to release resources obtained from the nesting BeanContext.
- *
- * This method revokes any services obtained from its parent.
- *
- * subclasses may envelope this method to implement their own semantics.
- */
-
- protected synchronized void releaseBeanContextResources() {
- Object[] bcssc;
-
- super.releaseBeanContextResources();
-
- synchronized(children) {
- if (children.isEmpty()) return;
-
- bcssc = children.values().toArray();
- }
-
-
- for (int i = 0; i < bcssc.length; i++) {
- ((BCSSChild)bcssc[i]).revokeAllDelegatedServicesNow();
- }
-
- proxy = null;
- }
-
- /**
- * called from setBeanContext to notify a BeanContextChild
- * to allocate resources obtained from the nesting BeanContext.
- *
- * subclasses may envelope this method to implement their own semantics.
- */
-
- protected synchronized void initializeBeanContextResources() {
- super.initializeBeanContextResources();
-
- BeanContext nbc = getBeanContext();
-
- if (nbc == null) return;
-
- try {
- BeanContextServices bcs = (BeanContextServices)nbc;
-
- proxy = new BCSSProxyServiceProvider(bcs);
- } catch (ClassCastException cce) {
- // do nothing ...
- }
- }
-
- /**
- * Fires a <tt>BeanContextServiceEvent</tt> notifying of a new service.
- */
- protected final void fireServiceAdded(Class serviceClass) {
- BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);
-
- fireServiceAdded(bcssae);
- }
-
- /**
- * Fires a <tt>BeanContextServiceAvailableEvent</tt> indicating that a new
- * service has become available.
- *
- * @param bcssae the <tt>BeanContextServiceAvailableEvent</tt>
- */
- protected final void fireServiceAdded(BeanContextServiceAvailableEvent bcssae) {
- Object[] copy;
-
- synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
-
- for (int i = 0; i < copy.length; i++) {
- ((BeanContextServicesListener)copy[i]).serviceAvailable(bcssae);
- }
- }
-
- /**
- * Fires a <tt>BeanContextServiceEvent</tt> notifying of a service being revoked.
- *
- * @param bcsre the <tt>BeanContextServiceRevokedEvent</tt>
- */
- protected final void fireServiceRevoked(BeanContextServiceRevokedEvent bcsre) {
- Object[] copy;
-
- synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
-
- for (int i = 0; i < copy.length; i++) {
- ((BeanContextServiceRevokedListener)copy[i]).serviceRevoked(bcsre);
- }
- }
-
- /**
- * Fires a <tt>BeanContextServiceRevokedEvent</tt>
- * indicating that a particular service is
- * no longer available.
- */
- protected final void fireServiceRevoked(Class serviceClass, boolean revokeNow) {
- Object[] copy;
- BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(getBeanContextServicesPeer(), serviceClass, revokeNow);
-
- synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
-
- for (int i = 0; i < copy.length; i++) {
- ((BeanContextServicesListener)copy[i]).serviceRevoked(bcsre);
- }
- }
-
- /**
- * called from BeanContextSupport writeObject before it serializes the
- * children ...
- *
- * This class will serialize any Serializable BeanContextServiceProviders
- * herein.
- *
- * subclasses may envelope this method to insert their own serialization
- * processing that has to occur prior to serialization of the children
- */
-
- protected synchronized void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
-
- oos.writeInt(serializable);
-
- if (serializable <= 0) return;
-
- int count = 0;
-
- Iterator i = services.entrySet().iterator();
-
- while (i.hasNext() && count < serializable) {
- Map.Entry entry = (Map.Entry)i.next();
- BCSSServiceProvider bcsp = null;
-
- try {
- bcsp = (BCSSServiceProvider)entry.getValue();
- } catch (ClassCastException cce) {
- continue;
- }
-
- if (bcsp.getServiceProvider() instanceof Serializable) {
- oos.writeObject(entry.getKey());
- oos.writeObject(bcsp);
- count++;
- }
- }
-
- if (count != serializable)
- throw new IOException("wrote different number of service providers than expected");
- }
-
- /**
- * called from BeanContextSupport readObject before it deserializes the
- * children ...
- *
- * This class will deserialize any Serializable BeanContextServiceProviders
- * serialized earlier thus making them available to the children when they
- * deserialized.
- *
- * subclasses may envelope this method to insert their own serialization
- * processing that has to occur prior to serialization of the children
- */
-
- protected synchronized void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
-
- serializable = ois.readInt();
-
- int count = serializable;
-
- while (count > 0) {
- services.put(ois.readObject(), ois.readObject());
- count--;
- }
- }
-
- /**
- * serialize the instance
- */
-
- private synchronized void writeObject(ObjectOutputStream oos) throws IOException {
- oos.defaultWriteObject();
-
- serialize(oos, (Collection)bcsListeners);
- }
-
- /**
- * deserialize the instance
- */
-
- private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
-
- ois.defaultReadObject();
-
- deserialize(ois, (Collection)bcsListeners);
- }
-
-
- /*
- * fields
- */
-
- /**
- * all accesses to the <code> protected transient HashMap services </code>
- * field should be synchronized on that object
- */
- protected transient HashMap services;
-
- /**
- * The number of instances of a serializable <tt>BeanContextServceProvider</tt>.
- */
- protected transient int serializable = 0;
-
-
- /**
- * Delegate for the <tt>BeanContextServiceProvider</tt>.
- */
- protected transient BCSSProxyServiceProvider proxy;
-
-
- /**
- * List of <tt>BeanContextServicesListener</tt> objects.
- */
- protected transient ArrayList bcsListeners;
- }