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