History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/beans/beancontext/BeanContextServicesSupport.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/beans/beancontext/BeanContextServicesSupport.java+1238−0
@@ -0,0 +1,1238 @@
1+/*
2+ * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package java.beans.beancontext;
27+
28+import java.util.ArrayList;
29+import java.util.Collection;
30+import java.util.HashMap;
31+import java.util.HashSet;
32+import java.util.Iterator;
33+import java.util.Map;
34+import java.util.Map.Entry;
35+
36+import java.io.IOException;
37+import java.io.ObjectInputStream;
38+import java.io.ObjectOutputStream;
39+import java.io.Serializable;
40+
41+import java.util.TooManyListenersException;
42+
43+import java.util.Locale;
44+
45+/**
46+ * <p>
47+ * This helper class provides a utility implementation of the
48+ * java.beans.beancontext.BeanContextServices interface.
49+ * </p>
50+ * <p>
51+ * Since this class directly implements the BeanContextServices interface,
52+ * the class can, and is intended to be used either by subclassing this
53+ * implementation, or via delegation of an instance of this class
54+ * from another through the BeanContextProxy interface.
55+ * </p>
56+ *
57+ * @author Laurence P. G. Cable
58+ * @since 1.2
59+ */
60+
61+public class BeanContextServicesSupport extends BeanContextSupport
62+ implements BeanContextServices {
63+ private static final long serialVersionUID = -8494482757288719206L;
64+
65+ /**
66+ * <p>
67+ * Construct a BeanContextServicesSupport instance
68+ * </p>
69+ *
70+ * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
71+ * @param lcle The current Locale for this BeanContext.
72+ * @param dTime The initial state, true if in design mode, false if runtime.
73+ * @param visible The initial visibility.
74+ *
75+ */
76+
77+ public BeanContextServicesSupport(BeanContextServices peer, Locale lcle, boolean dTime, boolean visible) {
78+ super(peer, lcle, dTime, visible);
79+ }
80+
81+ /**
82+ * Create an instance using the specified Locale and design mode.
83+ *
84+ * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
85+ * @param lcle The current Locale for this BeanContext.
86+ * @param dtime The initial state, true if in design mode, false if runtime.
87+ */
88+
89+ public BeanContextServicesSupport(BeanContextServices peer, Locale lcle, boolean dtime) {
90+ this (peer, lcle, dtime, true);
91+ }
92+
93+ /**
94+ * Create an instance using the specified locale
95+ *
96+ * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
97+ * @param lcle The current Locale for this BeanContext.
98+ */
99+
100+ public BeanContextServicesSupport(BeanContextServices peer, Locale lcle) {
101+ this (peer, lcle, false, true);
102+ }
103+
104+ /**
105+ * Create an instance with a peer
106+ *
107+ * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
108+ */
109+
110+ public BeanContextServicesSupport(BeanContextServices peer) {
111+ this (peer, null, false, true);
112+ }
113+
114+ /**
115+ * Create an instance that is not a delegate of another object
116+ */
117+
118+ public BeanContextServicesSupport() {
119+ this (null, null, false, true);
120+ }
121+
122+ /**
123+ * called by BeanContextSupport superclass during construction and
124+ * deserialization to initialize subclass transient state.
125+ *
126+ * subclasses may envelope this method, but should not override it or
127+ * call it directly.
128+ */
129+
130+ public void initialize() {
131+ super.initialize();
132+
133+ services = new HashMap(serializable + 1);
134+ bcsListeners = new ArrayList(1);
135+ }
136+
137+ /**
138+ * Gets the <tt>BeanContextServices</tt> associated with this
139+ * <tt>BeanContextServicesSupport</tt>.
140+ *
141+ * @return the instance of <tt>BeanContext</tt>
142+ * this object is providing the implementation for.
143+ */
144+ public BeanContextServices getBeanContextServicesPeer() {
145+ return (BeanContextServices)getBeanContextChildPeer();
146+ }
147+
148+ /************************************************************************/
149+
150+ /*
151+ * protected nested class containing per child information, an instance
152+ * of which is associated with each child in the "children" hashtable.
153+ * subclasses can extend this class to include their own per-child state.
154+ *
155+ * Note that this 'value' is serialized with the corresponding child 'key'
156+ * when the BeanContextSupport is serialized.
157+ */
158+
159+ protected class BCSSChild extends BeanContextSupport.BCSChild {
160+
161+ private static final long serialVersionUID = -3263851306889194873L;
162+
163+ /*
164+ * private nested class to map serviceClass to Provider and requestors
165+ * listeners.
166+ */
167+
168+ class BCSSCServiceClassRef {
169+
170+ // create an instance of a service ref
171+
172+ BCSSCServiceClassRef(Class sc, BeanContextServiceProvider bcsp, boolean delegated) {
173+ super();
174+
175+ serviceClass = sc;
176+
177+ if (delegated)
178+ delegateProvider = bcsp;
179+ else
180+ serviceProvider = bcsp;
181+ }
182+
183+ // add a requestor and assoc listener
184+
185+ void addRequestor(Object requestor, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
186+ BeanContextServiceRevokedListener cbcsrl = (BeanContextServiceRevokedListener)requestors.get(requestor);
187+
188+ if (cbcsrl != null && !cbcsrl.equals(bcsrl))
189+ throw new TooManyListenersException();
190+
191+ requestors.put(requestor, bcsrl);
192+ }
193+
194+ // remove a requestor
195+
196+ void removeRequestor(Object requestor) {
197+ requestors.remove(requestor);
198+ }
199+
200+ // check a requestors listener
201+
202+ void verifyRequestor(Object requestor, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
203+ BeanContextServiceRevokedListener cbcsrl = (BeanContextServiceRevokedListener)requestors.get(requestor);
204+
205+ if (cbcsrl != null && !cbcsrl.equals(bcsrl))
206+ throw new TooManyListenersException();
207+ }
208+
209+ void verifyAndMaybeSetProvider(BeanContextServiceProvider bcsp, boolean isDelegated) {
210+ BeanContextServiceProvider current;
211+
212+ if (isDelegated) { // the provider is delegated
213+ current = delegateProvider;
214+
215+ if (current == null || bcsp == null) {
216+ delegateProvider = bcsp;
217+ return;
218+ }
219+ } else { // the provider is registered with this BCS
220+ current = serviceProvider;
221+
222+ if (current == null || bcsp == null) {
223+ serviceProvider = bcsp;
224+ return;
225+ }
226+ }
227+
228+ if (!current.equals(bcsp))
229+ throw new UnsupportedOperationException("existing service reference obtained from different BeanContextServiceProvider not supported");
230+
231+ }
232+
233+ Iterator cloneOfEntries() {
234+ return ((HashMap)requestors.clone()).entrySet().iterator();
235+ }
236+
237+ Iterator entries() { return requestors.entrySet().iterator(); }
238+
239+ boolean isEmpty() { return requestors.isEmpty(); }
240+
241+ Class getServiceClass() { return serviceClass; }
242+
243+ BeanContextServiceProvider getServiceProvider() {
244+ return serviceProvider;
245+ }
246+
247+ BeanContextServiceProvider getDelegateProvider() {
248+ return delegateProvider;
249+ }
250+
251+ boolean isDelegated() { return delegateProvider != null; }
252+
253+ void addRef(boolean delegated) {
254+ if (delegated) {
255+ delegateRefs++;
256+ } else {
257+ serviceRefs++;
258+ }
259+ }
260+
261+
262+ void releaseRef(boolean delegated) {
263+ if (delegated) {
264+ if (--delegateRefs == 0) {
265+ delegateProvider = null;
266+ }
267+ } else {
268+ if (--serviceRefs <= 0) {
269+ serviceProvider = null;
270+ }
271+ }
272+ }
273+
274+ int getRefs() { return serviceRefs + delegateRefs; }
275+
276+ int getDelegateRefs() { return delegateRefs; }
277+
278+ int getServiceRefs() { return serviceRefs; }
279+
280+ /*
281+ * fields
282+ */
283+
284+ Class serviceClass;
285+
286+ BeanContextServiceProvider serviceProvider;
287+ int serviceRefs;
288+
289+ BeanContextServiceProvider delegateProvider; // proxy
290+ int delegateRefs;
291+
292+ HashMap requestors = new HashMap(1);
293+ }
294+
295+ /*
296+ * per service reference info ...
297+ */
298+
299+ class BCSSCServiceRef {
300+ BCSSCServiceRef(BCSSCServiceClassRef scref, boolean isDelegated) {
301+ serviceClassRef = scref;
302+ delegated = isDelegated;
303+ }
304+
305+ void addRef() { refCnt++; }
306+ int release() { return --refCnt; }
307+
308+ BCSSCServiceClassRef getServiceClassRef() { return serviceClassRef; }
309+
310+ boolean isDelegated() { return delegated; }
311+
312+ /*
313+ * fields
314+ */
315+
316+ BCSSCServiceClassRef serviceClassRef;
317+ int refCnt = 1;
318+ boolean delegated = false;
319+ }
320+
321+ BCSSChild(Object bcc, Object peer) { super(bcc, peer); }
322+
323+ // note usage of service per requestor, per service
324+
325+ synchronized void usingService(Object requestor, Object service, Class serviceClass, BeanContextServiceProvider bcsp, boolean isDelegated, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException, UnsupportedOperationException {
326+
327+ // first, process mapping from serviceClass to requestor(s)
328+
329+ BCSSCServiceClassRef serviceClassRef = null;
330+
331+ if (serviceClasses == null)
332+ serviceClasses = new HashMap(1);
333+ else
334+ serviceClassRef = (BCSSCServiceClassRef)serviceClasses.get(serviceClass);
335+
336+ if (serviceClassRef == null) { // new service being used ...
337+ serviceClassRef = new BCSSCServiceClassRef(serviceClass, bcsp, isDelegated);
338+ serviceClasses.put(serviceClass, serviceClassRef);
339+
340+ } else { // existing service ...
341+ serviceClassRef.verifyAndMaybeSetProvider(bcsp, isDelegated); // throws
342+ serviceClassRef.verifyRequestor(requestor, bcsrl); // throws
343+ }
344+
345+ serviceClassRef.addRequestor(requestor, bcsrl);
346+ serviceClassRef.addRef(isDelegated);
347+
348+ // now handle mapping from requestor to service(s)
349+
350+ BCSSCServiceRef serviceRef = null;
351+ Map services = null;
352+
353+ if (serviceRequestors == null) {
354+ serviceRequestors = new HashMap(1);
355+ } else {
356+ services = (Map)serviceRequestors.get(requestor);
357+ }
358+
359+ if (services == null) {
360+ services = new HashMap(1);
361+
362+ serviceRequestors.put(requestor, services);
363+ } else
364+ serviceRef = (BCSSCServiceRef)services.get(service);
365+
366+ if (serviceRef == null) {
367+ serviceRef = new BCSSCServiceRef(serviceClassRef, isDelegated);
368+
369+ services.put(service, serviceRef);
370+ } else {
371+ serviceRef.addRef();
372+ }
373+ }
374+
375+ // release a service reference
376+
377+ synchronized void releaseService(Object requestor, Object service) {
378+ if (serviceRequestors == null) return;
379+
380+ Map services = (Map)serviceRequestors.get(requestor);
381+
382+ if (services == null) return; // oops its not there anymore!
383+
384+ BCSSCServiceRef serviceRef = (BCSSCServiceRef)services.get(service);
385+
386+ if (serviceRef == null) return; // oops its not there anymore!
387+
388+ BCSSCServiceClassRef serviceClassRef = serviceRef.getServiceClassRef();
389+ boolean isDelegated = serviceRef.isDelegated();
390+ BeanContextServiceProvider bcsp = isDelegated ? serviceClassRef.getDelegateProvider() : serviceClassRef.getServiceProvider();
391+
392+ bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);
393+
394+ serviceClassRef.releaseRef(isDelegated);
395+ serviceClassRef.removeRequestor(requestor);
396+
397+ if (serviceRef.release() == 0) {
398+
399+ services.remove(service);
400+
401+ if (services.isEmpty()) {
402+ serviceRequestors.remove(requestor);
403+ serviceClassRef.removeRequestor(requestor);
404+ }
405+
406+ if (serviceRequestors.isEmpty()) {
407+ serviceRequestors = null;
408+ }
409+
410+ if (serviceClassRef.isEmpty()) {
411+ serviceClasses.remove(serviceClassRef.getServiceClass());
412+ }
413+
414+ if (serviceClasses.isEmpty())
415+ serviceClasses = null;
416+ }
417+ }
418+
419+ // revoke a service
420+
421+ synchronized void revokeService(Class serviceClass, boolean isDelegated, boolean revokeNow) {
422+ if (serviceClasses == null) return;
423+
424+ BCSSCServiceClassRef serviceClassRef = (BCSSCServiceClassRef)serviceClasses.get(serviceClass);
425+
426+ if (serviceClassRef == null) return;
427+
428+ Iterator i = serviceClassRef.cloneOfEntries();
429+
430+ BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClass, revokeNow);
431+ boolean noMoreRefs = false;
432+
433+ while (i.hasNext() && serviceRequestors != null) {
434+ Map.Entry entry = (Map.Entry)i.next();
435+ BeanContextServiceRevokedListener listener = (BeanContextServiceRevokedListener)entry.getValue();
436+
437+ if (revokeNow) {
438+ Object requestor = entry.getKey();
439+ Map services = (Map)serviceRequestors.get(requestor);
440+
441+ if (services != null) {
442+ Iterator i1 = services.entrySet().iterator();
443+
444+ while (i1.hasNext()) {
445+ Map.Entry tmp = (Map.Entry)i1.next();
446+
447+ BCSSCServiceRef serviceRef = (BCSSCServiceRef)tmp.getValue();
448+ if (serviceRef.getServiceClassRef().equals(serviceClassRef) && isDelegated == serviceRef.isDelegated()) {
449+ i1.remove();
450+ }
451+ }
452+
453+ if (noMoreRefs = services.isEmpty()) {
454+ serviceRequestors.remove(requestor);
455+ }
456+ }
457+
458+ if (noMoreRefs) serviceClassRef.removeRequestor(requestor);
459+ }
460+
461+ listener.serviceRevoked(bcsre);
462+ }
463+
464+ if (revokeNow && serviceClasses != null) {
465+ if (serviceClassRef.isEmpty())
466+ serviceClasses.remove(serviceClass);
467+
468+ if (serviceClasses.isEmpty())
469+ serviceClasses = null;
470+ }
471+
472+ if (serviceRequestors != null && serviceRequestors.isEmpty())
473+ serviceRequestors = null;
474+ }
475+
476+ // release all references for this child since it has been unnested.
477+
478+ void cleanupReferences() {
479+
480+ if (serviceRequestors == null) return;
481+
482+ Iterator requestors = serviceRequestors.entrySet().iterator();
483+
484+ while(requestors.hasNext()) {
485+ Map.Entry tmp = (Map.Entry)requestors.next();
486+ Object requestor = tmp.getKey();
487+ Iterator services = ((Map)tmp.getValue()).entrySet().iterator();
488+
489+ requestors.remove();
490+
491+ while (services.hasNext()) {
492+ Map.Entry entry = (Map.Entry)services.next();
493+ Object service = entry.getKey();
494+ BCSSCServiceRef sref = (BCSSCServiceRef)entry.getValue();
495+
496+ BCSSCServiceClassRef scref = sref.getServiceClassRef();
497+
498+ BeanContextServiceProvider bcsp = sref.isDelegated() ? scref.getDelegateProvider() : scref.getServiceProvider();
499+
500+ scref.removeRequestor(requestor);
501+ services.remove();
502+
503+ while (sref.release() >= 0) {
504+ bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);
505+ }
506+ }
507+ }
508+
509+ serviceRequestors = null;
510+ serviceClasses = null;
511+ }
512+
513+ void revokeAllDelegatedServicesNow() {
514+ if (serviceClasses == null) return;
515+
516+ Iterator serviceClassRefs =
517+ new HashSet(serviceClasses.values()).iterator();
518+
519+ while (serviceClassRefs.hasNext()) {
520+ BCSSCServiceClassRef serviceClassRef = (BCSSCServiceClassRef)serviceClassRefs.next();
521+
522+ if (!serviceClassRef.isDelegated()) continue;
523+
524+ Iterator i = serviceClassRef.cloneOfEntries();
525+ BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClassRef.getServiceClass(), true);
526+ boolean noMoreRefs = false;
527+
528+ while (i.hasNext()) {
529+ Map.Entry entry = (Map.Entry)i.next();
530+ BeanContextServiceRevokedListener listener = (BeanContextServiceRevokedListener)entry.getValue();
531+
532+ Object requestor = entry.getKey();
533+ Map services = (Map)serviceRequestors.get(requestor);
534+
535+ if (services != null) {
536+ Iterator i1 = services.entrySet().iterator();
537+
538+ while (i1.hasNext()) {
539+ Map.Entry tmp = (Map.Entry)i1.next();
540+
541+ BCSSCServiceRef serviceRef = (BCSSCServiceRef)tmp.getValue();
542+ if (serviceRef.getServiceClassRef().equals(serviceClassRef) && serviceRef.isDelegated()) {
543+ i1.remove();
544+ }
545+ }
546+
547+ if (noMoreRefs = services.isEmpty()) {
548+ serviceRequestors.remove(requestor);
549+ }
550+ }
551+
552+ if (noMoreRefs) serviceClassRef.removeRequestor(requestor);
553+
554+ listener.serviceRevoked(bcsre);
555+
556+ if (serviceClassRef.isEmpty())
557+ serviceClasses.remove(serviceClassRef.getServiceClass());
558+ }
559+ }
560+
561+ if (serviceClasses.isEmpty()) serviceClasses = null;
562+
563+ if (serviceRequestors != null && serviceRequestors.isEmpty())
564+ serviceRequestors = null;
565+ }
566+
567+ /*
568+ * fields
569+ */
570+
571+ private transient HashMap serviceClasses;
572+ private transient HashMap serviceRequestors;
573+ }
574+
575+ /**
576+ * <p>
577+ * Subclasses can override this method to insert their own subclass
578+ * of Child without having to override add() or the other Collection
579+ * methods that add children to the set.
580+ * </p>
581+ *
582+ * @param targetChild the child to create the Child on behalf of
583+ * @param peer the peer if the targetChild and peer are related by BeanContextProxy
584+ */
585+
586+ protected BCSChild createBCSChild(Object targetChild, Object peer) {
587+ return new BCSSChild(targetChild, peer);
588+ }
589+
590+ /************************************************************************/
591+
592+ /**
593+ * subclasses may subclass this nested class to add behaviors for
594+ * each BeanContextServicesProvider.
595+ */
596+
597+ protected static class BCSSServiceProvider implements Serializable {
598+ private static final long serialVersionUID = 861278251667444782L;
599+
600+ BCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp) {
601+ super();
602+
603+ serviceProvider = bcsp;
604+ }
605+
606+ protected BeanContextServiceProvider getServiceProvider() {
607+ return serviceProvider;
608+ }
609+
610+ /*
611+ * fields
612+ */
613+
614+ protected BeanContextServiceProvider serviceProvider;
615+ }
616+
617+ /**
618+ * subclasses can override this method to create new subclasses of
619+ * BCSSServiceProvider without having to overrride addService() in
620+ * order to instantiate.
621+ */
622+
623+ protected BCSSServiceProvider createBCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp) {
624+ return new BCSSServiceProvider(sc, bcsp);
625+ }
626+
627+ /************************************************************************/
628+
629+ /**
630+ * add a BeanContextServicesListener
631+ *
632+ * @throws NullPointerException
633+ */
634+
635+ public void addBeanContextServicesListener(BeanContextServicesListener bcsl) {
636+ if (bcsl == null) throw new NullPointerException("bcsl");
637+
638+ synchronized(bcsListeners) {
639+ if (bcsListeners.contains(bcsl))
640+ return;
641+ else
642+ bcsListeners.add(bcsl);
643+ }
644+ }
645+
646+ /**
647+ * remove a BeanContextServicesListener
648+ */
649+
650+ public void removeBeanContextServicesListener(BeanContextServicesListener bcsl) {
651+ if (bcsl == null) throw new NullPointerException("bcsl");
652+
653+ synchronized(bcsListeners) {
654+ if (!bcsListeners.contains(bcsl))
655+ return;
656+ else
657+ bcsListeners.remove(bcsl);
658+ }
659+ }
660+
661+ /**
662+ * add a service
663+ */
664+
665+ public boolean addService(Class serviceClass, BeanContextServiceProvider bcsp) {
666+ return addService(serviceClass, bcsp, true);
667+ }
668+
669+ /**
670+ * add a service
671+ */
672+
673+ protected boolean addService(Class serviceClass, BeanContextServiceProvider bcsp, boolean fireEvent) {
674+
675+ if (serviceClass == null) throw new NullPointerException("serviceClass");
676+ if (bcsp == null) throw new NullPointerException("bcsp");
677+
678+ synchronized(BeanContext.globalHierarchyLock) {
679+ if (services.containsKey(serviceClass))
680+ return false;
681+ else {
682+ services.put(serviceClass, createBCSSServiceProvider(serviceClass, bcsp));
683+
684+ if (bcsp instanceof Serializable) serializable++;
685+
686+ if (!fireEvent) return true;
687+
688+
689+ BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);
690+
691+ fireServiceAdded(bcssae);
692+
693+ synchronized(children) {
694+ Iterator i = children.keySet().iterator();
695+
696+ while (i.hasNext()) {
697+ Object c = i.next();
698+
699+ if (c instanceof BeanContextServices) {
700+ ((BeanContextServicesListener)c).serviceAvailable(bcssae);
701+ }
702+ }
703+ }
704+
705+ return true;
706+ }
707+ }
708+ }
709+
710+ /**
711+ * remove a service
712+ */
713+
714+ public void revokeService(Class serviceClass, BeanContextServiceProvider bcsp, boolean revokeCurrentServicesNow) {
715+
716+ if (serviceClass == null) throw new NullPointerException("serviceClass");
717+ if (bcsp == null) throw new NullPointerException("bcsp");
718+
719+ synchronized(BeanContext.globalHierarchyLock) {
720+ if (!services.containsKey(serviceClass)) return;
721+
722+ BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
723+
724+ if (!bcsssp.getServiceProvider().equals(bcsp))
725+ throw new IllegalArgumentException("service provider mismatch");
726+
727+ services.remove(serviceClass);
728+
729+ if (bcsp instanceof Serializable) serializable--;
730+
731+ Iterator i = bcsChildren(); // get the BCSChild values.
732+
733+ while (i.hasNext()) {
734+ ((BCSSChild)i.next()).revokeService(serviceClass, false, revokeCurrentServicesNow);
735+ }
736+
737+ fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
738+ }
739+ }
740+
741+ /**
742+ * has a service, which may be delegated
743+ */
744+
745+ public synchronized boolean hasService(Class serviceClass) {
746+ if (serviceClass == null) throw new NullPointerException("serviceClass");
747+
748+ synchronized(BeanContext.globalHierarchyLock) {
749+ if (services.containsKey(serviceClass)) return true;
750+
751+ BeanContextServices bcs = null;
752+
753+ try {
754+ bcs = (BeanContextServices)getBeanContext();
755+ } catch (ClassCastException cce) {
756+ return false;
757+ }
758+
759+ return bcs == null ? false : bcs.hasService(serviceClass);
760+ }
761+ }
762+
763+ /************************************************************************/
764+
765+ /*
766+ * a nested subclass used to represent a proxy for serviceClasses delegated
767+ * to an enclosing BeanContext.
768+ */
769+
770+ protected class BCSSProxyServiceProvider implements BeanContextServiceProvider, BeanContextServiceRevokedListener {
771+
772+ BCSSProxyServiceProvider(BeanContextServices bcs) {
773+ super();
774+
775+ nestingCtxt = bcs;
776+ }
777+
778+ public Object getService(BeanContextServices bcs, Object requestor, Class serviceClass, Object serviceSelector) {
779+ Object service = null;
780+
781+ try {
782+ service = nestingCtxt.getService(bcs, requestor, serviceClass, serviceSelector, this);
783+ } catch (TooManyListenersException tmle) {
784+ return null;
785+ }
786+
787+ return service;
788+ }
789+
790+ public void releaseService(BeanContextServices bcs, Object requestor, Object service) {
791+ nestingCtxt.releaseService(bcs, requestor, service);
792+ }
793+
794+ public Iterator getCurrentServiceSelectors(BeanContextServices bcs, Class serviceClass) {
795+ return nestingCtxt.getCurrentServiceSelectors(serviceClass);
796+ }
797+
798+ public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
799+ Iterator i = bcsChildren(); // get the BCSChild values.
800+
801+ while (i.hasNext()) {
802+ ((BCSSChild)i.next()).revokeService(bcsre.getServiceClass(), true, bcsre.isCurrentServiceInvalidNow());
803+ }
804+ }
805+
806+ /*
807+ * fields
808+ */
809+
810+ private BeanContextServices nestingCtxt;
811+ }
812+
813+ /************************************************************************/
814+
815+ /**
816+ * obtain a service which may be delegated
817+ */
818+
819+ public Object getService(BeanContextChild child, Object requestor, Class serviceClass, Object serviceSelector, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
820+ if (child == null) throw new NullPointerException("child");
821+ if (serviceClass == null) throw new NullPointerException("serviceClass");
822+ if (requestor == null) throw new NullPointerException("requestor");
823+ if (bcsrl == null) throw new NullPointerException("bcsrl");
824+
825+ Object service = null;
826+ BCSSChild bcsc;
827+ BeanContextServices bcssp = getBeanContextServicesPeer();
828+
829+ synchronized(BeanContext.globalHierarchyLock) {
830+ synchronized(children) { bcsc = (BCSSChild)children.get(child); }
831+
832+ if (bcsc == null) throw new IllegalArgumentException("not a child of this context"); // not a child ...
833+
834+ BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
835+
836+ if (bcsssp != null) {
837+ BeanContextServiceProvider bcsp = bcsssp.getServiceProvider();
838+ service = bcsp.getService(bcssp, requestor, serviceClass, serviceSelector);
839+ if (service != null) { // do bookkeeping ...
840+ try {
841+ bcsc.usingService(requestor, service, serviceClass, bcsp, false, bcsrl);
842+ } catch (TooManyListenersException tmle) {
843+ bcsp.releaseService(bcssp, requestor, service);
844+ throw tmle;
845+ } catch (UnsupportedOperationException uope) {
846+ bcsp.releaseService(bcssp, requestor, service);
847+ throw uope; // unchecked rt exception
848+ }
849+
850+ return service;
851+ }
852+ }
853+
854+
855+ if (proxy != null) {
856+
857+ // try to delegate ...
858+
859+ service = proxy.getService(bcssp, requestor, serviceClass, serviceSelector);
860+
861+ if (service != null) { // do bookkeeping ...
862+ try {
863+ bcsc.usingService(requestor, service, serviceClass, proxy, true, bcsrl);
864+ } catch (TooManyListenersException tmle) {
865+ proxy.releaseService(bcssp, requestor, service);
866+ throw tmle;
867+ } catch (UnsupportedOperationException uope) {
868+ proxy.releaseService(bcssp, requestor, service);
869+ throw uope; // unchecked rt exception
870+ }
871+
872+ return service;
873+ }
874+ }
875+ }
876+
877+ return null;
878+ }
879+
880+ /**
881+ * release a service
882+ */
883+
884+ public void releaseService(BeanContextChild child, Object requestor, Object service) {
885+ if (child == null) throw new NullPointerException("child");
886+ if (requestor == null) throw new NullPointerException("requestor");
887+ if (service == null) throw new NullPointerException("service");
888+
889+ BCSSChild bcsc;
890+
891+ synchronized(BeanContext.globalHierarchyLock) {
892+ synchronized(children) { bcsc = (BCSSChild)children.get(child); }
893+
894+ if (bcsc != null)
895+ bcsc.releaseService(requestor, service);
896+ else
897+ throw new IllegalArgumentException("child actual is not a child of this BeanContext");
898+ }
899+ }
900+
901+ /**
902+ * @return an iterator for all the currently registered service classes.
903+ */
904+
905+ public Iterator getCurrentServiceClasses() {
906+ return new BCSIterator(services.keySet().iterator());
907+ }
908+
909+ /**
910+ * @return an iterator for all the currently available service selectors
911+ * (if any) available for the specified service.
912+ */
913+
914+ public Iterator getCurrentServiceSelectors(Class serviceClass) {
915+
916+ BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
917+
918+ return bcsssp != null ? new BCSIterator(bcsssp.getServiceProvider().getCurrentServiceSelectors(getBeanContextServicesPeer(), serviceClass)) : null;
919+ }
920+
921+ /**
922+ * BeanContextServicesListener callback, propagates event to all
923+ * currently registered listeners and BeanContextServices children,
924+ * if this BeanContextService does not already implement this service
925+ * itself.
926+ *
927+ * subclasses may override or envelope this method to implement their
928+ * own propagation semantics.
929+ */
930+
931+ public void serviceAvailable(BeanContextServiceAvailableEvent bcssae) {
932+ synchronized(BeanContext.globalHierarchyLock) {
933+ if (services.containsKey(bcssae.getServiceClass())) return;
934+
935+ fireServiceAdded(bcssae);
936+
937+ Iterator i;
938+
939+ synchronized(children) {
940+ i = children.keySet().iterator();
941+ }
942+
943+ while (i.hasNext()) {
944+ Object c = i.next();
945+
946+ if (c instanceof BeanContextServices) {
947+ ((BeanContextServicesListener)c).serviceAvailable(bcssae);
948+ }
949+ }
950+ }
951+ }
952+
953+ /**
954+ * BeanContextServicesListener callback, propagates event to all
955+ * currently registered listeners and BeanContextServices children,
956+ * if this BeanContextService does not already implement this service
957+ * itself.
958+ *
959+ * subclasses may override or envelope this method to implement their
960+ * own propagation semantics.
961+ */
962+
963+ public void serviceRevoked(BeanContextServiceRevokedEvent bcssre) {
964+ synchronized(BeanContext.globalHierarchyLock) {
965+ if (services.containsKey(bcssre.getServiceClass())) return;
966+
967+ fireServiceRevoked(bcssre);
968+
969+ Iterator i;
970+
971+ synchronized(children) {
972+ i = children.keySet().iterator();
973+ }
974+
975+ while (i.hasNext()) {
976+ Object c = i.next();
977+
978+ if (c instanceof BeanContextServices) {
979+ ((BeanContextServicesListener)c).serviceRevoked(bcssre);
980+ }
981+ }
982+ }
983+ }
984+
985+ /**
986+ * Gets the <tt>BeanContextServicesListener</tt> (if any) of the specified
987+ * child.
988+ *
989+ * @param child the specified child
990+ * @return the BeanContextServicesListener (if any) of the specified child
991+ */
992+ protected static final BeanContextServicesListener getChildBeanContextServicesListener(Object child) {
993+ try {
994+ return (BeanContextServicesListener)child;
995+ } catch (ClassCastException cce) {
996+ return null;
997+ }
998+ }
999+
1000+ /**
1001+ * called from superclass child removal operations after a child
1002+ * has been successfully removed. called with child synchronized.
1003+ *
1004+ * This subclass uses this hook to immediately revoke any services
1005+ * being used by this child if it is a BeanContextChild.
1006+ *
1007+ * subclasses may envelope this method in order to implement their
1008+ * own child removal side-effects.
1009+ */
1010+
1011+ protected void childJustRemovedHook(Object child, BCSChild bcsc) {
1012+ BCSSChild bcssc = (BCSSChild)bcsc;
1013+
1014+ bcssc.cleanupReferences();
1015+ }
1016+
1017+ /**
1018+ * called from setBeanContext to notify a BeanContextChild
1019+ * to release resources obtained from the nesting BeanContext.
1020+ *
1021+ * This method revokes any services obtained from its parent.
1022+ *
1023+ * subclasses may envelope this method to implement their own semantics.
1024+ */
1025+
1026+ protected synchronized void releaseBeanContextResources() {
1027+ Object[] bcssc;
1028+
1029+ super.releaseBeanContextResources();
1030+
1031+ synchronized(children) {
1032+ if (children.isEmpty()) return;
1033+
1034+ bcssc = children.values().toArray();
1035+ }
1036+
1037+
1038+ for (int i = 0; i < bcssc.length; i++) {
1039+ ((BCSSChild)bcssc[i]).revokeAllDelegatedServicesNow();
1040+ }
1041+
1042+ proxy = null;
1043+ }
1044+
1045+ /**
1046+ * called from setBeanContext to notify a BeanContextChild
1047+ * to allocate resources obtained from the nesting BeanContext.
1048+ *
1049+ * subclasses may envelope this method to implement their own semantics.
1050+ */
1051+
1052+ protected synchronized void initializeBeanContextResources() {
1053+ super.initializeBeanContextResources();
1054+
1055+ BeanContext nbc = getBeanContext();
1056+
1057+ if (nbc == null) return;
1058+
1059+ try {
1060+ BeanContextServices bcs = (BeanContextServices)nbc;
1061+
1062+ proxy = new BCSSProxyServiceProvider(bcs);
1063+ } catch (ClassCastException cce) {
1064+ // do nothing ...
1065+ }
1066+ }
1067+
1068+ /**
1069+ * Fires a <tt>BeanContextServiceEvent</tt> notifying of a new service.
1070+ */
1071+ protected final void fireServiceAdded(Class serviceClass) {
1072+ BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);
1073+
1074+ fireServiceAdded(bcssae);
1075+ }
1076+
1077+ /**
1078+ * Fires a <tt>BeanContextServiceAvailableEvent</tt> indicating that a new
1079+ * service has become available.
1080+ *
1081+ * @param bcssae the <tt>BeanContextServiceAvailableEvent</tt>
1082+ */
1083+ protected final void fireServiceAdded(BeanContextServiceAvailableEvent bcssae) {
1084+ Object[] copy;
1085+
1086+ synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1087+
1088+ for (int i = 0; i < copy.length; i++) {
1089+ ((BeanContextServicesListener)copy[i]).serviceAvailable(bcssae);
1090+ }
1091+ }
1092+
1093+ /**
1094+ * Fires a <tt>BeanContextServiceEvent</tt> notifying of a service being revoked.
1095+ *
1096+ * @param bcsre the <tt>BeanContextServiceRevokedEvent</tt>
1097+ */
1098+ protected final void fireServiceRevoked(BeanContextServiceRevokedEvent bcsre) {
1099+ Object[] copy;
1100+
1101+ synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1102+
1103+ for (int i = 0; i < copy.length; i++) {
1104+ ((BeanContextServiceRevokedListener)copy[i]).serviceRevoked(bcsre);
1105+ }
1106+ }
1107+
1108+ /**
1109+ * Fires a <tt>BeanContextServiceRevokedEvent</tt>
1110+ * indicating that a particular service is
1111+ * no longer available.
1112+ */
1113+ protected final void fireServiceRevoked(Class serviceClass, boolean revokeNow) {
1114+ Object[] copy;
1115+ BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(getBeanContextServicesPeer(), serviceClass, revokeNow);
1116+
1117+ synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1118+
1119+ for (int i = 0; i < copy.length; i++) {
1120+ ((BeanContextServicesListener)copy[i]).serviceRevoked(bcsre);
1121+ }
1122+ }
1123+
1124+ /**
1125+ * called from BeanContextSupport writeObject before it serializes the
1126+ * children ...
1127+ *
1128+ * This class will serialize any Serializable BeanContextServiceProviders
1129+ * herein.
1130+ *
1131+ * subclasses may envelope this method to insert their own serialization
1132+ * processing that has to occur prior to serialization of the children
1133+ */
1134+
1135+ protected synchronized void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
1136+
1137+ oos.writeInt(serializable);
1138+
1139+ if (serializable <= 0) return;
1140+
1141+ int count = 0;
1142+
1143+ Iterator i = services.entrySet().iterator();
1144+
1145+ while (i.hasNext() && count < serializable) {
1146+ Map.Entry entry = (Map.Entry)i.next();
1147+ BCSSServiceProvider bcsp = null;
1148+
1149+ try {
1150+ bcsp = (BCSSServiceProvider)entry.getValue();
1151+ } catch (ClassCastException cce) {
1152+ continue;
1153+ }
1154+
1155+ if (bcsp.getServiceProvider() instanceof Serializable) {
1156+ oos.writeObject(entry.getKey());
1157+ oos.writeObject(bcsp);
1158+ count++;
1159+ }
1160+ }
1161+
1162+ if (count != serializable)
1163+ throw new IOException("wrote different number of service providers than expected");
1164+ }
1165+
1166+ /**
1167+ * called from BeanContextSupport readObject before it deserializes the
1168+ * children ...
1169+ *
1170+ * This class will deserialize any Serializable BeanContextServiceProviders
1171+ * serialized earlier thus making them available to the children when they
1172+ * deserialized.
1173+ *
1174+ * subclasses may envelope this method to insert their own serialization
1175+ * processing that has to occur prior to serialization of the children
1176+ */
1177+
1178+ protected synchronized void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1179+
1180+ serializable = ois.readInt();
1181+
1182+ int count = serializable;
1183+
1184+ while (count > 0) {
1185+ services.put(ois.readObject(), ois.readObject());
1186+ count--;
1187+ }
1188+ }
1189+
1190+ /**
1191+ * serialize the instance
1192+ */
1193+
1194+ private synchronized void writeObject(ObjectOutputStream oos) throws IOException {
1195+ oos.defaultWriteObject();
1196+
1197+ serialize(oos, (Collection)bcsListeners);
1198+ }
1199+
1200+ /**
1201+ * deserialize the instance
1202+ */
1203+
1204+ private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1205+
1206+ ois.defaultReadObject();
1207+
1208+ deserialize(ois, (Collection)bcsListeners);
1209+ }
1210+
1211+
1212+ /*
1213+ * fields
1214+ */
1215+
1216+ /**
1217+ * all accesses to the <code> protected transient HashMap services </code>
1218+ * field should be synchronized on that object
1219+ */
1220+ protected transient HashMap services;
1221+
1222+ /**
1223+ * The number of instances of a serializable <tt>BeanContextServceProvider</tt>.
1224+ */
1225+ protected transient int serializable = 0;
1226+
1227+
1228+ /**
1229+ * Delegate for the <tt>BeanContextServiceProvider</tt>.
1230+ */
1231+ protected transient BCSSProxyServiceProvider proxy;
1232+
1233+
1234+ /**
1235+ * List of <tt>BeanContextServicesListener</tt> objects.
1236+ */
1237+ protected transient ArrayList bcsListeners;
1238+}