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 }