KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > beans > beancontext > BeanContextServicesSupport


1 /*
2  * @(#)BeanContextServicesSupport.java 1.23 04/04/15
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.beans.beancontext;
9
10 import java.util.ArrayList JavaDoc;
11 import java.util.Collection JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.HashSet JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Map.Entry;
17
18 import java.io.IOException JavaDoc;
19 import java.io.ObjectInputStream JavaDoc;
20 import java.io.ObjectOutputStream JavaDoc;
21 import java.io.Serializable JavaDoc;
22
23 import java.util.TooManyListenersException JavaDoc;
24
25 import java.util.Locale JavaDoc;
26
27 /**
28  * <p>
29  * This helper class provides a utility implementation of the
30  * java.beans.beancontext.BeanContextServices interface.
31  * </p>
32  * <p>
33  * Since this class directly implements the BeanContextServices interface,
34  * the class can, and is intended to be used either by subclassing this
35  * implementation, or via delegation of an instance of this class
36  * from another through the BeanContextProxy interface.
37  * </p>
38  *
39  * @author Laurence P. G. Cable
40  * @version 1.23, 04/15/04
41  * @since 1.2
42  */

43
44 public class BeanContextServicesSupport extends BeanContextSupport JavaDoc
45        implements BeanContextServices JavaDoc {
46
47     /**
48      * <p>
49      * Construct a BeanContextServicesSupport instance
50      * </p>
51      *
52      * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
53      * @param lcle The current Locale for this BeanContext.
54      * @param dtime The initial state, true if in design mode, false if runtime.
55      * @param visible The initial visibility.
56      *
57      */

58
59     public BeanContextServicesSupport(BeanContextServices JavaDoc peer, Locale JavaDoc lcle, boolean dTime, boolean visible) {
60     super(peer, lcle, dTime, visible);
61     }
62
63     /**
64      * Create an instance using the specified Locale and design mode.
65      *
66      * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
67      * @param lcle The current Locale for this BeanContext.
68      * @param dtime The initial state, true if in design mode, false if runtime.
69      */

70
71     public BeanContextServicesSupport(BeanContextServices JavaDoc peer, Locale JavaDoc lcle, boolean dtime) {
72     this (peer, lcle, dtime, true);
73     }
74
75     /**
76      * Create an instance using the specified locale
77      *
78      * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
79      * @param lcle The current Locale for this BeanContext.
80      */

81
82     public BeanContextServicesSupport(BeanContextServices JavaDoc peer, Locale JavaDoc lcle) {
83     this (peer, lcle, false, true);
84     }
85
86     /**
87      * Create an instance with a peer
88      *
89      * @param peer The peer BeanContext we are supplying an implementation for, if null the this object is its own peer
90      */

91
92     public BeanContextServicesSupport(BeanContextServices JavaDoc peer) {
93     this (peer, null, false, true);
94     }
95
96     /**
97      * Create an instance that is not a delegate of another object
98      */

99
100     public BeanContextServicesSupport() {
101     this (null, null, false, true);
102     }
103
104     /**
105      * called by BeanContextSupport superclass during construction and
106      * deserialization to initialize subclass transient state.
107      *
108      * subclasses may envelope this method, but should not override it or
109      * call it directly.
110      */

111
112     public void initialize() {
113     super.initialize();
114
115     services = new HashMap JavaDoc(serializable + 1);
116     bcsListeners = new ArrayList JavaDoc(1);
117     }
118
119     /**
120      * Gets the <tt>BeanContextServices</tt> associated with this
121      * <tt>BeanContextServicesSupport</tt>.
122      *
123      * @return the instance of <tt>BeanContext</tt>
124      * this object is providing the implementation for.
125      */

126     public BeanContextServices JavaDoc getBeanContextServicesPeer() {
127     return (BeanContextServices JavaDoc)getBeanContextChildPeer();
128     }
129
130     /************************************************************************/
131
132     /*
133      * protected nested class containing per child information, an instance
134      * of which is associated with each child in the "children" hashtable.
135      * subclasses can extend this class to include their own per-child state.
136      *
137      * Note that this 'value' is serialized with the corresponding child 'key'
138      * when the BeanContextSupport is serialized.
139      */

140
141     protected class BCSSChild extends BeanContextSupport.BCSChild JavaDoc {
142
143         private static final long serialVersionUID = -3263851306889194873L;
144
145     /*
146      * private nested class to map serviceClass to Provider and requestors
147      * listeners.
148      */

149
150     class BCSSCServiceClassRef {
151
152         // create an instance of a service ref
153

154         BCSSCServiceClassRef(Class JavaDoc sc, BeanContextServiceProvider JavaDoc bcsp, boolean delegated) {
155         super();
156     
157         serviceClass = sc;
158
159         if (delegated)
160             delegateProvider = bcsp;
161         else
162             serviceProvider = bcsp;
163         }
164
165         // add a requestor and assoc listener
166

167         void addRequestor(Object JavaDoc requestor, BeanContextServiceRevokedListener JavaDoc bcsrl) throws TooManyListenersException JavaDoc {
168         BeanContextServiceRevokedListener JavaDoc cbcsrl = (BeanContextServiceRevokedListener JavaDoc)requestors.get(requestor);
169
170         if (cbcsrl != null && !cbcsrl.equals(bcsrl))
171             throw new TooManyListenersException JavaDoc();
172
173         requestors.put(requestor, bcsrl);
174         }
175
176         // remove a requestor
177

178         void removeRequestor(Object JavaDoc requestor) {
179         requestors.remove(requestor);
180         }
181
182         // check a requestors listener
183

184         void verifyRequestor(Object JavaDoc requestor, BeanContextServiceRevokedListener JavaDoc bcsrl) throws TooManyListenersException JavaDoc {
185         BeanContextServiceRevokedListener JavaDoc cbcsrl = (BeanContextServiceRevokedListener JavaDoc)requestors.get(requestor);
186
187         if (cbcsrl != null && !cbcsrl.equals(bcsrl))
188             throw new TooManyListenersException JavaDoc();
189         }
190
191         void verifyAndMaybeSetProvider(BeanContextServiceProvider JavaDoc bcsp, boolean isDelegated) {
192         BeanContextServiceProvider JavaDoc current;
193
194         if (isDelegated) { // the provider is delegated
195
current = delegateProvider;
196
197             if (current == null || bcsp == null) {
198             delegateProvider = bcsp;
199             return;
200             }
201         } else { // the provider is registered with this BCS
202
current = serviceProvider;
203
204             if (current == null || bcsp == null) {
205             serviceProvider = bcsp;
206             return;
207             }
208         }
209
210         if (!current.equals(bcsp))
211             throw new UnsupportedOperationException JavaDoc("existing service reference obtained from different BeanContextServiceProvider not supported");
212
213         }
214
215         Iterator JavaDoc cloneOfEntries() {
216         return ((HashMap JavaDoc)requestors.clone()).entrySet().iterator();
217         }
218
219         Iterator JavaDoc entries() { return requestors.entrySet().iterator(); }
220
221         boolean isEmpty() { return requestors.isEmpty(); }
222
223         Class JavaDoc getServiceClass() { return serviceClass; }
224
225         BeanContextServiceProvider JavaDoc getServiceProvider() {
226         return serviceProvider;
227         }
228
229         BeanContextServiceProvider JavaDoc getDelegateProvider() {
230         return delegateProvider;
231         }
232
233         boolean isDelegated() { return delegateProvider != null; }
234
235         void addRef(boolean delegated) {
236         if (delegated) {
237             delegateRefs++;
238         } else {
239             serviceRefs++;
240         }
241         }
242
243
244         void releaseRef(boolean delegated) {
245                 if (delegated) {
246                     if (--delegateRefs == 0) {
247             delegateProvider = null;
248             }
249                 } else {
250                     if (--serviceRefs <= 0) {
251             serviceProvider = null;
252             }
253         }
254             }
255
256         int getRefs() { return serviceRefs + delegateRefs; }
257
258         int getDelegateRefs() { return delegateRefs; }
259
260         int getServiceRefs() { return serviceRefs; }
261
262         /*
263          * fields
264          */

265
266         Class JavaDoc serviceClass;
267
268         BeanContextServiceProvider JavaDoc serviceProvider;
269         int serviceRefs;
270
271         BeanContextServiceProvider JavaDoc delegateProvider; // proxy
272
int delegateRefs;
273
274         HashMap JavaDoc requestors = new HashMap JavaDoc(1);
275     }
276
277         /*
278      * per service reference info ...
279      */

280
281     class BCSSCServiceRef {
282         BCSSCServiceRef(BCSSCServiceClassRef scref, boolean isDelegated) {
283         serviceClassRef = scref;
284         delegated = isDelegated;
285         }
286
287         void addRef() { refCnt++; }
288         int release() { return --refCnt; }
289
290         BCSSCServiceClassRef getServiceClassRef() { return serviceClassRef; }
291
292         boolean isDelegated() { return delegated; }
293
294         /*
295              * fields
296          */

297
298         BCSSCServiceClassRef serviceClassRef;
299         int refCnt = 1;
300         boolean delegated = false;
301     }
302
303     BCSSChild(Object JavaDoc bcc, Object JavaDoc peer) { super(bcc, peer); }
304
305         // note usage of service per requestor, per service
306

307     synchronized void usingService(Object JavaDoc requestor, Object JavaDoc service, Class JavaDoc serviceClass, BeanContextServiceProvider JavaDoc bcsp, boolean isDelegated, BeanContextServiceRevokedListener JavaDoc bcsrl) throws TooManyListenersException JavaDoc, UnsupportedOperationException JavaDoc {
308     
309         // first, process mapping from serviceClass to requestor(s)
310

311         BCSSCServiceClassRef serviceClassRef = null;
312
313         if (serviceClasses == null)
314         serviceClasses = new HashMap JavaDoc(1);
315         else
316             serviceClassRef = (BCSSCServiceClassRef)serviceClasses.get(serviceClass);
317
318         if (serviceClassRef == null) { // new service being used ...
319
serviceClassRef = new BCSSCServiceClassRef(serviceClass, bcsp, isDelegated);
320         serviceClasses.put(serviceClass, serviceClassRef);
321
322         } else { // existing service ...
323
serviceClassRef.verifyAndMaybeSetProvider(bcsp, isDelegated); // throws
324
serviceClassRef.verifyRequestor(requestor, bcsrl); // throws
325
}
326
327         serviceClassRef.addRequestor(requestor, bcsrl);
328         serviceClassRef.addRef(isDelegated);
329
330         // now handle mapping from requestor to service(s)
331

332         BCSSCServiceRef serviceRef = null;
333         Map JavaDoc services = null;
334
335         if (serviceRequestors == null) {
336         serviceRequestors = new HashMap JavaDoc(1);
337         } else {
338         services = (Map JavaDoc)serviceRequestors.get(requestor);
339         }
340
341         if (services == null) {
342         services = new HashMap JavaDoc(1);
343
344         serviceRequestors.put(requestor, services);
345         } else
346         serviceRef = (BCSSCServiceRef)services.get(service);
347
348         if (serviceRef == null) {
349         serviceRef = new BCSSCServiceRef(serviceClassRef, isDelegated);
350
351         services.put(service, serviceRef);
352         } else {
353         serviceRef.addRef();
354         }
355     }
356
357     // release a service reference
358

359     synchronized void releaseService(Object JavaDoc requestor, Object JavaDoc service) {
360         if (serviceRequestors == null) return;
361
362         Map JavaDoc services = (Map JavaDoc)serviceRequestors.get(requestor);
363     
364         if (services == null) return; // oops its not there anymore!
365

366         BCSSCServiceRef serviceRef = (BCSSCServiceRef)services.get(service);
367
368         if (serviceRef == null) return; // oops its not there anymore!
369

370         BCSSCServiceClassRef serviceClassRef = serviceRef.getServiceClassRef();
371         boolean isDelegated = serviceRef.isDelegated();
372         BeanContextServiceProvider JavaDoc bcsp = isDelegated ? serviceClassRef.getDelegateProvider() : serviceClassRef.getServiceProvider();
373
374         bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);
375
376         serviceClassRef.releaseRef(isDelegated);
377         serviceClassRef.removeRequestor(requestor);
378
379         if (serviceRef.release() == 0) {
380
381         services.remove(service);
382
383         if (services.isEmpty()) {
384             serviceRequestors.remove(requestor);
385             serviceClassRef.removeRequestor(requestor);
386         }
387
388         if (serviceRequestors.isEmpty()) {
389             serviceRequestors = null;
390         }
391
392         if (serviceClassRef.isEmpty()) {
393             serviceClasses.remove(serviceClassRef.getServiceClass());
394         }
395
396         if (serviceClasses.isEmpty())
397             serviceClasses = null;
398         }
399     }
400
401     // revoke a service
402

403     synchronized void revokeService(Class JavaDoc serviceClass, boolean isDelegated, boolean revokeNow) {
404         if (serviceClasses == null) return;
405
406         BCSSCServiceClassRef serviceClassRef = (BCSSCServiceClassRef)serviceClasses.get(serviceClass);
407
408         if (serviceClassRef == null) return;
409
410         Iterator JavaDoc i = serviceClassRef.cloneOfEntries();
411
412         BeanContextServiceRevokedEvent JavaDoc bcsre = new BeanContextServiceRevokedEvent JavaDoc(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClass, revokeNow);
413         boolean noMoreRefs = false;
414
415         while (i.hasNext() && serviceRequestors != null) {
416         Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
417         BeanContextServiceRevokedListener JavaDoc listener = (BeanContextServiceRevokedListener JavaDoc)entry.getValue();
418
419         if (revokeNow) {
420             Object JavaDoc requestor = entry.getKey();
421             Map JavaDoc services = (Map JavaDoc)serviceRequestors.get(requestor);
422
423             if (services != null) {
424             Iterator JavaDoc i1 = services.entrySet().iterator();
425
426             while (i1.hasNext()) {
427                 Map.Entry JavaDoc tmp = (Map.Entry JavaDoc)i1.next();
428
429                 BCSSCServiceRef serviceRef = (BCSSCServiceRef)tmp.getValue();
430                 if (serviceRef.getServiceClassRef().equals(serviceClassRef) && isDelegated == serviceRef.isDelegated()) {
431                 i1.remove();
432                 }
433             }
434
435             if (noMoreRefs = services.isEmpty()) {
436                 serviceRequestors.remove(requestor);
437             }
438             }
439
440             if (noMoreRefs) serviceClassRef.removeRequestor(requestor);
441         }
442
443         listener.serviceRevoked(bcsre);
444         }
445
446         if (revokeNow && serviceClasses != null) {
447         if (serviceClassRef.isEmpty())
448             serviceClasses.remove(serviceClass);
449
450             if (serviceClasses.isEmpty())
451             serviceClasses = null;
452         }
453
454         if (serviceRequestors != null && serviceRequestors.isEmpty())
455         serviceRequestors = null;
456     }
457
458     // release all references for this child since it has been unnested.
459

460     void cleanupReferences() {
461
462         if (serviceRequestors == null) return;
463
464         Iterator JavaDoc requestors = serviceRequestors.entrySet().iterator();
465
466         while(requestors.hasNext()) {
467         Map.Entry JavaDoc tmp = (Map.Entry JavaDoc)requestors.next();
468         Object JavaDoc requestor = tmp.getKey();
469         Iterator JavaDoc services = ((Map JavaDoc)tmp.getValue()).entrySet().iterator();
470
471         requestors.remove();
472
473         while (services.hasNext()) {
474             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)services.next();
475             Object JavaDoc service = entry.getKey();
476             BCSSCServiceRef sref = (BCSSCServiceRef)entry.getValue();
477
478             BCSSCServiceClassRef scref = sref.getServiceClassRef();
479         
480             BeanContextServiceProvider JavaDoc bcsp = sref.isDelegated() ? scref.getDelegateProvider() : scref.getServiceProvider();
481
482             scref.removeRequestor(requestor);
483             services.remove();
484
485             while (sref.release() >= 0) {
486             bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);
487             }
488         }
489         }
490
491         serviceRequestors = null;
492         serviceClasses = null;
493     }
494
495         void revokeAllDelegatedServicesNow() {
496         if (serviceClasses == null) return;
497
498         Iterator JavaDoc serviceClassRefs =
499         new HashSet JavaDoc(serviceClasses.values()).iterator();
500
501         while (serviceClassRefs.hasNext()) {
502             BCSSCServiceClassRef serviceClassRef = (BCSSCServiceClassRef)serviceClassRefs.next();
503
504             if (!serviceClassRef.isDelegated()) continue;
505
506             Iterator JavaDoc i = serviceClassRef.cloneOfEntries();
507             BeanContextServiceRevokedEvent JavaDoc bcsre = new BeanContextServiceRevokedEvent JavaDoc(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClassRef.getServiceClass(), true);
508             boolean noMoreRefs = false;
509
510             while (i.hasNext()) {
511             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
512             BeanContextServiceRevokedListener JavaDoc listener = (BeanContextServiceRevokedListener JavaDoc)entry.getValue();
513
514             Object JavaDoc requestor = entry.getKey();
515             Map JavaDoc services = (Map JavaDoc)serviceRequestors.get(requestor);
516
517             if (services != null) {
518             Iterator JavaDoc i1 = services.entrySet().iterator();
519
520             while (i1.hasNext()) {
521                 Map.Entry JavaDoc tmp = (Map.Entry JavaDoc)i1.next();
522
523                 BCSSCServiceRef serviceRef = (BCSSCServiceRef)tmp.getValue();
524                 if (serviceRef.getServiceClassRef().equals(serviceClassRef) && serviceRef.isDelegated()) {
525                 i1.remove();
526                 }
527             }
528
529             if (noMoreRefs = services.isEmpty()) {
530                 serviceRequestors.remove(requestor);
531             }
532             }
533
534             if (noMoreRefs) serviceClassRef.removeRequestor(requestor);
535
536             listener.serviceRevoked(bcsre);
537
538             if (serviceClassRef.isEmpty())
539                 serviceClasses.remove(serviceClassRef.getServiceClass());
540             }
541         }
542
543         if (serviceClasses.isEmpty()) serviceClasses = null;
544
545         if (serviceRequestors != null && serviceRequestors.isEmpty())
546         serviceRequestors = null;
547         }
548
549     /*
550      * fields
551      */

