Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/beans/beancontext/BeanContextServicesSupport.java
38918 views
1
/*
2
* Copyright (c) 1998, 2013, 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
/**
607
* Returns the service provider.
608
* @return the service provider
609
*/
610
protected BeanContextServiceProvider getServiceProvider() {
611
return serviceProvider;
612
}
613
614
/**
615
* The service provider.
616
*/
617
618
protected BeanContextServiceProvider serviceProvider;
619
}
620
621
/**
622
* subclasses can override this method to create new subclasses of
623
* BCSSServiceProvider without having to override addService() in
624
* order to instantiate.
625
* @param sc the class
626
* @param bcsp the service provider
627
* @return a service provider without overriding addService()
628
*/
629
630
protected BCSSServiceProvider createBCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp) {
631
return new BCSSServiceProvider(sc, bcsp);
632
}
633
634
/************************************************************************/
635
636
/**
637
* add a BeanContextServicesListener
638
*
639
* @throws NullPointerException if the argument is null
640
*/
641
642
public void addBeanContextServicesListener(BeanContextServicesListener bcsl) {
643
if (bcsl == null) throw new NullPointerException("bcsl");
644
645
synchronized(bcsListeners) {
646
if (bcsListeners.contains(bcsl))
647
return;
648
else
649
bcsListeners.add(bcsl);
650
}
651
}
652
653
/**
654
* remove a BeanContextServicesListener
655
*/
656
657
public void removeBeanContextServicesListener(BeanContextServicesListener bcsl) {
658
if (bcsl == null) throw new NullPointerException("bcsl");
659
660
synchronized(bcsListeners) {
661
if (!bcsListeners.contains(bcsl))
662
return;
663
else
664
bcsListeners.remove(bcsl);
665
}
666
}
667
668
/**
669
* add a service
670
* @param serviceClass the service class
671
* @param bcsp the service provider
672
*/
673
674
public boolean addService(Class serviceClass, BeanContextServiceProvider bcsp) {
675
return addService(serviceClass, bcsp, true);
676
}
677
678
/**
679
* add a service
680
* @param serviceClass the service class
681
* @param bcsp the service provider
682
* @param fireEvent whether or not an event should be fired
683
* @return true if the service was successfully added
684
*/
685
686
protected boolean addService(Class serviceClass, BeanContextServiceProvider bcsp, boolean fireEvent) {
687
688
if (serviceClass == null) throw new NullPointerException("serviceClass");
689
if (bcsp == null) throw new NullPointerException("bcsp");
690
691
synchronized(BeanContext.globalHierarchyLock) {
692
if (services.containsKey(serviceClass))
693
return false;
694
else {
695
services.put(serviceClass, createBCSSServiceProvider(serviceClass, bcsp));
696
697
if (bcsp instanceof Serializable) serializable++;
698
699
if (!fireEvent) return true;
700
701
702
BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);
703
704
fireServiceAdded(bcssae);
705
706
synchronized(children) {
707
Iterator i = children.keySet().iterator();
708
709
while (i.hasNext()) {
710
Object c = i.next();
711
712
if (c instanceof BeanContextServices) {
713
((BeanContextServicesListener)c).serviceAvailable(bcssae);
714
}
715
}
716
}
717
718
return true;
719
}
720
}
721
}
722
723
/**
724
* remove a service
725
* @param serviceClass the service class
726
* @param bcsp the service provider
727
* @param revokeCurrentServicesNow whether or not to revoke the service
728
*/
729
730
public void revokeService(Class serviceClass, BeanContextServiceProvider bcsp, boolean revokeCurrentServicesNow) {
731
732
if (serviceClass == null) throw new NullPointerException("serviceClass");
733
if (bcsp == null) throw new NullPointerException("bcsp");
734
735
synchronized(BeanContext.globalHierarchyLock) {
736
if (!services.containsKey(serviceClass)) return;
737
738
BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
739
740
if (!bcsssp.getServiceProvider().equals(bcsp))
741
throw new IllegalArgumentException("service provider mismatch");
742
743
services.remove(serviceClass);
744
745
if (bcsp instanceof Serializable) serializable--;
746
747
Iterator i = bcsChildren(); // get the BCSChild values.
748
749
while (i.hasNext()) {
750
((BCSSChild)i.next()).revokeService(serviceClass, false, revokeCurrentServicesNow);
751
}
752
753
fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
754
}
755
}
756
757
/**
758
* has a service, which may be delegated
759
*/
760
761
public synchronized boolean hasService(Class serviceClass) {
762
if (serviceClass == null) throw new NullPointerException("serviceClass");
763
764
synchronized(BeanContext.globalHierarchyLock) {
765
if (services.containsKey(serviceClass)) return true;
766
767
BeanContextServices bcs = null;
768
769
try {
770
bcs = (BeanContextServices)getBeanContext();
771
} catch (ClassCastException cce) {
772
return false;
773
}
774
775
return bcs == null ? false : bcs.hasService(serviceClass);
776
}
777
}
778
779
/************************************************************************/
780
781
/*
782
* a nested subclass used to represent a proxy for serviceClasses delegated
783
* to an enclosing BeanContext.
784
*/
785
786
protected class BCSSProxyServiceProvider implements BeanContextServiceProvider, BeanContextServiceRevokedListener {
787
788
BCSSProxyServiceProvider(BeanContextServices bcs) {
789
super();
790
791
nestingCtxt = bcs;
792
}
793
794
public Object getService(BeanContextServices bcs, Object requestor, Class serviceClass, Object serviceSelector) {
795
Object service = null;
796
797
try {
798
service = nestingCtxt.getService(bcs, requestor, serviceClass, serviceSelector, this);
799
} catch (TooManyListenersException tmle) {
800
return null;
801
}
802
803
return service;
804
}
805
806
public void releaseService(BeanContextServices bcs, Object requestor, Object service) {
807
nestingCtxt.releaseService(bcs, requestor, service);
808
}
809
810
public Iterator getCurrentServiceSelectors(BeanContextServices bcs, Class serviceClass) {
811
return nestingCtxt.getCurrentServiceSelectors(serviceClass);
812
}
813
814
public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
815
Iterator i = bcsChildren(); // get the BCSChild values.
816
817
while (i.hasNext()) {
818
((BCSSChild)i.next()).revokeService(bcsre.getServiceClass(), true, bcsre.isCurrentServiceInvalidNow());
819
}
820
}
821
822
/*
823
* fields
824
*/
825
826
private BeanContextServices nestingCtxt;
827
}
828
829
/************************************************************************/
830
831
/**
832
* obtain a service which may be delegated
833
*/
834
835
public Object getService(BeanContextChild child, Object requestor, Class serviceClass, Object serviceSelector, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
836
if (child == null) throw new NullPointerException("child");
837
if (serviceClass == null) throw new NullPointerException("serviceClass");
838
if (requestor == null) throw new NullPointerException("requestor");
839
if (bcsrl == null) throw new NullPointerException("bcsrl");
840
841
Object service = null;
842
BCSSChild bcsc;
843
BeanContextServices bcssp = getBeanContextServicesPeer();
844
845
synchronized(BeanContext.globalHierarchyLock) {
846
synchronized(children) { bcsc = (BCSSChild)children.get(child); }
847
848
if (bcsc == null) throw new IllegalArgumentException("not a child of this context"); // not a child ...
849
850
BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
851
852
if (bcsssp != null) {
853
BeanContextServiceProvider bcsp = bcsssp.getServiceProvider();
854
service = bcsp.getService(bcssp, requestor, serviceClass, serviceSelector);
855
if (service != null) { // do bookkeeping ...
856
try {
857
bcsc.usingService(requestor, service, serviceClass, bcsp, false, bcsrl);
858
} catch (TooManyListenersException tmle) {
859
bcsp.releaseService(bcssp, requestor, service);
860
throw tmle;
861
} catch (UnsupportedOperationException uope) {
862
bcsp.releaseService(bcssp, requestor, service);
863
throw uope; // unchecked rt exception
864
}
865
866
return service;
867
}
868
}
869
870
871
if (proxy != null) {
872
873
// try to delegate ...
874
875
service = proxy.getService(bcssp, requestor, serviceClass, serviceSelector);
876
877
if (service != null) { // do bookkeeping ...
878
try {
879
bcsc.usingService(requestor, service, serviceClass, proxy, true, bcsrl);
880
} catch (TooManyListenersException tmle) {
881
proxy.releaseService(bcssp, requestor, service);
882
throw tmle;
883
} catch (UnsupportedOperationException uope) {
884
proxy.releaseService(bcssp, requestor, service);
885
throw uope; // unchecked rt exception
886
}
887
888
return service;
889
}
890
}
891
}
892
893
return null;
894
}
895
896
/**
897
* release a service
898
*/
899
900
public void releaseService(BeanContextChild child, Object requestor, Object service) {
901
if (child == null) throw new NullPointerException("child");
902
if (requestor == null) throw new NullPointerException("requestor");
903
if (service == null) throw new NullPointerException("service");
904
905
BCSSChild bcsc;
906
907
synchronized(BeanContext.globalHierarchyLock) {
908
synchronized(children) { bcsc = (BCSSChild)children.get(child); }
909
910
if (bcsc != null)
911
bcsc.releaseService(requestor, service);
912
else
913
throw new IllegalArgumentException("child actual is not a child of this BeanContext");
914
}
915
}
916
917
/**
918
* @return an iterator for all the currently registered service classes.
919
*/
920
921
public Iterator getCurrentServiceClasses() {
922
return new BCSIterator(services.keySet().iterator());
923
}
924
925
/**
926
* @return an iterator for all the currently available service selectors
927
* (if any) available for the specified service.
928
*/
929
930
public Iterator getCurrentServiceSelectors(Class serviceClass) {
931
932
BCSSServiceProvider bcsssp = (BCSSServiceProvider)services.get(serviceClass);
933
934
return bcsssp != null ? new BCSIterator(bcsssp.getServiceProvider().getCurrentServiceSelectors(getBeanContextServicesPeer(), serviceClass)) : null;
935
}
936
937
/**
938
* BeanContextServicesListener callback, propagates event to all
939
* currently registered listeners and BeanContextServices children,
940
* if this BeanContextService does not already implement this service
941
* itself.
942
*
943
* subclasses may override or envelope this method to implement their
944
* own propagation semantics.
945
*/
946
947
public void serviceAvailable(BeanContextServiceAvailableEvent bcssae) {
948
synchronized(BeanContext.globalHierarchyLock) {
949
if (services.containsKey(bcssae.getServiceClass())) return;
950
951
fireServiceAdded(bcssae);
952
953
Iterator i;
954
955
synchronized(children) {
956
i = children.keySet().iterator();
957
}
958
959
while (i.hasNext()) {
960
Object c = i.next();
961
962
if (c instanceof BeanContextServices) {
963
((BeanContextServicesListener)c).serviceAvailable(bcssae);
964
}
965
}
966
}
967
}
968
969
/**
970
* BeanContextServicesListener callback, propagates event to all
971
* currently registered listeners and BeanContextServices children,
972
* if this BeanContextService does not already implement this service
973
* itself.
974
*
975
* subclasses may override or envelope this method to implement their
976
* own propagation semantics.
977
*/
978
979
public void serviceRevoked(BeanContextServiceRevokedEvent bcssre) {
980
synchronized(BeanContext.globalHierarchyLock) {
981
if (services.containsKey(bcssre.getServiceClass())) return;
982
983
fireServiceRevoked(bcssre);
984
985
Iterator i;
986
987
synchronized(children) {
988
i = children.keySet().iterator();
989
}
990
991
while (i.hasNext()) {
992
Object c = i.next();
993
994
if (c instanceof BeanContextServices) {
995
((BeanContextServicesListener)c).serviceRevoked(bcssre);
996
}
997
}
998
}
999
}
1000
1001
/**
1002
* Gets the <tt>BeanContextServicesListener</tt> (if any) of the specified
1003
* child.
1004
*
1005
* @param child the specified child
1006
* @return the BeanContextServicesListener (if any) of the specified child
1007
*/
1008
protected static final BeanContextServicesListener getChildBeanContextServicesListener(Object child) {
1009
try {
1010
return (BeanContextServicesListener)child;
1011
} catch (ClassCastException cce) {
1012
return null;
1013
}
1014
}
1015
1016
/**
1017
* called from superclass child removal operations after a child
1018
* has been successfully removed. called with child synchronized.
1019
*
1020
* This subclass uses this hook to immediately revoke any services
1021
* being used by this child if it is a BeanContextChild.
1022
*
1023
* subclasses may envelope this method in order to implement their
1024
* own child removal side-effects.
1025
*/
1026
1027
protected void childJustRemovedHook(Object child, BCSChild bcsc) {
1028
BCSSChild bcssc = (BCSSChild)bcsc;
1029
1030
bcssc.cleanupReferences();
1031
}
1032
1033
/**
1034
* called from setBeanContext to notify a BeanContextChild
1035
* to release resources obtained from the nesting BeanContext.
1036
*
1037
* This method revokes any services obtained from its parent.
1038
*
1039
* subclasses may envelope this method to implement their own semantics.
1040
*/
1041
1042
protected synchronized void releaseBeanContextResources() {
1043
Object[] bcssc;
1044
1045
super.releaseBeanContextResources();
1046
1047
synchronized(children) {
1048
if (children.isEmpty()) return;
1049
1050
bcssc = children.values().toArray();
1051
}
1052
1053
1054
for (int i = 0; i < bcssc.length; i++) {
1055
((BCSSChild)bcssc[i]).revokeAllDelegatedServicesNow();
1056
}
1057
1058
proxy = null;
1059
}
1060
1061
/**
1062
* called from setBeanContext to notify a BeanContextChild
1063
* to allocate resources obtained from the nesting BeanContext.
1064
*
1065
* subclasses may envelope this method to implement their own semantics.
1066
*/
1067
1068
protected synchronized void initializeBeanContextResources() {
1069
super.initializeBeanContextResources();
1070
1071
BeanContext nbc = getBeanContext();
1072
1073
if (nbc == null) return;
1074
1075
try {
1076
BeanContextServices bcs = (BeanContextServices)nbc;
1077
1078
proxy = new BCSSProxyServiceProvider(bcs);
1079
} catch (ClassCastException cce) {
1080
// do nothing ...
1081
}
1082
}
1083
1084
/**
1085
* Fires a <tt>BeanContextServiceEvent</tt> notifying of a new service.
1086
* @param serviceClass the service class
1087
*/
1088
protected final void fireServiceAdded(Class serviceClass) {
1089
BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);
1090
1091
fireServiceAdded(bcssae);
1092
}
1093
1094
/**
1095
* Fires a <tt>BeanContextServiceAvailableEvent</tt> indicating that a new
1096
* service has become available.
1097
*
1098
* @param bcssae the <tt>BeanContextServiceAvailableEvent</tt>
1099
*/
1100
protected final void fireServiceAdded(BeanContextServiceAvailableEvent bcssae) {
1101
Object[] copy;
1102
1103
synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1104
1105
for (int i = 0; i < copy.length; i++) {
1106
((BeanContextServicesListener)copy[i]).serviceAvailable(bcssae);
1107
}
1108
}
1109
1110
/**
1111
* Fires a <tt>BeanContextServiceEvent</tt> notifying of a service being revoked.
1112
*
1113
* @param bcsre the <tt>BeanContextServiceRevokedEvent</tt>
1114
*/
1115
protected final void fireServiceRevoked(BeanContextServiceRevokedEvent bcsre) {
1116
Object[] copy;
1117
1118
synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1119
1120
for (int i = 0; i < copy.length; i++) {
1121
((BeanContextServiceRevokedListener)copy[i]).serviceRevoked(bcsre);
1122
}
1123
}
1124
1125
/**
1126
* Fires a <tt>BeanContextServiceRevokedEvent</tt>
1127
* indicating that a particular service is
1128
* no longer available.
1129
* @param serviceClass the service class
1130
* @param revokeNow whether or not the event should be revoked now
1131
*/
1132
protected final void fireServiceRevoked(Class serviceClass, boolean revokeNow) {
1133
Object[] copy;
1134
BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(getBeanContextServicesPeer(), serviceClass, revokeNow);
1135
1136
synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1137
1138
for (int i = 0; i < copy.length; i++) {
1139
((BeanContextServicesListener)copy[i]).serviceRevoked(bcsre);
1140
}
1141
}
1142
1143
/**
1144
* called from BeanContextSupport writeObject before it serializes the
1145
* children ...
1146
*
1147
* This class will serialize any Serializable BeanContextServiceProviders
1148
* herein.
1149
*
1150
* subclasses may envelope this method to insert their own serialization
1151
* processing that has to occur prior to serialization of the children
1152
*/
1153
1154
protected synchronized void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
1155
1156
oos.writeInt(serializable);
1157
1158
if (serializable <= 0) return;
1159
1160
int count = 0;
1161
1162
Iterator i = services.entrySet().iterator();
1163
1164
while (i.hasNext() && count < serializable) {
1165
Map.Entry entry = (Map.Entry)i.next();
1166
BCSSServiceProvider bcsp = null;
1167
1168
try {
1169
bcsp = (BCSSServiceProvider)entry.getValue();
1170
} catch (ClassCastException cce) {
1171
continue;
1172
}
1173
1174
if (bcsp.getServiceProvider() instanceof Serializable) {
1175
oos.writeObject(entry.getKey());
1176
oos.writeObject(bcsp);
1177
count++;
1178
}
1179
}
1180
1181
if (count != serializable)
1182
throw new IOException("wrote different number of service providers than expected");
1183
}
1184
1185
/**
1186
* called from BeanContextSupport readObject before it deserializes the
1187
* children ...
1188
*
1189
* This class will deserialize any Serializable BeanContextServiceProviders
1190
* serialized earlier thus making them available to the children when they
1191
* deserialized.
1192
*
1193
* subclasses may envelope this method to insert their own serialization
1194
* processing that has to occur prior to serialization of the children
1195
*/
1196
1197
protected synchronized void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1198
1199
serializable = ois.readInt();
1200
1201
int count = serializable;
1202
1203
while (count > 0) {
1204
services.put(ois.readObject(), ois.readObject());
1205
count--;
1206
}
1207
}
1208
1209
/**
1210
* serialize the instance
1211
*/
1212
1213
private synchronized void writeObject(ObjectOutputStream oos) throws IOException {
1214
oos.defaultWriteObject();
1215
1216
serialize(oos, (Collection)bcsListeners);
1217
}
1218
1219
/**
1220
* deserialize the instance
1221
*/
1222
1223
private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1224
1225
ois.defaultReadObject();
1226
1227
deserialize(ois, (Collection)bcsListeners);
1228
}
1229
1230
1231
/*
1232
* fields
1233
*/
1234
1235
/**
1236
* all accesses to the <code> protected transient HashMap services </code>
1237
* field should be synchronized on that object
1238
*/
1239
protected transient HashMap services;
1240
1241
/**
1242
* The number of instances of a serializable <tt>BeanContextServceProvider</tt>.
1243
*/
1244
protected transient int serializable = 0;
1245
1246
1247
/**
1248
* Delegate for the <tt>BeanContextServiceProvider</tt>.
1249
*/
1250
protected transient BCSSProxyServiceProvider proxy;
1251
1252
1253
/**
1254
* List of <tt>BeanContextServicesListener</tt> objects.
1255
*/
1256
protected transient ArrayList bcsListeners;
1257
}
1258
1259