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
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 }
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
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
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 }
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 }
|
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 services = new HashMap<>(serializable + 1);
133 bcsListeners = new ArrayList<>(1);
134 }
135
136 /**
137 * Gets the <tt>BeanContextServices</tt> associated with this
138 * <tt>BeanContextServicesSupport</tt>.
139 *
140 * @return the instance of <tt>BeanContext</tt>
141 * this object is providing the implementation for.
142 */
143 public BeanContextServices getBeanContextServicesPeer() {
144 return (BeanContextServices)getBeanContextChildPeer();
145 }
146
147 /************************************************************************/
148
149 /*
150 * protected nested class containing per child information, an instance
151 * of which is associated with each child in the "children" hashtable.
152 * subclasses can extend this class to include their own per-child state.
153 *
154 * Note that this 'value' is serialized with the corresponding child 'key'
155 * when the BeanContextSupport is serialized.
156 */
157
158 protected class BCSSChild extends BeanContextSupport.BCSChild {
159
160 private static final long serialVersionUID = -3263851306889194873L;
161
162 /*
163 * private nested class to map serviceClass to Provider and requestors
164 * listeners.
165 */
166
167 class BCSSCServiceClassRef {
168
169 // create an instance of a service ref
170
171 BCSSCServiceClassRef(Class<?> sc, BeanContextServiceProvider bcsp, boolean delegated) {
172 super();
173
174 serviceClass = sc;
175
176 if (delegated)
177 delegateProvider = bcsp;
178 else
179 serviceProvider = bcsp;
180 }
181
182 // add a requestor and assoc listener
183
184 void addRequestor(Object requestor, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
185 BeanContextServiceRevokedListener cbcsrl = requestors.get(requestor);
186
187 if (cbcsrl != null && !cbcsrl.equals(bcsrl))
188 throw new TooManyListenersException();
189
190 requestors.put(requestor, bcsrl);
191 }
192
193 // remove a requestor
194
195 void removeRequestor(Object requestor) {
196 requestors.remove(requestor);
197 }
198
199 // check a requestors listener
200
201 void verifyRequestor(Object requestor, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
202 BeanContextServiceRevokedListener cbcsrl = requestors.get(requestor);
203
204 if (cbcsrl != null && !cbcsrl.equals(bcsrl))
205 throw new TooManyListenersException();
206 }
207
208 void verifyAndMaybeSetProvider(BeanContextServiceProvider bcsp, boolean isDelegated) {
209 BeanContextServiceProvider current;
210
211 if (isDelegated) { // the provider is delegated
212 current = delegateProvider;
213
214 if (current == null || bcsp == null) {
215 delegateProvider = bcsp;
216 return;
217 }
218 } else { // the provider is registered with this BCS
219 current = serviceProvider;
220
221 if (current == null || bcsp == null) {
222 serviceProvider = bcsp;
223 return;
224 }
225 }
226
227 if (!current.equals(bcsp))
228 throw new UnsupportedOperationException("existing service reference obtained from different BeanContextServiceProvider not supported");
229
230 }
231
232 @SuppressWarnings("unchecked") // Cast from clone
233 Iterator<Map.Entry<Object, BeanContextServiceRevokedListener>> cloneOfEntries() {
234 return ((HashMap<Object, BeanContextServiceRevokedListener>)requestors.clone()).entrySet().iterator();
235 }
236
237 Iterator<Map.Entry<Object, BeanContextServiceRevokedListener>> entries() {
238 return requestors.entrySet().iterator();
239 }
240
241 boolean isEmpty() { return requestors.isEmpty(); }
242
243 Class<?> getServiceClass() { return serviceClass; }
244
245 BeanContextServiceProvider getServiceProvider() {
246 return serviceProvider;
247 }
248
249 BeanContextServiceProvider getDelegateProvider() {
250 return delegateProvider;
251 }
252
253 boolean isDelegated() { return delegateProvider != null; }
254
255 void addRef(boolean delegated) {
256 if (delegated) {
257 delegateRefs++;
258 } else {
259 serviceRefs++;
260 }
261 }
262
263
266 if (--delegateRefs == 0) {
267 delegateProvider = null;
268 }
269 } else {
270 if (--serviceRefs <= 0) {
271 serviceProvider = null;
272 }
273 }
274 }
275
276 int getRefs() { return serviceRefs + delegateRefs; }
277
278 int getDelegateRefs() { return delegateRefs; }
279
280 int getServiceRefs() { return serviceRefs; }
281
282 /*
283 * fields
284 */
285
286 Class<?> serviceClass;
287
288 BeanContextServiceProvider serviceProvider;
289 int serviceRefs;
290
291 BeanContextServiceProvider delegateProvider; // proxy
292 int delegateRefs;
293
294 HashMap<Object, BeanContextServiceRevokedListener> requestors = new HashMap<>(1);
295 }
296
297 /*
298 * per service reference info ...
299 */
300
301 class BCSSCServiceRef {
302 BCSSCServiceRef(BCSSCServiceClassRef scref, boolean isDelegated) {
303 serviceClassRef = scref;
304 delegated = isDelegated;
305 }
306
307 void addRef() { refCnt++; }
308 int release() { return --refCnt; }
309
310 BCSSCServiceClassRef getServiceClassRef() { return serviceClassRef; }
311
312 boolean isDelegated() { return delegated; }
313
314 /*
315 * fields
316 */
317
318 BCSSCServiceClassRef serviceClassRef;
319 int refCnt = 1;
320 boolean delegated = false;
321 }
322
323 BCSSChild(Object bcc, Object peer) { super(bcc, peer); }
324
325 // note usage of service per requestor, per service
326
327 synchronized void usingService(Object requestor, Object service, Class<?> serviceClass, BeanContextServiceProvider bcsp, boolean isDelegated, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException, UnsupportedOperationException {
328
329 // first, process mapping from serviceClass to requestor(s)
330
331 BCSSCServiceClassRef serviceClassRef = null;
332
333 if (serviceClasses == null)
334 serviceClasses = new HashMap<>(1);
335 else
336 serviceClassRef = serviceClasses.get(serviceClass);
337
338 if (serviceClassRef == null) { // new service being used ...
339 serviceClassRef = new BCSSCServiceClassRef(serviceClass, bcsp, isDelegated);
340 serviceClasses.put(serviceClass, serviceClassRef);
341
342 } else { // existing service ...
343 serviceClassRef.verifyAndMaybeSetProvider(bcsp, isDelegated); // throws
344 serviceClassRef.verifyRequestor(requestor, bcsrl); // throws
345 }
346
347 serviceClassRef.addRequestor(requestor, bcsrl);
348 serviceClassRef.addRef(isDelegated);
349
350 // now handle mapping from requestor to service(s)
351
352 BCSSCServiceRef serviceRef = null;
353 Map<Object , BCSSCServiceRef> services = null;
354
355 if (serviceRequestors == null) {
356 serviceRequestors = new HashMap<>(1);
357 } else {
358 services = serviceRequestors.get(requestor);
359 }
360
361 if (services == null) {
362 services = new HashMap<>(1);
363
364 serviceRequestors.put(requestor, services);
365 } else
366 serviceRef = services.get(service);
367
368 if (serviceRef == null) {
369 serviceRef = new BCSSCServiceRef(serviceClassRef, isDelegated);
370
371 services.put(service, serviceRef);
372 } else {
373 serviceRef.addRef();
374 }
375 }
376
377 // release a service reference
378
379 synchronized void releaseService(Object requestor, Object service) {
380 if (serviceRequestors == null) return;
381
382 Map<Object, BCSSCServiceRef> services = serviceRequestors.get(requestor);
383
384 if (services == null) return; // oops its not there anymore!
385
386 BCSSCServiceRef serviceRef = services.get(service);
387
388 if (serviceRef == null) return; // oops its not there anymore!
389
390 BCSSCServiceClassRef serviceClassRef = serviceRef.getServiceClassRef();
391 boolean isDelegated = serviceRef.isDelegated();
392 BeanContextServiceProvider bcsp = isDelegated ? serviceClassRef.getDelegateProvider() : serviceClassRef.getServiceProvider();
393
394 bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);
395
396 serviceClassRef.releaseRef(isDelegated);
397 serviceClassRef.removeRequestor(requestor);
398
399 if (serviceRef.release() == 0) {
400
401 services.remove(service);
402
403 if (services.isEmpty()) {
404 serviceRequestors.remove(requestor);
405 serviceClassRef.removeRequestor(requestor);
406 }
407
408 if (serviceRequestors.isEmpty()) {
409 serviceRequestors = null;
410 }
411
412 if (serviceClassRef.isEmpty()) {
413 serviceClasses.remove(serviceClassRef.getServiceClass());
414 }
415
416 if (serviceClasses.isEmpty())
417 serviceClasses = null;
418 }
419 }
420
421 // revoke a service
422
423 synchronized void revokeService(Class<?> serviceClass, boolean isDelegated, boolean revokeNow) {
424 if (serviceClasses == null) return;
425
426 BCSSCServiceClassRef serviceClassRef = serviceClasses.get(serviceClass);
427
428 if (serviceClassRef == null) return;
429
430 Iterator<Map.Entry<Object, BeanContextServiceRevokedListener>> i = serviceClassRef.cloneOfEntries();
431
432 BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClass, revokeNow);
433 boolean noMoreRefs = false;
434
435 while (i.hasNext() && serviceRequestors != null) {
436 Map.Entry<Object,BeanContextServiceRevokedListener> entry = i.next();
437 BeanContextServiceRevokedListener listener = entry.getValue();
438
439 if (revokeNow) {
440 Object requestor = entry.getKey();
441 Map<Object, BCSSCServiceRef> services = serviceRequestors.get(requestor);
442
443 if (services != null) {
444 Iterator<Map.Entry<Object, BCSSCServiceRef>> i1 = services.entrySet().iterator();
445
446 while (i1.hasNext()) {
447 Map.Entry<Object, BCSSCServiceRef> tmp = i1.next();
448
449 BCSSCServiceRef serviceRef = tmp.getValue();
450 if (serviceRef.getServiceClassRef().equals(serviceClassRef) && isDelegated == serviceRef.isDelegated()) {
451 i1.remove();
452 }
453 }
454
455 if (noMoreRefs = services.isEmpty()) {
456 serviceRequestors.remove(requestor);
457 }
458 }
459
460 if (noMoreRefs) serviceClassRef.removeRequestor(requestor);
461 }
462
463 listener.serviceRevoked(bcsre);
464 }
465
466 if (revokeNow && serviceClasses != null) {
467 if (serviceClassRef.isEmpty())
468 serviceClasses.remove(serviceClass);
469
470 if (serviceClasses.isEmpty())
471 serviceClasses = null;
472 }
473
474 if (serviceRequestors != null && serviceRequestors.isEmpty())
475 serviceRequestors = null;
476 }
477
478 // release all references for this child since it has been unnested.
479
480 void cleanupReferences() {
481
482 if (serviceRequestors == null) return;
483
484 Iterator<Map.Entry<Object, Map<Object, BCSSCServiceRef>>> requestors = serviceRequestors.entrySet().iterator();
485
486 while(requestors.hasNext()) {
487 Map.Entry<Object, Map<Object, BCSSCServiceRef>> tmp = requestors.next();
488 Object requestor = tmp.getKey();
489 Iterator<Map.Entry<Object, BCSSCServiceRef>> services = tmp.getValue().entrySet().iterator();
490
491 requestors.remove();
492
493 while (services.hasNext()) {
494 Map.Entry<Object, BCSSCServiceRef> entry = services.next();
495 Object service = entry.getKey();
496 BCSSCServiceRef sref = entry.getValue();
497
498 BCSSCServiceClassRef scref = sref.getServiceClassRef();
499
500 BeanContextServiceProvider bcsp = sref.isDelegated() ? scref.getDelegateProvider() : scref.getServiceProvider();
501
502 scref.removeRequestor(requestor);
503 services.remove();
504
505 while (sref.release() >= 0) {
506 bcsp.releaseService(BeanContextServicesSupport.this.getBeanContextServicesPeer(), requestor, service);
507 }
508 }
509 }
510
511 serviceRequestors = null;
512 serviceClasses = null;
513 }
514
515 void revokeAllDelegatedServicesNow() {
516 if (serviceClasses == null) return;
517
518 Iterator<BCSSCServiceClassRef> serviceClassRefs =
519 new HashSet<>(serviceClasses.values()).iterator();
520
521 while (serviceClassRefs.hasNext()) {
522 BCSSCServiceClassRef serviceClassRef = serviceClassRefs.next();
523
524 if (!serviceClassRef.isDelegated()) continue;
525
526 Iterator<Map.Entry<Object, BeanContextServiceRevokedListener>> i = serviceClassRef.cloneOfEntries();
527 BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(BeanContextServicesSupport.this.getBeanContextServicesPeer(), serviceClassRef.getServiceClass(), true);
528 boolean noMoreRefs = false;
529
530 while (i.hasNext()) {
531 Map.Entry<Object, BeanContextServiceRevokedListener> entry = i.next();
532 BeanContextServiceRevokedListener listener = entry.getValue();
533
534 Object requestor = entry.getKey();
535 Map<Object, BCSSCServiceRef> services = serviceRequestors.get(requestor);
536
537 if (services != null) {
538 Iterator<Map.Entry<Object, BCSSCServiceRef>> i1 = services.entrySet().iterator();
539
540 while (i1.hasNext()) {
541 Map.Entry<Object, BCSSCServiceRef> tmp = i1.next();
542
543 BCSSCServiceRef serviceRef = tmp.getValue();
544 if (serviceRef.getServiceClassRef().equals(serviceClassRef) && serviceRef.isDelegated()) {
545 i1.remove();
546 }
547 }
548
549 if (noMoreRefs = services.isEmpty()) {
550 serviceRequestors.remove(requestor);
551 }
552 }
553
554 if (noMoreRefs) serviceClassRef.removeRequestor(requestor);
555
556 listener.serviceRevoked(bcsre);
557
558 if (serviceClassRef.isEmpty())
559 serviceClasses.remove(serviceClassRef.getServiceClass());
560 }
561 }
562
563 if (serviceClasses.isEmpty()) serviceClasses = null;
564
565 if (serviceRequestors != null && serviceRequestors.isEmpty())
566 serviceRequestors = null;
567 }
568
569 /*
570 * fields
571 */
572
573 private transient HashMap<Class<?>, BCSSCServiceClassRef> serviceClasses;
574 private transient HashMap<Object, Map<Object, BeanContextServicesSupport.BCSSChild.BCSSCServiceRef>> serviceRequestors;
575 }
576
577 /**
578 * <p>
579 * Subclasses can override this method to insert their own subclass
580 * of Child without having to override add() or the other Collection
581 * methods that add children to the set.
582 * </p>
583 *
584 * @param targetChild the child to create the Child on behalf of
585 * @param peer the peer if the targetChild and peer are related by BeanContextProxy
586 */
587
588 protected BCSChild createBCSChild(Object targetChild, Object peer) {
589 return new BCSSChild(targetChild, peer);
590 }
591
592 /************************************************************************/
593
594 /**
595 * subclasses may subclass this nested class to add behaviors for
596 * each BeanContextServicesProvider.
597 */
598
599 protected static class BCSSServiceProvider implements Serializable {
600 private static final long serialVersionUID = 861278251667444782L;
601
602 BCSSServiceProvider(Class<?> sc, BeanContextServiceProvider bcsp) {
603 super();
604
605 serviceProvider = bcsp;
606 }
607
608 /**
609 * Returns the service provider.
610 * @return the service provider
611 */
612 protected BeanContextServiceProvider getServiceProvider() {
613 return serviceProvider;
614 }
615
616 /**
617 * The service provider.
618 */
619
620 protected BeanContextServiceProvider serviceProvider;
621 }
622
623 /**
624 * subclasses can override this method to create new subclasses of
625 * BCSSServiceProvider without having to override addService() in
626 * order to instantiate.
627 * @param sc the class
628 * @param bcsp the service provider
629 * @return a service provider without overriding addService()
630 */
631
632 protected BCSSServiceProvider createBCSSServiceProvider(Class<?> sc, BeanContextServiceProvider bcsp) {
633 return new BCSSServiceProvider(sc, bcsp);
634 }
635
636 /************************************************************************/
637
638 /**
639 * add a BeanContextServicesListener
640 *
641 * @throws NullPointerException if the argument is null
642 */
643
644 public void addBeanContextServicesListener(BeanContextServicesListener bcsl) {
645 if (bcsl == null) throw new NullPointerException("bcsl");
646
647 synchronized(bcsListeners) {
648 if (bcsListeners.contains(bcsl))
649 return;
650 else
651 bcsListeners.add(bcsl);
652 }
656 * remove a BeanContextServicesListener
657 */
658
659 public void removeBeanContextServicesListener(BeanContextServicesListener bcsl) {
660 if (bcsl == null) throw new NullPointerException("bcsl");
661
662 synchronized(bcsListeners) {
663 if (!bcsListeners.contains(bcsl))
664 return;
665 else
666 bcsListeners.remove(bcsl);
667 }
668 }
669
670 /**
671 * add a service
672 * @param serviceClass the service class
673 * @param bcsp the service provider
674 */
675
676 public boolean addService(Class<?> serviceClass, BeanContextServiceProvider bcsp) {
677 return addService(serviceClass, bcsp, true);
678 }
679
680 /**
681 * add a service
682 * @param serviceClass the service class
683 * @param bcsp the service provider
684 * @param fireEvent whether or not an event should be fired
685 * @return true if the service was successfully added
686 */
687
688 protected boolean addService(Class<?> serviceClass, BeanContextServiceProvider bcsp, boolean fireEvent) {
689
690 if (serviceClass == null) throw new NullPointerException("serviceClass");
691 if (bcsp == null) throw new NullPointerException("bcsp");
692
693 synchronized(BeanContext.globalHierarchyLock) {
694 if (services.containsKey(serviceClass))
695 return false;
696 else {
697 services.put(serviceClass, createBCSSServiceProvider(serviceClass, bcsp));
698
699 if (bcsp instanceof Serializable) serializable++;
700
701 if (!fireEvent) return true;
702
703
704 BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);
705
706 fireServiceAdded(bcssae);
707
708 synchronized(children) {
709 Iterator<Object> i = children.keySet().iterator();
710
711 while (i.hasNext()) {
712 Object c = i.next();
713
714 if (c instanceof BeanContextServices) {
715 ((BeanContextServicesListener)c).serviceAvailable(bcssae);
716 }
717 }
718 }
719
720 return true;
721 }
722 }
723 }
724
725 /**
726 * remove a service
727 * @param serviceClass the service class
728 * @param bcsp the service provider
729 * @param revokeCurrentServicesNow whether or not to revoke the service
730 */
731
732 public void revokeService(Class<?> serviceClass, BeanContextServiceProvider bcsp, boolean revokeCurrentServicesNow) {
733
734 if (serviceClass == null) throw new NullPointerException("serviceClass");
735 if (bcsp == null) throw new NullPointerException("bcsp");
736
737 synchronized(BeanContext.globalHierarchyLock) {
738 if (!services.containsKey(serviceClass)) return;
739
740 BCSSServiceProvider bcsssp = services.get(serviceClass);
741
742 if (!bcsssp.getServiceProvider().equals(bcsp))
743 throw new IllegalArgumentException("service provider mismatch");
744
745 services.remove(serviceClass);
746
747 if (bcsp instanceof Serializable) serializable--;
748
749 Iterator<BeanContextSupport.BCSChild> i = bcsChildren(); // get the BCSChild values.
750
751 while (i.hasNext()) {
752 ((BCSSChild)i.next()).revokeService(serviceClass, false, revokeCurrentServicesNow);
753 }
754
755 fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
756 }
757 }
758
759 /**
760 * has a service, which may be delegated
761 */
762
763 public synchronized boolean hasService(Class<?> serviceClass) {
764 if (serviceClass == null) throw new NullPointerException("serviceClass");
765
766 synchronized(BeanContext.globalHierarchyLock) {
767 if (services.containsKey(serviceClass)) return true;
768
769 BeanContextServices bcs = null;
770
771 try {
772 bcs = (BeanContextServices)getBeanContext();
773 } catch (ClassCastException cce) {
774 return false;
775 }
776
777 return bcs == null ? false : bcs.hasService(serviceClass);
778 }
779 }
780
781 /************************************************************************/
782
783 /*
784 * a nested subclass used to represent a proxy for serviceClasses delegated
785 * to an enclosing BeanContext.
786 */
787
788 protected class BCSSProxyServiceProvider implements BeanContextServiceProvider, BeanContextServiceRevokedListener {
789
790 BCSSProxyServiceProvider(BeanContextServices bcs) {
791 super();
792
793 nestingCtxt = bcs;
794 }
795
796 public Object getService(BeanContextServices bcs, Object requestor, Class<?> serviceClass, Object serviceSelector) {
797 Object service = null;
798
799 try {
800 service = nestingCtxt.getService(bcs, requestor, serviceClass, serviceSelector, this);
801 } catch (TooManyListenersException tmle) {
802 return null;
803 }
804
805 return service;
806 }
807
808 public void releaseService(BeanContextServices bcs, Object requestor, Object service) {
809 nestingCtxt.releaseService(bcs, requestor, service);
810 }
811
812 public Iterator<?> getCurrentServiceSelectors(BeanContextServices bcs, Class<?> serviceClass) {
813 return nestingCtxt.getCurrentServiceSelectors(serviceClass);
814 }
815
816 public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
817 Iterator<BeanContextSupport.BCSChild> i = bcsChildren(); // get the BCSChild values.
818
819 while (i.hasNext()) {
820 ((BCSSChild)i.next()).revokeService(bcsre.getServiceClass(), true, bcsre.isCurrentServiceInvalidNow());
821 }
822 }
823
824 /*
825 * fields
826 */
827
828 private BeanContextServices nestingCtxt;
829 }
830
831 /************************************************************************/
832
833 /**
834 * obtain a service which may be delegated
835 */
836
837 public Object getService(BeanContextChild child, Object requestor, Class<?> serviceClass, Object serviceSelector, BeanContextServiceRevokedListener bcsrl) throws TooManyListenersException {
838 if (child == null) throw new NullPointerException("child");
839 if (serviceClass == null) throw new NullPointerException("serviceClass");
840 if (requestor == null) throw new NullPointerException("requestor");
841 if (bcsrl == null) throw new NullPointerException("bcsrl");
842
843 Object service = null;
844 BCSSChild bcsc;
845 BeanContextServices bcssp = getBeanContextServicesPeer();
846
847 synchronized(BeanContext.globalHierarchyLock) {
848 synchronized(children) { bcsc = (BCSSChild)children.get(child); }
849
850 if (bcsc == null) throw new IllegalArgumentException("not a child of this context"); // not a child ...
851
852 BCSSServiceProvider bcsssp = services.get(serviceClass);
853
854 if (bcsssp != null) {
855 BeanContextServiceProvider bcsp = bcsssp.getServiceProvider();
856 service = bcsp.getService(bcssp, requestor, serviceClass, serviceSelector);
857 if (service != null) { // do bookkeeping ...
858 try {
859 bcsc.usingService(requestor, service, serviceClass, bcsp, false, bcsrl);
860 } catch (TooManyListenersException tmle) {
861 bcsp.releaseService(bcssp, requestor, service);
862 throw tmle;
863 } catch (UnsupportedOperationException uope) {
864 bcsp.releaseService(bcssp, requestor, service);
865 throw uope; // unchecked rt exception
866 }
867
868 return service;
869 }
870 }
871
872
903 if (child == null) throw new NullPointerException("child");
904 if (requestor == null) throw new NullPointerException("requestor");
905 if (service == null) throw new NullPointerException("service");
906
907 BCSSChild bcsc;
908
909 synchronized(BeanContext.globalHierarchyLock) {
910 synchronized(children) { bcsc = (BCSSChild)children.get(child); }
911
912 if (bcsc != null)
913 bcsc.releaseService(requestor, service);
914 else
915 throw new IllegalArgumentException("child actual is not a child of this BeanContext");
916 }
917 }
918
919 /**
920 * @return an iterator for all the currently registered service classes.
921 */
922
923 public Iterator<Object> getCurrentServiceClasses() {
924 return new BCSIterator(services.keySet().iterator());
925 }
926
927 /**
928 * @return an iterator for all the currently available service selectors
929 * (if any) available for the specified service.
930 */
931
932 public Iterator<?> getCurrentServiceSelectors(Class<?> serviceClass) {
933
934 BCSSServiceProvider bcsssp = services.get(serviceClass);
935
936 return bcsssp != null ? new BCSIterator(bcsssp.getServiceProvider().getCurrentServiceSelectors(getBeanContextServicesPeer(), serviceClass)) : null;
937 }
938
939 /**
940 * BeanContextServicesListener callback, propagates event to all
941 * currently registered listeners and BeanContextServices children,
942 * if this BeanContextService does not already implement this service
943 * itself.
944 *
945 * subclasses may override or envelope this method to implement their
946 * own propagation semantics.
947 */
948
949 public void serviceAvailable(BeanContextServiceAvailableEvent bcssae) {
950 synchronized(BeanContext.globalHierarchyLock) {
951 if (services.containsKey(bcssae.getServiceClass())) return;
952
953 fireServiceAdded(bcssae);
954
955 Iterator<Object> i;
956
957 synchronized(children) {
958 i = children.keySet().iterator();
959 }
960
961 while (i.hasNext()) {
962 Object c = i.next();
963
964 if (c instanceof BeanContextServices) {
965 ((BeanContextServicesListener)c).serviceAvailable(bcssae);
966 }
967 }
968 }
969 }
970
971 /**
972 * BeanContextServicesListener callback, propagates event to all
973 * currently registered listeners and BeanContextServices children,
974 * if this BeanContextService does not already implement this service
975 * itself.
976 *
977 * subclasses may override or envelope this method to implement their
978 * own propagation semantics.
979 */
980
981 public void serviceRevoked(BeanContextServiceRevokedEvent bcssre) {
982 synchronized(BeanContext.globalHierarchyLock) {
983 if (services.containsKey(bcssre.getServiceClass())) return;
984
985 fireServiceRevoked(bcssre);
986
987 Iterator<Object> i;
988
989 synchronized(children) {
990 i = children.keySet().iterator();
991 }
992
993 while (i.hasNext()) {
994 Object c = i.next();
995
996 if (c instanceof BeanContextServices) {
997 ((BeanContextServicesListener)c).serviceRevoked(bcssre);
998 }
999 }
1000 }
1001 }
1002
1003 /**
1004 * Gets the <tt>BeanContextServicesListener</tt> (if any) of the specified
1005 * child.
1006 *
1007 * @param child the specified child
1070 protected synchronized void initializeBeanContextResources() {
1071 super.initializeBeanContextResources();
1072
1073 BeanContext nbc = getBeanContext();
1074
1075 if (nbc == null) return;
1076
1077 try {
1078 BeanContextServices bcs = (BeanContextServices)nbc;
1079
1080 proxy = new BCSSProxyServiceProvider(bcs);
1081 } catch (ClassCastException cce) {
1082 // do nothing ...
1083 }
1084 }
1085
1086 /**
1087 * Fires a <tt>BeanContextServiceEvent</tt> notifying of a new service.
1088 * @param serviceClass the service class
1089 */
1090 protected final void fireServiceAdded(Class<?> serviceClass) {
1091 BeanContextServiceAvailableEvent bcssae = new BeanContextServiceAvailableEvent(getBeanContextServicesPeer(), serviceClass);
1092
1093 fireServiceAdded(bcssae);
1094 }
1095
1096 /**
1097 * Fires a <tt>BeanContextServiceAvailableEvent</tt> indicating that a new
1098 * service has become available.
1099 *
1100 * @param bcssae the <tt>BeanContextServiceAvailableEvent</tt>
1101 */
1102 protected final void fireServiceAdded(BeanContextServiceAvailableEvent bcssae) {
1103 Object[] copy;
1104
1105 synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1106
1107 for (int i = 0; i < copy.length; i++) {
1108 ((BeanContextServicesListener)copy[i]).serviceAvailable(bcssae);
1109 }
1110 }
1114 *
1115 * @param bcsre the <tt>BeanContextServiceRevokedEvent</tt>
1116 */
1117 protected final void fireServiceRevoked(BeanContextServiceRevokedEvent bcsre) {
1118 Object[] copy;
1119
1120 synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1121
1122 for (int i = 0; i < copy.length; i++) {
1123 ((BeanContextServiceRevokedListener)copy[i]).serviceRevoked(bcsre);
1124 }
1125 }
1126
1127 /**
1128 * Fires a <tt>BeanContextServiceRevokedEvent</tt>
1129 * indicating that a particular service is
1130 * no longer available.
1131 * @param serviceClass the service class
1132 * @param revokeNow whether or not the event should be revoked now
1133 */
1134 protected final void fireServiceRevoked(Class<?> serviceClass, boolean revokeNow) {
1135 Object[] copy;
1136 BeanContextServiceRevokedEvent bcsre = new BeanContextServiceRevokedEvent(getBeanContextServicesPeer(), serviceClass, revokeNow);
1137
1138 synchronized (bcsListeners) { copy = bcsListeners.toArray(); }
1139
1140 for (int i = 0; i < copy.length; i++) {
1141 ((BeanContextServicesListener)copy[i]).serviceRevoked(bcsre);
1142 }
1143 }
1144
1145 /**
1146 * called from BeanContextSupport writeObject before it serializes the
1147 * children ...
1148 *
1149 * This class will serialize any Serializable BeanContextServiceProviders
1150 * herein.
1151 *
1152 * subclasses may envelope this method to insert their own serialization
1153 * processing that has to occur prior to serialization of the children
1154 */
1155
1156 protected synchronized void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
1157
1158 oos.writeInt(serializable);
1159
1160 if (serializable <= 0) return;
1161
1162 int count = 0;
1163
1164 Iterator<Map.Entry<Object, BCSSServiceProvider>> i = services.entrySet().iterator();
1165
1166 while (i.hasNext() && count < serializable) {
1167 Map.Entry<Object, BCSSServiceProvider> entry = i.next();
1168 BCSSServiceProvider bcsp = null;
1169
1170 try {
1171 bcsp = entry.getValue();
1172 } catch (ClassCastException cce) {
1173 continue;
1174 }
1175
1176 if (bcsp.getServiceProvider() instanceof Serializable) {
1177 oos.writeObject(entry.getKey());
1178 oos.writeObject(bcsp);
1179 count++;
1180 }
1181 }
1182
1183 if (count != serializable)
1184 throw new IOException("wrote different number of service providers than expected");
1185 }
1186
1187 /**
1188 * called from BeanContextSupport readObject before it deserializes the
1189 * children ...
1190 *
1191 * This class will deserialize any Serializable BeanContextServiceProviders
1192 * serialized earlier thus making them available to the children when they
1193 * deserialized.
1194 *
1195 * subclasses may envelope this method to insert their own serialization
1196 * processing that has to occur prior to serialization of the children
1197 */
1198
1199 protected synchronized void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1200
1201 serializable = ois.readInt();
1202
1203 int count = serializable;
1204
1205 while (count > 0) {
1206 services.put(ois.readObject(), (BCSSServiceProvider)ois.readObject());
1207 count--;
1208 }
1209 }
1210
1211 /**
1212 * serialize the instance
1213 */
1214
1215 private synchronized void writeObject(ObjectOutputStream oos) throws IOException {
1216 oos.defaultWriteObject();
1217
1218 serialize(oos, (Collection)bcsListeners);
1219 }
1220
1221 /**
1222 * deserialize the instance
1223 */
1224
1225 private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1226
1227 ois.defaultReadObject();
1228
1229 deserialize(ois, (Collection)bcsListeners);
1230 }
1231
1232
1233 /*
1234 * fields
1235 */
1236
1237 /**
1238 * all accesses to the <code> protected transient HashMap services </code>
1239 * field should be synchronized on that object
1240 */
1241 protected transient HashMap<Object, BCSSServiceProvider> services;
1242
1243 /**
1244 * The number of instances of a serializable <tt>BeanContextServceProvider</tt>.
1245 */
1246 protected transient int serializable = 0;
1247
1248
1249 /**
1250 * Delegate for the <tt>BeanContextServiceProvider</tt>.
1251 */
1252 protected transient BCSSProxyServiceProvider proxy;
1253
1254
1255 /**
1256 * List of <tt>BeanContextServicesListener</tt> objects.
1257 */
1258 protected transient ArrayList<BeanContextServicesListener> bcsListeners;
1259 }
|