552
553     private transient HashMap JavaDoc serviceClasses;
554     private transient HashMap JavaDoc serviceRequestors;
555     }
556
557     /**
558      * <p>
559      * Subclasses can override this method to insert their own subclass
560      * of Child without having to override add() or the other Collection
561      * methods that add children to the set.
562      * </p>
563      *
564      * @param targetChild the child to create the Child on behalf of
565      * @param peer the peer if the targetChild and peer are related by BeanContextProxy
566      */

567
568     protected BCSChild createBCSChild(Object JavaDoc targetChild, Object JavaDoc peer) {
569     return new BCSSChild(targetChild, peer);
570     }
571
572     /************************************************************************/
573
574     /**
575      * subclasses may subclass this nested class to add behaviors for
576      * each BeanContextServicesProvider.
577      */

578
579     protected static class BCSSServiceProvider implements Serializable JavaDoc {
580
581         BCSSServiceProvider(Class JavaDoc sc, BeanContextServiceProvider JavaDoc bcsp) {
582         super();
583     
584         serviceProvider = bcsp;
585         }
586
587         protected BeanContextServiceProvider JavaDoc getServiceProvider() {
588         return serviceProvider;
589         }
590
591         /*
592          * fields
593          */

594
595         protected BeanContextServiceProvider JavaDoc serviceProvider;
596     }
597
598         /**
599      * subclasses can override this method to create new subclasses of
600      * BCSSServiceProvider without having to overrride addService() in
601      * order to instantiate.
602      */

