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