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 }