603
604     protected BCSSServiceProvider createBCSSServiceProvider(Class JavaDoc sc, BeanContextServiceProvider JavaDoc bcsp) {
605         return new BCSSServiceProvider(sc, bcsp);
606     }
607
608     /************************************************************************/
609
610     /**
611      * add a BeanContextServicesListener
612      *
613      * @throw new NullPointerException
614      */

615
616     public void addBeanContextServicesListener(BeanContextServicesListener JavaDoc bcsl) {
617     if (bcsl == null) throw new NullPointerException JavaDoc("bcsl");
618
619     synchronized(bcsListeners) {
620         if (bcsListeners.contains(bcsl))
621         return;
622         else
623             bcsListeners.add(bcsl);
624     }
625     }
626
627     /**
628      * remove a BeanContextServicesListener
629      */

630
631     public void removeBeanContextServicesListener(BeanContextServicesListener JavaDoc bcsl) {
632     if (bcsl == null) throw new NullPointerException JavaDoc("bcsl");
633
634     synchronized(bcsListeners) {
635         if (!bcsListeners.contains(bcsl))
636         return;
637         else
638             bcsListeners.remove(bcsl);
639     }
640     }
641
642     /**
643      * add a service
644      */

645
646     public boolean addService(Class JavaDoc serviceClass, BeanContextServiceProvider JavaDoc bcsp) {
647     return addService(serviceClass, bcsp, true);
648     }
649
650     /**
651      * add a service
652      */

