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
26package java.beans.beancontext;
27
28import java.util.ArrayList;
29import java.util.Collection;
30import java.util.HashMap;
31import java.util.HashSet;
32import java.util.Iterator;
33import java.util.Map;
34import java.util.Map.Entry;
35
36import java.io.IOException;
37import java.io.ObjectInputStream;
38import java.io.ObjectOutputStream;
39import java.io.Serializable;
40
41import java.util.TooManyListenersException;
42
43import 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
61public 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}