001 /* BeanContextServicesSupport.java --
002 Copyright (C) 2003, 2005 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.beans.beancontext;
040
041 import java.io.IOException;
042 import java.io.ObjectInputStream;
043 import java.io.ObjectOutputStream;
044 import java.io.Serializable;
045 import java.util.ArrayList;
046 import java.util.HashMap;
047 import java.util.HashSet;
048 import java.util.Iterator;
049 import java.util.List;
050 import java.util.Locale;
051 import java.util.Set;
052 import java.util.TooManyListenersException;
053
054 /**
055 * This is a helper class for implementing a bean context which
056 * supplies services. It is intended to be used either by
057 * subclassing or by calling methods of this implementation
058 * from another.
059 *
060 * @author Michael Koch
061 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
062 * @since 1.2
063 */
064 public class BeanContextServicesSupport
065 extends BeanContextSupport
066 implements BeanContextServices
067 {
068 private static final long serialVersionUID = -8494482757288719206L;
069
070 protected class BCSSChild
071 extends BeanContextSupport.BCSChild
072 {
073 private static final long serialVersionUID = -3263851306889194873L;
074
075 BCSSChild(Object targetChild, Object peer)
076 {
077 super(targetChild, peer);
078 }
079 }
080
081 protected class BCSSProxyServiceProvider
082 implements BeanContextServiceProvider,
083 BeanContextServiceRevokedListener
084 {
085 private static final long serialVersionUID = 7078212910685744490L;
086
087 private BeanContextServiceProvider provider;
088
089 BCSSProxyServiceProvider(BeanContextServiceProvider p)
090 {
091 provider = p;
092 }
093
094 public Iterator getCurrentServiceSelectors (BeanContextServices bcs,
095 Class serviceClass)
096 {
097 return provider.getCurrentServiceSelectors(bcs, serviceClass);
098 }
099
100 public Object getService (BeanContextServices bcs,
101 Object requestor,
102 Class serviceClass,
103 Object serviceSelector)
104 {
105 return provider.getService(bcs, requestor, serviceClass,
106 serviceSelector);
107 }
108
109 public void releaseService (BeanContextServices bcs,
110 Object requestor,
111 Object service)
112 {
113 provider.releaseService(bcs, requestor, service);
114 }
115
116 public void serviceRevoked (BeanContextServiceRevokedEvent bcsre)
117 {
118 if (provider instanceof BeanContextServiceRevokedListener)
119 ((BeanContextServiceRevokedListener) provider).serviceRevoked(bcsre);
120 }
121 }
122
123 protected static class BCSSServiceProvider
124 implements Serializable
125 {
126 private static final long serialVersionUID = 861278251667444782L;
127
128 protected BeanContextServiceProvider serviceProvider;
129
130 private Class serviceClass;
131
132 private BCSSServiceProvider(Class serviceClass,
133 BeanContextServiceProvider provider)
134 {
135 this.serviceClass = serviceClass;
136 serviceProvider = provider;
137 }
138
139 protected BeanContextServiceProvider getServiceProvider()
140 {
141 return serviceProvider;
142 }
143
144 private Class getServiceClass()
145 {
146 return serviceClass;
147 }
148
149 }
150
151 /**
152 * Represents a request for a service. This is
153 * a common superclass used by the classes which maintain
154 * the listener-requestor and service-requestor relationships.
155 *
156 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
157 */
158 private static abstract class Request
159 {
160 private Object requestor;
161
162 public Request(Object requestor)
163 {
164 this.requestor = requestor;
165 }
166
167 public boolean equals(Object obj)
168 {
169 if (obj instanceof Request)
170 {
171 Request req = (Request) obj;
172 return req.getRequestor().equals(requestor);
173 }
174 return false;
175 }
176
177 public Object getRequestor()
178 {
179 return requestor;
180 }
181
182 }
183
184 /**
185 * Represents a relationship between a service requestor
186 * and a revocation listener.
187 *
188 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
189 */
190 private static class ServiceRequest
191 extends Request
192 {
193
194 private BeanContextServiceRevokedListener listener;
195
196 public ServiceRequest(Object requestor,
197 BeanContextServiceRevokedListener listener)
198 {
199 super(requestor);
200 this.listener = listener;
201 }
202
203 public boolean equals(Object obj)
204 {
205 if (obj instanceof ServiceRequest)
206 {
207 ServiceRequest sr = (ServiceRequest) obj;
208 return (super.equals(obj) &&
209 sr.getListener().equals(listener));
210 }
211 return false;
212 }
213
214 public BeanContextServiceRevokedListener getListener()
215 {
216 return listener;
217 }
218 }
219
220 /**
221 * Represents a relationship between a service requestor
222 * and a service instance.
223 *
224 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
225 */
226 private static class ServiceLease
227 extends Request
228 {
229
230 private Object service;
231
232 public ServiceLease(Object requestor, Object service)
233 {
234 super(requestor);
235 this.service = service;
236 }
237
238 public boolean equals(Object obj)
239 {
240 if (obj instanceof ServiceLease)
241 {
242 ServiceLease sl = (ServiceLease) obj;
243 return (super.equals(obj) &&
244 sl.getService().equals(service));
245 }
246 return false;
247 }
248
249 public Object getService()
250 {
251 return service;
252 }
253 }
254
255 /**
256 * A collection of listeners who receive availability
257 * and revocation notifications.
258 */
259 protected transient ArrayList bcsListeners;
260
261 protected transient BCSSProxyServiceProvider proxy;
262
263 /**
264 * The number of serializable service providers.
265 */
266 protected transient int serializable;
267
268 /**
269 * A map of registered services, linking the service
270 * class to its associated {@link BCSSServiceProvider}.
271 */
272 protected transient HashMap services;
273
274 /**
275 * A map of children to a list of services they
276 * have obtained.
277 */
278 private transient HashMap serviceUsers;
279
280 /**
281 * A map of services to {@link ServiceRequest}s.
282 */
283 private transient HashMap serviceRequests;
284
285 /**
286 * A map of {@link ServiceLease}s to providers.
287 */
288 private transient HashMap serviceLeases;
289
290 /**
291 * Construct a {@link BeanContextServicesSupport} instance.
292 */
293 public BeanContextServicesSupport ()
294 {
295 super();
296 }
297
298 /**
299 * Construct a {@link BeanContextServicesSupport} instance.
300 *
301 * @param peer the bean context services peer (<code>null</code> permitted).
302 */
303 public BeanContextServicesSupport (BeanContextServices peer)
304 {
305 super(peer);
306 }
307
308 /**
309 * Construct a {@link BeanContextServicesSupport} instance.
310 *
311 * @param peer the bean context peer (<code>null</code> permitted).
312 * @param locale the locale (<code>null</code> permitted, equivalent to
313 * the default locale).
314 */
315 public BeanContextServicesSupport(BeanContextServices peer, Locale locale)
316 {
317 super(peer, locale);
318 }
319
320 /**
321 * Construct a {@link BeanContextServicesSupport} instance.
322 *
323 * @param peer the bean context peer (<code>null</code> permitted).
324 * @param locale the locale (<code>null</code> permitted, equivalent to
325 * the default locale).
326 * @param dtime a flag indicating whether or not the bean context is in
327 * design time mode.
328 */
329 public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
330 boolean dtime)
331 {
332 super(peer, locale, dtime);
333 }
334
335 /**
336 * Construct a {@link BeanContextServicesSupport} instance.
337 *
338 * @param peer the bean context peer (<code>null</code> permitted).
339 * @param locale the locale (<code>null</code> permitted, equivalent to
340 * the default locale).
341 * @param dtime a flag indicating whether or not the bean context is in
342 * design time mode.
343 * @param visible initial value of the <code>okToUseGui</code> flag.
344 */
345 public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
346 boolean dtime, boolean visible)
347 {
348 super(peer, locale, dtime, visible);
349 }
350
351 /**
352 * Adds a new listener for service availability and
353 * revocation events.
354 *
355 * @param listener the listener to add.
356 */
357 public void addBeanContextServicesListener
358 (BeanContextServicesListener listener)
359 {
360 synchronized (bcsListeners)
361 {
362 if (! bcsListeners.contains(listener))
363 bcsListeners.add(listener);
364 }
365 }
366
367 /**
368 * Registers a new service from the specified service provider.
369 * The service is internally associated with the service provider
370 * and a <code>BeanContextServiceAvailableEvent</code> is fired. If
371 * the service is already registered, then this method instead
372 * returns <code>false</code>. This is equivalent to calling
373 * <code>addService(serviceClass, bcsp, true)</code>.
374 *
375 * @param serviceClass the class of the service to be registered.
376 * @param bcsp the provider of the given service.
377 * @return true if the service was registered successfully.
378 * @see #addService(Class, BeanContextServiceProvider, boolean)
379 */
380 public boolean addService (Class serviceClass,
381 BeanContextServiceProvider bcsp)
382 {
383 return addService(serviceClass, bcsp, true);
384 }
385
386 /**
387 * Registers a new service from the specified service provider.
388 * The service is internally associated with the service provider
389 * and (if <code>fireEvent</code> is true) a
390 * <code>BeanContextServiceAvailableEvent</code> is fired. If
391 * the service is already registered, then this method instead
392 * returns <code>false</code>.
393 *
394 * @param serviceClass the class of the service to be registered.
395 * @param bcsp the provider of the given service.
396 * @param fireEvent true if a service availability event should
397 * be fired.
398 * @return true if the service was registered successfully.
399 */
400 protected boolean addService (Class serviceClass,
401 BeanContextServiceProvider bcsp,
402 boolean fireEvent)
403 {
404 synchronized (globalHierarchyLock)
405 {
406 synchronized (services)
407 {
408 if (services.containsKey(serviceClass))
409 return false;
410 services.put(serviceClass,
411 createBCSSServiceProvider(serviceClass, bcsp));
412 if (bcsp instanceof Serializable)
413 ++serializable;
414 if (fireEvent)
415 fireServiceAdded(serviceClass);
416 return true;
417 }
418 }
419 }
420
421 /**
422 * Deserializes any service providers which are serializable. This
423 * method is called by the <code>readObject</code> method of
424 * {@link BeanContextSupport} prior to deserialization of the children.
425 * Subclasses may envelope its behaviour in order to read further
426 * serialized data to the stream.
427 *
428 * @param ois the stream from which data is being deserialized.
429 * @throws IOException if an I/O error occurs.
430 * @throws ClassNotFoundException if the class of a deserialized object
431 * can not be found.
432 */
433 protected void bcsPreDeserializationHook (ObjectInputStream ois)
434 throws ClassNotFoundException, IOException
435 {
436 serializable = ois.readInt();
437 for (int a = 0; a < serializable; ++a)
438 {
439 BCSSServiceProvider bcsssp = (BCSSServiceProvider) ois.readObject();
440 addService(bcsssp.getServiceClass(), bcsssp.getServiceProvider());
441 }
442 }
443
444 /**
445 * Serializes any service providers which are serializable. This
446 * method is called by the <code>writeObject</code> method of
447 * {@link BeanContextSupport} prior to serialization of the children.
448 * Subclasses may envelope its behaviour in order to add further
449 * serialized data to the stream.
450 *
451 * @param oos the stream to which data is being serialized.
452 * @throws IOException if an I/O error occurs.
453 */
454 protected void bcsPreSerializationHook (ObjectOutputStream oos)
455 throws IOException
456 {
457 oos.writeInt(serializable);
458 synchronized (services)
459 {
460 Iterator i = services.values().iterator();
461 while (i.hasNext())
462 {
463 BCSSServiceProvider bcsssp = (BCSSServiceProvider) i.next();
464 if (bcsssp.getServiceProvider() instanceof Serializable)
465 oos.writeObject(bcsssp);
466 }
467 }
468 }
469
470 /**
471 * Revokes any services used by a child that has just been removed.
472 * The superclass ({@link BeanContextSupport}) calls this method
473 * when a child has just been successfully removed. Subclasses can
474 * extend this method in order to perform additional operations
475 * on child removal.
476 *
477 * @param child the child being removed.
478 * @param bcsc the support object for the child.
479 */
480 protected void childJustRemovedHook (Object child,
481 BeanContextSupport.BCSChild bcsc)
482 {
483 if (child instanceof BeanContextChild)
484 {
485 BeanContextChild bcchild = (BeanContextChild) child;
486 Iterator childServices = ((List) serviceUsers.get(bcchild)).iterator();
487 while (childServices.hasNext())
488 releaseService(bcchild, this, childServices.next());
489 serviceUsers.remove(bcchild);
490 }
491 }
492
493 /**
494 * Overrides the {@link BeanContextSupport#createBCSChild} method
495 * so as to use a {@link BCSSChild} instead.
496 *
497 * @param targetChild the child to create the child for.
498 * @param peer the peer which relates to the child if a proxy is used.
499 * @return a new instance of {@link BCSSChild}.
500 */
501 protected BeanContextSupport.BCSChild createBCSChild (Object targetChild,
502 Object peer)
503 {
504 return new BCSSChild(targetChild, peer);
505 }
506
507 /**
508 * Provides a hook so that subclasses can replace the
509 * {@link BCSSServiceProvider} class, used to store registered
510 * service providers, with a subclass without replacing the
511 * {@link #addService(Class, BeanContextServiceProvider)} method.
512 *
513 * @param sc the class of service being registered.
514 * @param bcsp the provider of the service.
515 * @return a instance of {@link BCSSServiceProvider} wrapping the provider.
516 */
517 protected BeanContextServicesSupport.BCSSServiceProvider
518 createBCSSServiceProvider (Class sc, BeanContextServiceProvider bcsp)
519 {
520 return new BCSSServiceProvider(sc, bcsp);
521 }
522
523 /**
524 * Sends a <code>BeanContextServiceAvailableEvent</code> to all
525 * registered listeners.
526 *
527 * @param bcssae the event to send.
528 */
529 protected final void fireServiceAdded (BeanContextServiceAvailableEvent bcssae)
530 {
531 synchronized (bcsListeners)
532 {
533 int size = bcsListeners.size();
534 for (int i = 0; i < size; ++i)
535 {
536 BeanContextServicesListener bcsl
537 = (BeanContextServicesListener) bcsListeners.get(i);
538 bcsl.serviceAvailable(bcssae);
539 }
540 }
541 }
542
543 /**
544 * Sends a <code>BeanContextServiceAvailableEvent</code> to all
545 * registered listeners.
546 *
547 * @param serviceClass the service that is now available.
548 * @see #fireServiceAdded(BeanContextServiceAvailableEvent)
549 */
550 protected final void fireServiceAdded (Class serviceClass)
551 {
552 fireServiceAdded(new BeanContextServiceAvailableEvent(this,
553 serviceClass));
554 }
555
556 /**
557 * Sends a <code>BeanContextServiceRevokedEvent</code> to all
558 * registered listeners.
559 *
560 * @param event the event to send.
561 */
562 protected final void fireServiceRevoked(BeanContextServiceRevokedEvent event)
563 {
564 synchronized (bcsListeners)
565 {
566 int size = bcsListeners.size();
567 for (int i = 0; i < size; ++i)
568 {
569 BeanContextServicesListener bcsl
570 = (BeanContextServicesListener) bcsListeners.get(i);
571 bcsl.serviceRevoked(event);
572 }
573 List requests = (List) serviceRequests.get(event.getServiceClass());
574 if (requests != null)
575 {
576 Iterator i = requests.iterator();
577 while (i.hasNext())
578 {
579 ServiceRequest r = (ServiceRequest) i.next();
580 r.getListener().serviceRevoked(event);
581 }
582 }
583 }
584 }
585
586 /**
587 * Sends a <code>BeanContextServiceRevokedEvent</code> to all
588 * registered listeners.
589 *
590 * @param serviceClass the service that has been revoked.
591 * @see #fireServiceRevoked(BeanContextServiceRevokedEvent)
592 */
593 protected final void fireServiceRevoked (Class serviceClass,
594 boolean revokeNow)
595 {
596 fireServiceRevoked(new BeanContextServiceRevokedEvent(this, serviceClass,
597 revokeNow));
598 }
599
600 /**
601 * Returns the services peer given at construction time,
602 * or <code>null</code> if no peer was given.
603 *
604 * @return the {@link BeanContextServices} peer.
605 */
606 public BeanContextServices getBeanContextServicesPeer ()
607 {
608 return (BeanContextServices) beanContextChildPeer;
609 }
610
611 /**
612 * Returns <code>child</code> as an instance of
613 * {@link BeanContextServicesListener}, or <code>null</code> if
614 * <code>child</code> does not implement that interface.
615 *
616 * @param child the child (<code>null</code> permitted).
617 *
618 * @return The child cast to {@link BeanContextServicesListener}.
619 */
620 protected static final BeanContextServicesListener
621 getChildBeanContextServicesListener(Object child)
622 {
623 if (child instanceof BeanContextServicesListener)
624 return (BeanContextServicesListener) child;
625 else
626 return null;
627 }
628
629 /**
630 * Returns an iterator over the currently available
631 * services.
632 *
633 * @return an iterator over the currently available services.
634 */
635 public Iterator getCurrentServiceClasses ()
636 {
637 synchronized (globalHierarchyLock)
638 {
639 synchronized (services)
640 {
641 return services.keySet().iterator();
642 }
643 }
644 }
645
646 /**
647 * Returns an iterator over the service selectors of the service
648 * provider for the given service. The iterator is actually
649 * obtained by calling the
650 * {@link BeanContextServiceProvider#getCurrentServiceSelectors}
651 * of the provider itself. If the specified service is not available,
652 * <code>null</code> is returned.
653 *
654 * @param serviceClass the service whose provider's selectors should
655 * be iterated over.
656 * @return an {@link Iterator} over the service selectors of the
657 * provider of the given service.
658 */
659 public Iterator getCurrentServiceSelectors (Class serviceClass)
660 {
661 synchronized (globalHierarchyLock)
662 {
663 synchronized (services)
664 {
665 BeanContextServiceProvider bcsp
666 = ((BCSSServiceProvider)
667 services.get(serviceClass)).getServiceProvider();
668 if (bcsp == null)
669 return null;
670 else
671 return bcsp.getCurrentServiceSelectors(this, serviceClass);
672 }
673 }
674 }
675
676 /**
677 * Retrieves the specified service. If a provider for the service
678 * is registered in this context, then the request is passed on to
679 * the provider and the service returned. Otherwise, the request
680 * is delegated to a parent {@link BeanContextServices}, if possible.
681 * If the service can not be found at all, then <code>null</code>
682 * is returned.
683 *
684 * @param child the child obtaining the reference.
685 * @param requestor the requestor of the service, which may be the
686 * child itself.
687 * @param serviceClass the service being requested.
688 * @param serviceSelector an additional service-dependent parameter
689 * (may be <code>null</code> if not appropriate).
690 * @param bcsrl a listener used to notify the requestor that the service
691 * has since been revoked.
692 * @return a reference to the service requested, or <code>null</code>.
693 * @throws TooManyListenersException according to Sun's documentation.
694 */
695 public Object getService (BeanContextChild child, Object requestor,
696 Class serviceClass, Object serviceSelector,
697 BeanContextServiceRevokedListener bcsrl)
698 throws TooManyListenersException
699 {
700 synchronized (globalHierarchyLock)
701 {
702 synchronized (services)
703 {
704 Object service;
705 BeanContextServiceProvider provider = ((BCSSServiceProvider)
706 services.get(serviceClass)).getServiceProvider();
707 if (provider != null)
708 {
709 service = provider.getService(this, requestor, serviceClass,
710 serviceSelector);
711 List childServices = (List) serviceUsers.get(child);
712 if (childServices == null)
713 {
714 childServices = new ArrayList();
715 serviceUsers.put(child, childServices);
716 }
717 childServices.add(serviceClass);
718 }
719 else
720 {
721 BeanContextServices peer = getBeanContextServicesPeer();
722 if (peer != null)
723 service = peer.getService(child, requestor, serviceClass,
724 serviceSelector, bcsrl);
725 else
726 service = null;
727 }
728 if (service != null)
729 {
730 ServiceRequest request = new ServiceRequest(requestor, bcsrl);
731 Set requests = (Set) serviceRequests.get(serviceClass);
732 if (requests == null)
733 {
734 requests = new HashSet();
735 serviceRequests.put(serviceClass, requests);
736 }
737 requests.add(request);
738 ServiceLease lease = new ServiceLease(requestor, service);
739 serviceLeases.put(lease, provider);
740 }
741 return service;
742 }
743 }
744 }
745
746 /**
747 * Returns true if the specified service is available.
748 *
749 * @param serviceClass the service to check for.
750 * @return true if the service is available.
751 */
752 public boolean hasService (Class serviceClass)
753 {
754 synchronized (globalHierarchyLock)
755 {
756 synchronized (services)
757 {
758 return services.containsKey(serviceClass);
759 }
760 }
761 }
762
763 public void initialize ()
764 {
765 super.initialize();
766
767 bcsListeners = new ArrayList();
768 services = new HashMap();
769 serviceUsers = new HashMap();
770 serviceRequests = new HashMap();
771 serviceLeases = new HashMap();
772 }
773
774 /**
775 * Subclasses may override this method to allocate resources
776 * from the nesting bean context.
777 */
778 protected void initializeBeanContextResources()
779 {
780 /* Purposefully left empty */
781 }
782
783 /**
784 * Relinquishes any resources obtained from the parent context.
785 * Specifically, those services obtained from the parent are revoked.
786 * Subclasses may override this method to deallocate resources
787 * from the nesting bean context.
788 */
789 protected void releaseBeanContextResources()
790 {
791 /* Purposefully left empty */
792 }
793
794 /**
795 * Releases the reference to a service held by a
796 * {@link BeanContextChild} (or an arbitrary object associated
797 * with it). It simply calls the appropriate method on the
798 * underlying provider.
799 *
800 * @param child the child who holds the reference.
801 * @param requestor the object that requested the reference.
802 * @param service the service being released.
803 */
804 public void releaseService (BeanContextChild child, Object requestor,
805 Object service)
806 {
807 synchronized (globalHierarchyLock)
808 {
809 synchronized (services)
810 {
811 ServiceLease lease = new ServiceLease(requestor, service);
812 BeanContextServiceProvider provider = (BeanContextServiceProvider)
813 serviceLeases.get(lease);
814 if (provider != null)
815 provider.releaseService(this, requestor, service);
816 else
817 {
818 BeanContextServices peer = getBeanContextServicesPeer();
819 if (peer != null)
820 peer.releaseService(child, requestor, service);
821 }
822 serviceLeases.remove(lease);
823 }
824 }
825 }
826
827 public void removeBeanContextServicesListener
828 (BeanContextServicesListener listener)
829 {
830 synchronized (bcsListeners)
831 {
832 bcsListeners.remove(listener);
833 }
834 }
835
836 /**
837 * Revokes the given service. A {@link BeanContextServiceRevokedEvent} is
838 * emitted to all registered {@link BeanContextServiceRevokedListener}s
839 * and {@link BeanContextServiceListener}s. If <code>revokeCurrentServicesNow</code>
840 * is true, termination of the service is immediate. Otherwise, prior
841 * acquisitions of the service by requestors remain valid.
842 *
843 * @param serviceClass the service to revoke.
844 * @param bcsp the provider of the revoked service.
845 * @param revokeCurrentServicesNow true if this is an exceptional circumstance
846 * where service should be immediately revoked.
847 */
848 public void revokeService (Class serviceClass, BeanContextServiceProvider bcsp,
849 boolean revokeCurrentServicesNow)
850 {
851 synchronized (globalHierarchyLock)
852 {
853 synchronized (services)
854 {
855 fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
856 services.remove(serviceClass);
857 if (bcsp instanceof Serializable)
858 --serializable;
859 }
860 }
861 }
862
863 public void serviceAvailable (BeanContextServiceAvailableEvent bcssae)
864 {
865 synchronized (services)
866 {
867 Class klass = bcssae.getServiceClass();
868 if (services.containsKey(klass))
869 return;
870 Iterator it = bcsChildren();
871 while (it.hasNext())
872 {
873 Object obj = it.next();
874 if (obj instanceof BeanContextServices)
875 ((BeanContextServices) obj).serviceAvailable(bcssae);
876 }
877 }
878 }
879
880 public void serviceRevoked (BeanContextServiceRevokedEvent bcssre)
881 {
882 synchronized (services)
883 {
884 Class klass = bcssre.getServiceClass();
885 if (services.containsKey(klass))
886 return;
887 Iterator it = bcsChildren();
888 while (it.hasNext())
889 {
890 Object obj = it.next();
891 if (obj instanceof BeanContextServices)
892 ((BeanContextServices) obj).serviceRevoked(bcssre);
893 }
894 }
895 }
896 }