653
654     protected boolean addService(Class JavaDoc serviceClass, BeanContextServiceProvider JavaDoc bcsp, boolean fireEvent) {
655
656     if (serviceClass == null) throw new NullPointerException JavaDoc("serviceClass");
657     if (bcsp == null) throw new NullPointerException JavaDoc("bcsp");
658
659     synchronized(BeanContext.globalHierarchyLock) {
660             if (services.containsKey(serviceClass))
661                 return false;
662             else {
663                 services.put(serviceClass, createBCSSServiceProvider(serviceClass, bcsp));
664     
665                 if (bcsp instanceof Serializable JavaDoc) serializable++;
666     
667                 if (!fireEvent) return true;
668     
669     
670                 BeanContextServiceAvailableEvent JavaDoc bcssae = new BeanContextServiceAvailableEvent JavaDoc(getBeanContextServicesPeer(), serviceClass);
671     
672                 fireServiceAdded(bcssae);
673     
674                 synchronized(children) {
675                     Iterator JavaDoc i = children.keySet().iterator();
676     
677                     while (i.hasNext()) {
678                         Object JavaDoc c = i.next();
679     
680                         if (c instanceof BeanContextServices JavaDoc) {
681                         ((BeanContextServicesListener JavaDoc)c).serviceAvailable(bcssae);
682                         }
683                     }
684                 }
685     
686                 return true;
687             }
688     }
689     }
690
691     /**
692      * remove a service
693      */

