Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/beans/beancontext/BeanContextServicesSupport.java
38918 views
/*1* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.beans.beancontext;2627import java.util.ArrayList;28import java.util.Collection;29import java.util.HashMap;30import java.util.HashSet;31import java.util.Iterator;32import java.util.Map;33import java.util.Map.Entry;3435import java.io.IOException;36import java.io.ObjectInputStream;37import java.io.ObjectOutputStream;38import java.io.Serializable;3940import java.util.TooManyListenersException;4142import java.util.Locale;4344/**45* <p>46* This helper class provides a utility implementation of the47* java.beans.beancontext.BeanContextServices interface.48* </p>49* <p>50* Since this class directly implements the BeanContextServices interface,51* the class can, and is intended to be used either by subclassing this52* implementation, or via delegation of an instance of this class53* from another through the BeanContextProxy interface.54* </p>55*56* @author Laurence P. G. Cable57* @since 1.258*/5960public class BeanContextServicesSupport extends BeanContextSupport61implements BeanContextServices {62private static final long serialVersionUID = -8494482757288719206L;6364/**65* <p>66* Construct a BeanContextServicesSupport instance67* </p>68*69* @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer70* @param lcle The current Locale for this BeanContext.71* @param dTime The initial state, true if in design mode, false if runtime.72* @param visible The initial visibility.73*74*/7576public BeanContextServicesSupport(BeanContextServices peer, Locale lcle, boolean dTime, boolean visible) {77super(peer, lcle, dTime, visible);78}7980/**81* Create an instance using the specified Locale and design mode.82*83* @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer84* @param lcle The current Locale for this BeanContext.85* @param dtime The initial state, true if in design mode, false if runtime.86*/8788public BeanContextServicesSupport(BeanContextServices peer, Locale lcle, boolean dtime) {89this (peer, lcle, dtime, true);90}9192/**93* Create an instance using the specified locale94*95* @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer96* @param lcle The current Locale for this BeanContext.97*/9899public BeanContextServicesSupport(BeanContextServices peer, Locale lcle) {100this (peer, lcle, false, true);101}102103/**104* Create an instance with a peer105*106* @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer107*/108109public BeanContextServicesSupport(BeanContextServices peer) {110this (peer, null, false, true);111}112113/**114* Create an instance that is not a delegate of another object115*/116117public BeanContextServicesSupport() {118this (null, null, false, true);119}120121/**122* called by BeanContextSupport superclass during construction and123* deserialization to initialize subclass transient state.124*125* subclasses may envelope this method, but should not override it or126* call it directly.127*/128129public void initialize() {130super.initialize();131132services = new HashMap(serializable + 1);133bcsListeners = new ArrayList(1);134}135136/**137* Gets the <tt>BeanContextServices</tt> associated with this138* <tt>BeanContextServicesSupport</tt>.139*140* @return the instance of <tt>BeanContext</tt>141* this object is providing the implementation for.142*/143public BeanContextServices getBeanContextServicesPeer() {144return (BeanContextServices)getBeanContextChildPeer();145}146147/************************************************************************/148149/*150* protected nested class containing per child information, an instance151* of which is associated with each child in the "children" hashtable.152* subclasses can extend this class to include their own per-child state.153*154* Note that this 'value' is serialized with the corresponding child 'key'155* when the BeanContextSupport is serialized.156*/157158protected class BCSSChild extends BeanContextSupport.BCSChild {159160private static final long serialVersionUID = -3263851306889194873L;161162/*163* private nested class to map serviceClass to Provider and requestors164* listeners.165*/166167class BCSSCServiceClassRef {168169// create an instance of a service ref170171BCSSCServiceClassRef(Class sc, BeanContextServiceProvider bcsp, boolean delegated) {172super();173174serviceClass = sc;175176if (delegated)177delegateProvider = bcsp;178else179serviceProvider = bcsp;180}181182// add a requestor and assoc listener183184void addRequestor(Object requestor, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {185BeanContextServiceRevokedListener cbcsrl = (BeanContextServiceRevokedListener)requestors.get(requestor);186187if (cbcsrl != null && !cbcsrl.equals(bcsrl))188throw new TooManyListenersException();189190requestors.put(requestor, bcsrl);191}192193// remove a requestor194195void removeRequestor(Object requestor) {196requestors.remove(requestor);197}198199// check a requestors listener200201void verifyRequestor(Object requestor, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {202BeanContextServiceRevokedListener cbcsrl = (BeanContextServiceRevokedListener)requestors.get(requestor);203204if (cbcsrl != null && !cbcsrl.equals(bcsrl))205throw new TooManyListenersException();206}207208void verifyAndMaybeSetProvider(BeanContextServiceProvider bcsp, boolean isDelegated) {209BeanContextServiceProvider current;210211if (isDelegated) { // the provider is delegated212current = delegateProvider;213214if (current == null || bcsp == null) {215delegateProvider = bcsp;216return;217}218} else { // the provider is registered with this BCS219current = serviceProvider;220221if (current == null || bcsp == null) {222serviceProvider = bcsp;223return;224}225}226227if (!current.equals(bcsp))228throw new UnsupportedOperationException("existing service reference obtained from different BeanContextServiceProvider not supported");229230}231232Iterator cloneOfEntries() {233return ((HashMap)requestors.clone()).entrySet().iterator();234}235236Iterator entries() { return requestors.entrySet().iterator(); }237238boolean isEmpty() { return requestors.isEmpty(); }239240Class getServiceClass() { return serviceClass; }241242BeanContextServiceProvider getServiceProvider() {243return serviceProvider;244}245246BeanContextServiceProvider getDelegateProvider() {247return delegateProvider;248}249250boolean isDelegated() { return delegateProvider != null; }251252void addRef(boolean delegated) {253if (delegated) {254delegateRefs++;255} else {256serviceRefs++;257}258}259260261void releaseRef(boolean delegated) {262if (delegated) {263if (--delegateRefs == 0) {264delegateProvider = null;265}266} else {267if (--serviceRefs <= 0) {268serviceProvider = null;269}270}271}272273int getRefs() { return serviceRefs + delegateRefs; }274275int getDelegateRefs() { return delegateRefs; }276277int getServiceRefs() { return serviceRefs; }278279/*280* fields281*/282283Class serviceClass;284285BeanContextServiceProvider serviceProvider;286int serviceRefs;287288BeanContextServiceProvider delegateProvider; // proxy289int delegateRefs;290291HashMap requestors = new HashMap(1);292}293294/*295* per service reference info ...296*/297298class BCSSCServiceRef {299BCSSCServiceRef(BCSSCServiceClassRef scref, boolean isDelegated) {300serviceClassRef = scref;301delegated = isDelegated;302}303304void addRef() { refCnt++; }305int release() { return --refCnt; }306307BCSSCServiceClassRef getServiceClassRef() { return serviceClassRef; }308309boolean isDelegated() { return delegated; }310311/*312* fields313*/314315BCSSCServiceClassRef serviceClassRef;316int refCnt = 1;317boolean delegated = false;318}319320BCSSChild(Object bcc, Object peer) { super(bcc, peer); }321322// note usage of service per requestor, per service323324synchronized void usingService(Object requestor, Object service, Class serviceClass, BeanContextServiceProvider bcsp, boolean isDelegated, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException, UnsupportedOperationException {325326// first, process mapping from serviceClass to requestor(s)327328BCSSCServiceClassRef serviceClassRef = null;329330if (serviceClasses == null)331serviceClasses = new HashMap(1);332else333serviceClassRef = (BCSSCServiceClassRef)serviceClasses.get(serviceClass);334335if (serviceClassRef == null) { // new service being used ...336serviceClassRef = new BCSSCServiceClassRef(serviceClass, bcsp, isDelegated);337serviceClasses.put(serviceClass, serviceClassRef);338339} else { // existing service ...340serviceClassRef.verifyAndMaybeSetProvider(bcsp, isDelegated); // throws341serviceClassRef.verifyRequestor(requestor, bcsrl); // throws342}343344serviceClassRef.addRequestor(requestor, bcsrl);345serviceClassRef.addRef(isDelegated);346347// now handle mapping from requestor to service(s)348349BCSSCServiceRef serviceRef = null;350Map services = null;351352if (serviceRequestors == null) {353serviceRequestors = new HashMap(1);354} else {355services = (Map)serviceRequestors.get(requestor);356}357358if (services == null) {359services = new HashMap(1);360361serviceRequestors.put(requestor, services);362} else363serviceRef = (BCSSCServiceRef)services.get(service);364365if (serviceRef == null) {366serviceRef = new BCSSCServiceRef(serviceClassRef, isDelegated);367368services.put(service, serviceRef);369} else {370serviceRef.addRef();371}372}373374// release a service reference375376synchronized void releaseService(Object requestor, Object service) {377if (serviceRequestors == null) return;378379Map services = (Map)serviceRequestors.get(requestor);380381if (services == null) return; // oops its not there anymore!382383BCSSCServiceRef serviceRef = (BCSSCServiceRef)services.get(service);384385if (serviceRef == null) return; // oops its not there anymore!386387BCSSCServiceClassRef serviceClassRef = serviceRef.getServiceClassRef();388boolean isDelegated = serviceRef.isDelegated();389BeanContextServiceProvider bcsp = isDelegated ? serviceClassRef.getDelegateProvider() : serviceClassRef.getServiceProvider();390391bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);392393serviceClassRef.releaseRef(isDelegated);394serviceClassRef.removeRequestor(requestor);395396if (serviceRef.release() == 0) {397398services.remove(service);399400if (services.isEmpty()) {401serviceRequestors.remove(requestor);402serviceClassRef.removeRequestor(requestor);403}404405if (serviceRequestors.isEmpty()) {406serviceRequestors = null;407}408409if (serviceClassRef.isEmpty()) {410serviceClasses.remove(serviceClassRef.getServiceClass());411}412413if (serviceClasses.isEmpty())414serviceClasses = null;415}416}417418// revoke a service419420synchronized void revokeService(Class serviceClass, boolean isDelegated, boolean revokeNow) {421if (serviceClasses == null) return;422423BCSSCServiceClassRef serviceClassRef = (BCSSCServiceClassRef)serviceClasses.get(serviceClass);424425if (serviceClassRef == null) return;426427Iterator i = serviceClassRef.cloneOfEntries();428429BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClass, revokeNow);430boolean noMoreRefs = false;431432while (i.hasNext() && serviceRequestors != null) {433Map.Entry entry = (Map.Entry)i.next();434BeanContextServiceRevokedListener listener = (BeanContextServiceRevokedListener)entry.getValue();435436if (revokeNow) {437Object requestor = entry.getKey();438Map services = (Map)serviceRequestors.get(requestor);439440if (services != null) {441Iterator i1 = services.entrySet().iterator();442443while (i1.hasNext()) {444Map.Entry tmp = (Map.Entry)i1.next();445446BCSSCServiceRef serviceRef = (BCSSCServiceRef)tmp.getValue();447if (serviceRef.getServiceClassRef().equals(serviceClassRef) && isDelegated == serviceRef.isDelegated()) {448i1.remove();449}450}451452if (noMoreRefs = services.isEmpty()) {453serviceRequestors.remove(requestor);454}455}456457if (noMoreRefs) serviceClassRef.removeRequestor(requestor);458}459460listener.serviceRevoked(bcsre);461}462463if (revokeNow && serviceClasses != null) {464if (serviceClassRef.isEmpty())465serviceClasses.remove(serviceClass);466467if (serviceClasses.isEmpty())468serviceClasses = null;469}470471if (serviceRequestors != null && serviceRequestors.isEmpty())472serviceRequestors = null;473}474475// release all references for this child since it has been unnested.476477void cleanupReferences() {478479if (serviceRequestors == null) return;480481Iterator requestors = serviceRequestors.entrySet().iterator();482483while(requestors.hasNext()) {484Map.Entry tmp = (Map.Entry)requestors.next();485Object requestor = tmp.getKey();486Iterator services = ((Map)tmp.getValue()).entrySet().iterator();487488requestors.remove();489490while (services.hasNext()) {491Map.Entry entry = (Map.Entry)services.next();492Object service = entry.getKey();493BCSSCServiceRef sref = (BCSSCServiceRef)entry.getValue();494495BCSSCServiceClassRef scref = sref.getServiceClassRef();496497BeanContextServiceProvider bcsp = sref.isDelegated() ? scref.getDelegateProvider() : scref.getServiceProvider();498499scref.removeRequestor(requestor);500services.remove();501502while (sref.release() >= 0) {503bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);504}505}506}507508serviceRequestors = null;509serviceClasses = null;510}511512void revokeAllDelegatedServicesNow() {513if (serviceClasses == null) return;514515Iterator serviceClassRefs =516new HashSet(serviceClasses.values()).iterator();517518while (serviceClassRefs.hasNext()) {519BCSSCServiceClassRef serviceClassRef = (BCSSCServiceClassRef)serviceClassRefs.next();520521if (!serviceClassRef.isDelegated()) continue;522523Iterator i = serviceClassRef.cloneOfEntries();524BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClassRef.getServiceClass(), true);525boolean noMoreRefs = false;526527while (i.hasNext()) {528Map.Entry entry = (Map.Entry)i.next();529BeanContextServiceRevokedListener listener = (BeanContextServiceRevokedListener)entry.getValue();530531Object requestor = entry.getKey();532Map services = (Map)serviceRequestors.get(requestor);533534if (services != null) {535Iterator i1 = services.entrySet().iterator();536537while (i1.hasNext()) {538Map.Entry tmp = (Map.Entry)i1.next();539540BCSSCServiceRef serviceRef = (BCSSCServiceRef)tmp.getValue();541if (serviceRef.getServiceClassRef().equals(serviceClassRef) && serviceRef.isDelegated()) {542i1.remove();543}544}545546if (noMoreRefs = services.isEmpty()) {547serviceRequestors.remove(requestor);548}549}550551if (noMoreRefs) serviceClassRef.removeRequestor(requestor);552553listener.serviceRevoked(bcsre);554555if (serviceClassRef.isEmpty())556serviceClasses.remove(serviceClassRef.getServiceClass());557}558}559560if (serviceClasses.isEmpty()) serviceClasses = null;561562if (serviceRequestors != null && serviceRequestors.isEmpty())563serviceRequestors = null;564}565566/*567* fields568*/569570private transient HashMap serviceClasses;571private transient HashMap serviceRequestors;572}573574/**575* <p>576* Subclasses can override this method to insert their own subclass577* of Child without having to override add() or the other Collection578* methods that add children to the set.579* </p>580*581* @param targetChild the child to create the Child on behalf of582* @param peer the peer if the targetChild and peer are related by BeanContextProxy583*/584585protected BCSChild createBCSChild(Object targetChild, Object peer) {586return new BCSSChild(targetChild, peer);587}588589/************************************************************************/590591/**592* subclasses may subclass this nested class to add behaviors for593* each BeanContextServicesProvider.594*/595596protected static class BCSSServiceProvider implements Serializable {597private static final long serialVersionUID = 861278251667444782L;598599BCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp) {600super();601602serviceProvider = bcsp;603}604605/**606* Returns the service provider.607* @return the service provider608*/609protected BeanContextServiceProvider getServiceProvider() {610return serviceProvider;611}612613/**614* The service provider.615*/616617protected BeanContextServiceProvider serviceProvider;618}619620/**621* subclasses can override this method to create new subclasses of622* BCSSServiceProvider without having to override addService() in623* order to instantiate.624* @param sc the class625* @param bcsp the service provider626* @return a service provider without overriding addService()627*/628629protected BCSSServiceProvider createBCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp) {630return new BCSSServiceProvider(sc, bcsp);631}632633/************************************************************************/634635/**636* add a BeanContextServicesListener637*638* @throws NullPointerException if the argument is null639*/640641public void addBeanContextServicesListener(BeanContextServicesListener bcsl) {642if (bcsl == null) throw new NullPointerException("bcsl");643644synchronized(bcsListeners) {645if (bcsListeners.contains(bcsl))646return;647else648bcsListeners.add(bcsl);649}650}651652/**653* remove a BeanContextServicesListener654*/655656public void removeBeanContextServicesListener(BeanContextServicesListener bcsl) {657if (bcsl == null) throw new NullPointerException("bcsl");658659synchronized(bcsListeners) {660if (!bcsListeners.contains(bcsl))661return;662else663bcsListeners.remove(bcsl);664}665}666667/**668* add a service669* @param serviceClass the service class670* @param bcsp the service provider671*/672673public boolean addService(Class serviceClass, BeanContextServiceProvider bcsp) {674return addService(serviceClass, bcsp, true);675}676677/**678* add a service679* @param serviceClass the service class680* @param bcsp the service provider681* @param fireEvent whether or not an event should be fired682* @return true if the service was successfully added683*/684685protected boolean addService(Class serviceClass, BeanContextServiceProvider bcsp, boolean fireEvent) {686687if (serviceClass == null) throw new NullPointerException("serviceClass");688if (bcsp == null) throw new NullPointerException("bcsp");689690synchronized(BeanContext.globalHierarchyLock) {691if (services.containsKey(serviceClass))692return false;693else {694services.put(serviceClass, createBCSSServiceProvider(serviceClass, bcsp));695696if (bcsp instanceof Serializable) serializable++;697698if (!fireEvent) return true;699700701BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);702703fireServiceAdded(bcssae);704705synchronized(children) {706Iterator i = children.keySet().iterator();707708while (i.hasNext()) {709Object c = i.next();710711if (c instanceof BeanContextServices) {712((BeanContextServicesListener)c).serviceAvailable(bcssae);713}714}715}716717return true;718}719}720}721722/**723* remove a service724* @param serviceClass the service class725* @param bcsp the service provider726* @param revokeCurrentServicesNow whether or not to revoke the service727*/728729public void revokeService(Class serviceClass, BeanContextServiceProvider bcsp, boolean revokeCurrentServicesNow) {730731if (serviceClass == null) throw new NullPointerException("serviceClass");732if (bcsp == null) throw new NullPointerException("bcsp");733734synchronized(BeanContext.globalHierarchyLock) {735if (!services.containsKey(serviceClass)) return;736737BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);738739if (!bcsssp.getServiceProvider().equals(bcsp))740throw new IllegalArgumentException("service provider mismatch");741742services.remove(serviceClass);743744if (bcsp instanceof Serializable) serializable--;745746Iterator i = bcsChildren(); // get the BCSChild values.747748while (i.hasNext()) {749((BCSSChild)i.next()).revokeService(serviceClass, false, revokeCurrentServicesNow);750}751752fireServiceRevoked(serviceClass, revokeCurrentServicesNow);753}754}755756/**757* has a service, which may be delegated758*/759760public synchronized boolean hasService(Class serviceClass) {761if (serviceClass == null) throw new NullPointerException("serviceClass");762763synchronized(BeanContext.globalHierarchyLock) {764if (services.containsKey(serviceClass)) return true;765766BeanContextServices bcs = null;767768try {769bcs = (BeanContextServices)getBeanContext();770} catch (ClassCastException cce) {771return false;772}773774return bcs == null ? false : bcs.hasService(serviceClass);775}776}777778/************************************************************************/779780/*781* a nested subclass used to represent a proxy for serviceClasses delegated782* to an enclosing BeanContext.783*/784785protected class BCSSProxyServiceProvider implements BeanContextServiceProvider, BeanContextServiceRevokedListener {786787BCSSProxyServiceProvider(BeanContextServices bcs) {788super();789790nestingCtxt = bcs;791}792793public Object getService(BeanContextServices bcs, Object requestor, Class serviceClass, Object serviceSelector) {794Object service = null;795796try {797service = nestingCtxt.getService(bcs, requestor, serviceClass, serviceSelector, this);798} catch (TooManyListenersException tmle) {799return null;800}801802return service;803}804805public void releaseService(BeanContextServices bcs, Object requestor, Object service) {806nestingCtxt.releaseService(bcs, requestor, service);807}808809public Iterator getCurrentServiceSelectors(BeanContextServices bcs, Class serviceClass) {810return nestingCtxt.getCurrentServiceSelectors(serviceClass);811}812813public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {814Iterator i = bcsChildren(); // get the BCSChild values.815816while (i.hasNext()) {817((BCSSChild)i.next()).revokeService(bcsre.getServiceClass(), true, bcsre.isCurrentServiceInvalidNow());818}819}820821/*822* fields823*/824825private BeanContextServices nestingCtxt;826}827828/************************************************************************/829830/**831* obtain a service which may be delegated832*/833834public Object getService(BeanContextChild child, Object requestor, Class serviceClass, Object serviceSelector, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {835if (child == null) throw new NullPointerException("child");836if (serviceClass == null) throw new NullPointerException("serviceClass");837if (requestor == null) throw new NullPointerException("requestor");838if (bcsrl == null) throw new NullPointerException("bcsrl");839840Object service = null;841BCSSChild bcsc;842BeanContextServices bcssp = getBeanContextServicesPeer();843844synchronized(BeanContext.globalHierarchyLock) {845synchronized(children) { bcsc = (BCSSChild)children.get(child); }846847if (bcsc == null) throw new IllegalArgumentException("not a child of this context"); // not a child ...848849BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);850851if (bcsssp != null) {852BeanContextServiceProvider bcsp = bcsssp.getServiceProvider();853service = bcsp.getService(bcssp, requestor, serviceClass, serviceSelector);854if (service != null) { // do bookkeeping ...855try {856bcsc.usingService(requestor, service, serviceClass, bcsp, false, bcsrl);857} catch (TooManyListenersException tmle) {858bcsp.releaseService(bcssp, requestor, service);859throw tmle;860} catch (UnsupportedOperationException uope) {861bcsp.releaseService(bcssp, requestor, service);862throw uope; // unchecked rt exception863}864865return service;866}867}868869870if (proxy != null) {871872// try to delegate ...873874service = proxy.getService(bcssp, requestor, serviceClass, serviceSelector);875876if (service != null) { // do bookkeeping ...877try {878bcsc.usingService(requestor, service, serviceClass, proxy, true, bcsrl);879} catch (TooManyListenersException tmle) {880proxy.releaseService(bcssp, requestor, service);881throw tmle;882} catch (UnsupportedOperationException uope) {883proxy.releaseService(bcssp, requestor, service);884throw uope; // unchecked rt exception885}886887return service;888}889}890}891892return null;893}894895/**896* release a service897*/898899public void releaseService(BeanContextChild child, Object requestor, Object service) {900if (child == null) throw new NullPointerException("child");901if (requestor == null) throw new NullPointerException("requestor");902if (service == null) throw new NullPointerException("service");903904BCSSChild bcsc;905906synchronized(BeanContext.globalHierarchyLock) {907synchronized(children) { bcsc = (BCSSChild)children.get(child); }908909if (bcsc != null)910bcsc.releaseService(requestor, service);911else912throw new IllegalArgumentException("child actual is not a child of this BeanContext");913}914}915916/**917* @return an iterator for all the currently registered service classes.918*/919920public Iterator getCurrentServiceClasses() {921return new BCSIterator(services.keySet().iterator());922}923924/**925* @return an iterator for all the currently available service selectors926* (if any) available for the specified service.927*/928929public Iterator getCurrentServiceSelectors(Class serviceClass) {930931BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);932933return bcsssp != null ? new BCSIterator(bcsssp.getServiceProvider().getCurrentServiceSelectors(getBeanContextServicesPeer(), serviceClass)) : null;934}935936/**937* BeanContextServicesListener callback, propagates event to all938* currently registered listeners and BeanContextServices children,939* if this BeanContextService does not already implement this service940* itself.941*942* subclasses may override or envelope this method to implement their943* own propagation semantics.944*/945946public void serviceAvailable(BeanContextServiceAvailableEvent bcssae) {947synchronized(BeanContext.globalHierarchyLock) {948if (services.containsKey(bcssae.getServiceClass())) return;949950fireServiceAdded(bcssae);951952Iterator i;953954synchronized(children) {955i = children.keySet().iterator();956}957958while (i.hasNext()) {959Object c = i.next();960961if (c instanceof BeanContextServices) {962((BeanContextServicesListener)c).serviceAvailable(bcssae);963}964}965}966}967968/**969* BeanContextServicesListener callback, propagates event to all970* currently registered listeners and BeanContextServices children,971* if this BeanContextService does not already implement this service972* itself.973*974* subclasses may override or envelope this method to implement their975* own propagation semantics.976*/977978public void serviceRevoked(BeanContextServiceRevokedEvent bcssre) {979synchronized(BeanContext.globalHierarchyLock) {980if (services.containsKey(bcssre.getServiceClass())) return;981982fireServiceRevoked(bcssre);983984Iterator i;985986synchronized(children) {987i = children.keySet().iterator();988}989990while (i.hasNext()) {991Object c = i.next();992993if (c instanceof BeanContextServices) {994((BeanContextServicesListener)c).serviceRevoked(bcssre);995}996}997}998}9991000/**1001* Gets the <tt>BeanContextServicesListener</tt> (if any) of the specified1002* child.1003*1004* @param child the specified child1005* @return the BeanContextServicesListener (if any) of the specified child1006*/1007protected static final BeanContextServicesListener getChildBeanContextServicesListener(Object child) {1008try {1009return (BeanContextServicesListener)child;1010} catch (ClassCastException cce) {1011return null;1012}1013}10141015/**1016* called from superclass child removal operations after a child1017* has been successfully removed. called with child synchronized.1018*1019* This subclass uses this hook to immediately revoke any services1020* being used by this child if it is a BeanContextChild.1021*1022* subclasses may envelope this method in order to implement their1023* own child removal side-effects.1024*/10251026protected void childJustRemovedHook(Object child, BCSChild bcsc) {1027BCSSChild bcssc = (BCSSChild)bcsc;10281029bcssc.cleanupReferences();1030}10311032/**1033* called from setBeanContext to notify a BeanContextChild1034* to release resources obtained from the nesting BeanContext.1035*1036* This method revokes any services obtained from its parent.1037*1038* subclasses may envelope this method to implement their own semantics.1039*/10401041protected synchronized void releaseBeanContextResources() {1042Object[] bcssc;10431044super.releaseBeanContextResources();10451046synchronized(children) {1047if (children.isEmpty()) return;10481049bcssc = children.values().toArray();1050}105110521053for (int i = 0; i < bcssc.length; i++) {1054((BCSSChild)bcssc[i]).revokeAllDelegatedServicesNow();1055}10561057proxy = null;1058}10591060/**1061* called from setBeanContext to notify a BeanContextChild1062* to allocate resources obtained from the nesting BeanContext.1063*1064* subclasses may envelope this method to implement their own semantics.1065*/10661067protected synchronized void initializeBeanContextResources() {1068super.initializeBeanContextResources();10691070BeanContext nbc = getBeanContext();10711072if (nbc == null) return;10731074try {1075BeanContextServices bcs = (BeanContextServices)nbc;10761077proxy = new BCSSProxyServiceProvider(bcs);1078} catch (ClassCastException cce) {1079// do nothing ...1080}1081}10821083/**1084* Fires a <tt>BeanContextServiceEvent</tt> notifying of a new service.1085* @param serviceClass the service class1086*/1087protected final void fireServiceAdded(Class serviceClass) {1088BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);10891090fireServiceAdded(bcssae);1091}10921093/**1094* Fires a <tt>BeanContextServiceAvailableEvent</tt> indicating that a new1095* service has become available.1096*1097* @param bcssae the <tt>BeanContextServiceAvailableEvent</tt>1098*/1099protected final void fireServiceAdded(BeanContextServiceAvailableEvent bcssae) {1100Object[] copy;11011102synchronized (bcsListeners) { copy = bcsListeners.toArray(); }11031104for (int i = 0; i < copy.length; i++) {1105((BeanContextServicesListener)copy[i]).serviceAvailable(bcssae);1106}1107}11081109/**1110* Fires a <tt>BeanContextServiceEvent</tt> notifying of a service being revoked.1111*1112* @param bcsre the <tt>BeanContextServiceRevokedEvent</tt>1113*/1114protected final void fireServiceRevoked(BeanContextServiceRevokedEvent bcsre) {1115Object[] copy;11161117synchronized (bcsListeners) { copy = bcsListeners.toArray(); }11181119for (int i = 0; i < copy.length; i++) {1120((BeanContextServiceRevokedListener)copy[i]).serviceRevoked(bcsre);1121}1122}11231124/**1125* Fires a <tt>BeanContextServiceRevokedEvent</tt>1126* indicating that a particular service is1127* no longer available.1128* @param serviceClass the service class1129* @param revokeNow whether or not the event should be revoked now1130*/1131protected final void fireServiceRevoked(Class serviceClass, boolean revokeNow) {1132Object[] copy;1133BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(getBeanContextServicesPeer(), serviceClass, revokeNow);11341135synchronized (bcsListeners) { copy = bcsListeners.toArray(); }11361137for (int i = 0; i < copy.length; i++) {1138((BeanContextServicesListener)copy[i]).serviceRevoked(bcsre);1139}1140}11411142/**1143* called from BeanContextSupport writeObject before it serializes the1144* children ...1145*1146* This class will serialize any Serializable BeanContextServiceProviders1147* herein.1148*1149* subclasses may envelope this method to insert their own serialization1150* processing that has to occur prior to serialization of the children1151*/11521153protected synchronized void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {11541155oos.writeInt(serializable);11561157if (serializable <= 0) return;11581159int count = 0;11601161Iterator i = services.entrySet().iterator();11621163while (i.hasNext() && count < serializable) {1164Map.Entry entry = (Map.Entry)i.next();1165BCSSServiceProvider bcsp = null;11661167try {1168bcsp = (BCSSServiceProvider)entry.getValue();1169} catch (ClassCastException cce) {1170continue;1171}11721173if (bcsp.getServiceProvider() instanceof Serializable) {1174oos.writeObject(entry.getKey());1175oos.writeObject(bcsp);1176count++;1177}1178}11791180if (count != serializable)1181throw new IOException("wrote different number of service providers than expected");1182}11831184/**1185* called from BeanContextSupport readObject before it deserializes the1186* children ...1187*1188* This class will deserialize any Serializable BeanContextServiceProviders1189* serialized earlier thus making them available to the children when they1190* deserialized.1191*1192* subclasses may envelope this method to insert their own serialization1193* processing that has to occur prior to serialization of the children1194*/11951196protected synchronized void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {11971198serializable = ois.readInt();11991200int count = serializable;12011202while (count > 0) {1203services.put(ois.readObject(), ois.readObject());1204count--;1205}1206}12071208/**1209* serialize the instance1210*/12111212private synchronized void writeObject(ObjectOutputStream oos) throws IOException {1213oos.defaultWriteObject();12141215serialize(oos, (Collection)bcsListeners);1216}12171218/**1219* deserialize the instance1220*/12211222private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {12231224ois.defaultReadObject();12251226deserialize(ois, (Collection)bcsListeners);1227}122812291230/*1231* fields1232*/12331234/**1235* all accesses to the <code> protected transient HashMap services </code>1236* field should be synchronized on that object1237*/1238protected transient HashMap services;12391240/**1241* The number of instances of a serializable <tt>BeanContextServceProvider</tt>.1242*/1243protected transient int serializable = 0;124412451246/**1247* Delegate for the <tt>BeanContextServiceProvider</tt>.1248*/1249protected transient BCSSProxyServiceProvider proxy;125012511252/**1253* List of <tt>BeanContextServicesListener</tt> objects.1254*/1255protected transient ArrayList bcsListeners;1256}125712581259