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