694
695     public void revokeService(Class JavaDoc serviceClass, BeanContextServiceProvider JavaDoc bcsp, boolean revokeCurrentServicesNow) {
696
697     if (serviceClass == null) throw new NullPointerException JavaDoc("serviceClass");
698     if (bcsp == null) throw new NullPointerException JavaDoc("bcsp");
699
700     synchronized(BeanContext.globalHierarchyLock) {
701         if (!services.containsKey(serviceClass)) return;
702
703         BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
704     
705         if (!bcsssp.getServiceProvider().equals(bcsp))
706             throw new IllegalArgumentException JavaDoc("service provider mismatch");
707
708         services.remove(serviceClass);
709
710             if (bcsp instanceof Serializable JavaDoc) serializable--;
711
712         Iterator JavaDoc i = bcsChildren(); // get the BCSChild values.
713

714         while (i.hasNext()) {
715             ((BCSSChild)i.next()).revokeService(serviceClass, false, revokeCurrentServicesNow);
716         }
717
718         fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
719     }
720     }
721
722     /**
723      * has a service, which may be delegated
724      */

725
726     public synchronized boolean hasService(Class JavaDoc serviceClass) {
727     if (serviceClass == null) throw new NullPointerException JavaDoc("serviceClass");
728
729     synchronized(BeanContext.globalHierarchyLock) {
730         if (services.containsKey(serviceClass)) return true;
731
732         BeanContextServices JavaDoc bcs = null;
733
734         try {
735             bcs = (BeanContextServices JavaDoc)getBeanContext();
736         } catch (ClassCastException JavaDoc cce) {
737             return false;
738         }
739
740         return bcs == null ? false : bcs.hasService(serviceClass);
741     }
742     }
743
744     /************************************************************************/
745
746     /*
747      * a nested subclass used to represent a proxy for serviceClasses delegated
748      * to an enclosing BeanContext.
749      */

750
751     protected class BCSSProxyServiceProvider implements BeanContextServiceProvider JavaDoc, BeanContextServiceRevokedListener JavaDoc {
752     
753         BCSSProxyServiceProvider(BeanContextServices JavaDoc bcs) {
754         super();
755         
756         nestingCtxt = bcs;
757     }
758
759     public Object JavaDoc getService(BeanContextServices JavaDoc bcs, Object JavaDoc requestor, Class JavaDoc serviceClass, Object JavaDoc serviceSelector) {
760         Object JavaDoc service = null;
761
762         try {
763         service = nestingCtxt.getService(bcs, requestor, serviceClass, serviceSelector, this);
764         } catch (TooManyListenersException JavaDoc tmle) {
765         return null;
766         }
767     
768         return service;
769     }
770
771     public void releaseService(BeanContextServices JavaDoc bcs, Object JavaDoc requestor, Object JavaDoc service) {
772         nestingCtxt.releaseService(bcs, requestor, service);
773     }
774
775     public Iterator JavaDoc getCurrentServiceSelectors(BeanContextServices JavaDoc bcs, Class JavaDoc serviceClass) {
776         return nestingCtxt.getCurrentServiceSelectors(serviceClass);
777     }
778
779     public void serviceRevoked(BeanContextServiceRevokedEvent JavaDoc bcsre) {
780         Iterator JavaDoc i = bcsChildren(); // get the BCSChild values.
781

782         while (i.hasNext()) {
783             ((BCSSChild)i.next()).revokeService(bcsre.getServiceClass(), true, bcsre.isCurrentServiceInvalidNow());
784         }
785     }
786
787     /*
788      * fields
789      */

790
791     private BeanContextServices JavaDoc nestingCtxt;
792     }
793
794     /************************************************************************/
795
796     /**
797      * obtain a service which may be delegated
798      */

799
800      public Object JavaDoc getService(BeanContextChild JavaDoc child, Object JavaDoc requestor, Class JavaDoc serviceClass, Object JavaDoc serviceSelector, BeanContextServiceRevokedListener JavaDoc bcsrl) throws TooManyListenersException JavaDoc {
801     if (child == null) throw new NullPointerException JavaDoc("child");
802     if (serviceClass == null) throw new NullPointerException JavaDoc("serviceClass");
803     if (requestor == null) throw new NullPointerException JavaDoc("requestor");
804     if (bcsrl == null) throw new NullPointerException JavaDoc("bcsrl");
805
806     Object JavaDoc service = null;
807     BCSSChild bcsc;
808     BeanContextServices JavaDoc bcssp = getBeanContextServicesPeer();
809
810     synchronized(BeanContext.globalHierarchyLock) {
811         synchronized(children) { bcsc = (BCSSChild)children.get(child); }
812
813         if (bcsc == null) throw new IllegalArgumentException JavaDoc("not a child of this context"); // not a child ...
814

815         BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
816
817         if (bcsssp != null) {
818             BeanContextServiceProvider JavaDoc bcsp = bcsssp.getServiceProvider();
819             service = bcsp.getService(bcssp, requestor, serviceClass, serviceSelector);
820             if (service != null) { // do bookkeeping ...
821
try {
822                     bcsc.usingService(requestor, service, serviceClass, bcsp, false, bcsrl);
823             } catch (TooManyListenersException JavaDoc tmle) {
824                 bcsp.releaseService(bcssp, requestor, service);
825                 throw tmle;
826             } catch (UnsupportedOperationException JavaDoc uope) {
827                 bcsp.releaseService(bcssp, requestor, service);
828                 throw uope; // unchecked rt exception
829
}
830
831             return service;
832             }
833         }
834
835
836         if (proxy != null) {
837
838             // try to delegate ...
839

840             service = proxy.getService(bcssp, requestor, serviceClass, serviceSelector);
841     
842             if (service != null) { // do bookkeeping ...
843
try {
844                 bcsc.usingService(requestor, service, serviceClass, proxy, true, bcsrl);
845             } catch (TooManyListenersException JavaDoc tmle) {
846                 proxy.releaseService(bcssp, requestor, service);
847                 throw tmle;
848             } catch (UnsupportedOperationException JavaDoc uope) {
849                 proxy.releaseService(bcssp, requestor, service);
850                 throw uope; // unchecked rt exception
851
}
852
853             return service;
854             }
855         }
856     }
857
858         return null;
859     }
860
861     /**
862      * release a service
863      */

864
865     public void releaseService(BeanContextChild JavaDoc child, Object JavaDoc requestor, Object JavaDoc service) {
866     if (child == null) throw new NullPointerException JavaDoc("child");
867     if (requestor == null) throw new NullPointerException JavaDoc("requestor");
868     if (service == null) throw new NullPointerException JavaDoc("service");
869
870     BCSSChild bcsc;
871
872     synchronized(BeanContext.globalHierarchyLock) {
873             synchronized(children) { bcsc = (BCSSChild)children.get(child); }
874
875             if (bcsc != null)
876             bcsc.releaseService(requestor, service);
877         else
878            throw new IllegalArgumentException JavaDoc("child actual is not a child of this BeanContext");
879         }
880     }
881
882     /**
883      * @return an iterator for all the currently registered service classes.
884      */

885
886     public Iterator JavaDoc getCurrentServiceClasses() {
887     return new BCSIterator(services.keySet().iterator());
888     }
889
890     /**
891      * @return an iterator for all the currently available service selectors
892      * (if any) available for the specified service.
893      */

894
895     public Iterator JavaDoc getCurrentServiceSelectors(Class JavaDoc serviceClass) {
896     
897     BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
898     
899     return bcsssp != null ? new BCSIterator(bcsssp.getServiceProvider().getCurrentServiceSelectors(getBeanContextServicesPeer(), serviceClass)) : null;
900     }
901
902     /**
903      * BeanContextServicesListener callback, propagates event to all
904      * currently registered listeners and BeanContextServices children,
905      * if this BeanContextService does not already implement this service
906      * itself.
907      *
908      * subclasses may override or envelope this method to implement their
909      * own propagation semantics.
910      */

911
912      public void serviceAvailable(BeanContextServiceAvailableEvent JavaDoc bcssae) {
913     synchronized(BeanContext.globalHierarchyLock) {
914         if (services.containsKey(bcssae.getServiceClass())) return;
915
916         fireServiceAdded(bcssae);
917
918         Iterator JavaDoc i;
919
920         synchronized(children) {
921             i = children.keySet().iterator();
922         }
923
924         while (i.hasNext()) {
925             Object JavaDoc c = i.next();
926
927             if (c instanceof BeanContextServices JavaDoc) {
928                 ((BeanContextServicesListener JavaDoc)c).serviceAvailable(bcssae);
929             }
930         }
931     }
932      }
933
934     /**
935      * BeanContextServicesListener callback, propagates event to all
936      * currently registered listeners and BeanContextServices children,
937      * if this BeanContextService does not already implement this service
938      * itself.
939      *
940      * subclasses may override or envelope this method to implement their
941      * own propagation semantics.
942      */

943
944     public void serviceRevoked(BeanContextServiceRevokedEvent JavaDoc bcssre) {
945     synchronized(BeanContext.globalHierarchyLock) {
946         if (services.containsKey(bcssre.getServiceClass())) return;
947
948         fireServiceRevoked(bcssre);
949
950         Iterator JavaDoc i;
951
952         synchronized(children) {
953             i = children.keySet().iterator();
954         }
955
956         while (i.hasNext()) {
957             Object JavaDoc c = i.next();
958
959             if (c instanceof BeanContextServices JavaDoc) {
960                 ((BeanContextServicesListener JavaDoc)c).serviceRevoked(bcssre);
961             }
962         }
963     }
964     }
965
966     /**
967      * Gets the <tt>BeanContextServicesListener</tt> (if any) of the specified
968      * child.
969      *
970      * @param child the specified child
971      * @return the BeanContextServicesListener (if any) of the specified child
972      */

973     protected static final BeanContextServicesListener JavaDoc getChildBeanContextServicesListener(Object JavaDoc child) {
974     try {
975         return (BeanContextServicesListener JavaDoc)child;
976     } catch (ClassCastException JavaDoc cce) {
977         return null;
978     }
979     }
980
981     /**
982      * called from superclass child removal operations after a child
983      * has been successfully removed. called with child synchronized.
984      *
985      * This subclass uses this hook to immediately revoke any services
986      * being used by this child if it is a BeanContextChild.
987      *
988      * subclasses may envelope this method in order to implement their
989      * own child removal side-effects.
990      */

991
992     protected void childJustRemovedHook(Object JavaDoc child, BCSChild bcsc) {
993     BCSSChild bcssc = (BCSSChild)bcsc;
994
995     bcssc.cleanupReferences();
996     }
997
998     /**
999      * called from setBeanContext to notify a BeanContextChild
1000     * to release resources obtained from the nesting BeanContext.
1001     *
1002     * This method revokes any services obtained from its parent.
1003     *
1004     * subclasses may envelope this method to implement their own semantics.
1005     */

1006
1007    protected synchronized void releaseBeanContextResources() {
1008    Object JavaDoc[] bcssc;
1009
1010    super.releaseBeanContextResources();
1011
1012    synchronized(children) {
1013        if (children.isEmpty()) return;
1014
1015        bcssc = children.values().toArray();
1016    }
1017
1018
1019    for (int i = 0; i < bcssc.length; i++) {
1020        ((BCSSChild)bcssc[i]).revokeAllDelegatedServicesNow();
1021    }
1022
1023    proxy = null;
1024    }
1025
1026    /**
1027     * called from setBeanContext to notify a BeanContextChild
1028     * to allocate resources obtained from the nesting BeanContext.
1029     *
1030     * subclasses may envelope this method to implement their own semantics.
1031     */

1032
1033    protected synchronized void initializeBeanContextResources() {
1034    super.initializeBeanContextResources();
1035
1036    BeanContext JavaDoc nbc = getBeanContext();
1037
1038    if (nbc == null) return;
1039
1040    try {
1041        BeanContextServices JavaDoc bcs = (BeanContextServices JavaDoc)nbc;
1042
1043        proxy = new BCSSProxyServiceProvider(bcs);
1044    } catch (ClassCastException JavaDoc cce) {
1045        // do nothing ...
1046
}
1047    }
1048
1049    /**
1050     * Fires a <tt>BeanContextServiceEvent</tt> notifying of a new service.
1051     */

1052    protected final void fireServiceAdded(Class JavaDoc serviceClass) {
1053    BeanContextServiceAvailableEvent JavaDoc bcssae = new BeanContextServiceAvailableEvent JavaDoc(getBeanContextServicesPeer(), serviceClass);
1054
1055    fireServiceAdded(bcssae);
1056    }
1057
1058    /**
1059     * Fires a <tt>BeanContextServiceAvailableEvent</tt> indicating that a new
1060     * service has become available.
1061     *
1062     * @param bcssae the <tt>BeanContextServiceAvailableEvent</tt>
1063     */

1064    protected final void fireServiceAdded(BeanContextServiceAvailableEvent JavaDoc bcssae) {
1065    Object JavaDoc[] copy;
1066
1067    synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1068
1069    for (int i = 0; i < copy.length; i++) {
1070        ((BeanContextServicesListener JavaDoc)copy[i]).serviceAvailable(bcssae);
1071    }
1072    }
1073
1074    /**
1075     * Fires a <tt>BeanContextServiceEvent</tt> notifying of a service being revoked.
1076     *
1077     * @param bcsre the <tt>BeanContextServiceRevokedEvent</tt>
1078     */

1079    protected final void fireServiceRevoked(BeanContextServiceRevokedEvent JavaDoc bcsre) {
1080    Object JavaDoc[] copy;
1081
1082    synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1083
1084    for (int i = 0; i < copy.length; i++) {
1085        ((BeanContextServiceRevokedListener JavaDoc)copy[i]).serviceRevoked(bcsre);
1086    }
1087    }
1088
1089    /**
1090     * Fires a <tt>BeanContextServiceRevokedEvent</tt>
1091     * indicating that a particular service is
1092     * no longer available.
1093     */

1094    protected final void fireServiceRevoked(Class JavaDoc serviceClass, boolean revokeNow) {
1095    Object JavaDoc[] copy;
1096    BeanContextServiceRevokedEvent JavaDoc bcsre = new BeanContextServiceRevokedEvent JavaDoc(getBeanContextServicesPeer(), serviceClass, revokeNow);
1097
1098    synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1099
1100    for (int i = 0; i < copy.length; i++) {
1101        ((BeanContextServicesListener JavaDoc)copy[i]).serviceRevoked(bcsre);
1102    }
1103   }
1104
1105    /**
1106     * called from BeanContextSupport writeObject before it serializes the
1107     * children ...
1108     *
1109     * This class will serialize any Serializable BeanContextServiceProviders
1110     * herein.
1111     *
1112     * subclasses may envelope this method to insert their own serialization
1113     * processing that has to occur prior to serialization of the children
1114     */

1115
1116    protected synchronized void bcsPreSerializationHook(ObjectOutputStream JavaDoc oos) throws IOException JavaDoc {
1117
1118    oos.writeInt(serializable);
1119
1120    if (serializable <= 0) return;
1121
1122    int count = 0;
1123
1124    Iterator JavaDoc i = services.entrySet().iterator();
1125
1126    while (i.hasNext() && count < serializable) {
1127        Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
1128        BCSSServiceProvider bcsp = null;
1129
1130         try {
1131        bcsp = (BCSSServiceProvider)entry.getValue();
1132         } catch (ClassCastException JavaDoc cce) {
1133        continue;
1134         }
1135
1136         if (bcsp.getServiceProvider() instanceof Serializable JavaDoc) {
1137        oos.writeObject(entry.getKey());
1138        oos.writeObject(bcsp);
1139        count++;
1140         }
1141    }
1142
1143    if (count != serializable)
1144        throw new IOException JavaDoc("wrote different number of service providers than expected");
1145    }
1146
1147    /**
1148     * called from BeanContextSupport readObject before it deserializes the
1149     * children ...
1150     *
1151     * This class will deserialize any Serializable BeanContextServiceProviders
1152     * serialized earlier thus making them available to the children when they
1153     * deserialized.
1154     *
1155     * subclasses may envelope this method to insert their own serialization
1156     * processing that has to occur prior to serialization of the children
1157     */

1158
1159    protected synchronized void bcsPreDeserializationHook(ObjectInputStream JavaDoc ois) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
1160
1161    serializable = ois.readInt();
1162
1163    int count = serializable;
1164
1165    while (count > 0) {
1166        services.put(ois.readObject(), ois.readObject());
1167        count--;
1168    }
1169    }
1170 
1171    /**
1172     * serialize the instance
1173     */

1174
1175    private synchronized void writeObject(ObjectOutputStream JavaDoc oos) throws IOException JavaDoc {
1176    oos.defaultWriteObject();
1177
1178    serialize(oos, (Collection JavaDoc)bcsListeners);
1179    }
1180
1181    /**
1182     * deserialize the instance
1183     */

1184
1185    private synchronized void readObject(ObjectInputStream JavaDoc ois) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
1186
1187    ois.defaultReadObject();
1188
1189    deserialize(ois, (Collection JavaDoc)bcsListeners);
1190    }
1191
1192    
1193    /*
1194     * fields
1195     */

1196
1197    /**
1198     * all accesses to the <code> protected transient HashMap services </code>
1199     * field should be synchronized on that object
1200     */

1201    protected transient HashMap JavaDoc services;
1202
1203    /**
1204     * The number of instances of a serializable <tt>BeanContextServceProvider</tt>.
1205     */

1206    protected transient int serializable = 0;
1207
1208
1209    /**
1210     * Delegate for the <tt>BeanContextServiceProvider</tt>.
1211     */

1212    protected transient BCSSProxyServiceProvider proxy;
1213
1214
1215    /**
1216     * List of <tt>BeanContextServicesListener</tt> objects.
1217     */

1218    protected transient ArrayList JavaDoc bcsListeners;
1219}
1220
Popular Tags