1 /* BeanContextServicesSupport.java --
2    Copyright (C) 2003, 2005  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package java.beans.beancontext;
40 
41 import java.io.IOException;
42 import java.io.ObjectInputStream;
43 import java.io.ObjectOutputStream;
44 import java.io.Serializable;
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.HashSet;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Locale;
51 import java.util.Set;
52 import java.util.TooManyListenersException;
53 
54 /**
55  * This is a helper class for implementing a bean context which
56  * supplies services.  It is intended to be used either by
57  * subclassing or by calling methods of this implementation
58  * from another.
59  *
60  * @author Michael Koch
61  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
62  * @since 1.2
63  */
64 public class BeanContextServicesSupport
65   extends BeanContextSupport
66   implements BeanContextServices
67 {
68   private static final long serialVersionUID = -8494482757288719206L;
69 
70   protected class BCSSChild
71     extends BeanContextSupport.BCSChild
72   {
73     private static final long serialVersionUID = -3263851306889194873L;
74 
BCSSChild(Object targetChild, Object peer)75     BCSSChild(Object targetChild, Object peer)
76     {
77       super(targetChild, peer);
78     }
79   }
80 
81   protected class BCSSProxyServiceProvider
82     implements BeanContextServiceProvider,
83     BeanContextServiceRevokedListener
84   {
85     private static final long serialVersionUID = 7078212910685744490L;
86 
87     private BeanContextServiceProvider provider;
88 
BCSSProxyServiceProvider(BeanContextServiceProvider p)89     BCSSProxyServiceProvider(BeanContextServiceProvider p)
90     {
91       provider = p;
92     }
93 
getCurrentServiceSelectors(BeanContextServices bcs, Class serviceClass)94     public Iterator getCurrentServiceSelectors (BeanContextServices bcs,
95                                                 Class serviceClass)
96     {
97       return provider.getCurrentServiceSelectors(bcs, serviceClass);
98     }
99 
getService(BeanContextServices bcs, Object requestor, Class serviceClass, Object serviceSelector)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 
releaseService(BeanContextServices bcs, Object requestor, Object service)109     public void releaseService (BeanContextServices bcs,
110                                 Object requestor,
111                                 Object service)
112     {
113       provider.releaseService(bcs, requestor, service);
114     }
115 
serviceRevoked(BeanContextServiceRevokedEvent bcsre)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 
BCSSServiceProvider(Class serviceClass, BeanContextServiceProvider provider)132     private BCSSServiceProvider(Class serviceClass,
133                                 BeanContextServiceProvider provider)
134     {
135       this.serviceClass = serviceClass;
136       serviceProvider = provider;
137     }
138 
getServiceProvider()139     protected BeanContextServiceProvider getServiceProvider()
140     {
141       return serviceProvider;
142     }
143 
getServiceClass()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 
Request(Object requestor)162     public Request(Object requestor)
163     {
164       this.requestor = requestor;
165     }
166 
equals(Object obj)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 
getRequestor()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 
ServiceRequest(Object requestor, BeanContextServiceRevokedListener listener)196     public ServiceRequest(Object requestor,
197                           BeanContextServiceRevokedListener listener)
198     {
199       super(requestor);
200       this.listener = listener;
201     }
202 
equals(Object obj)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 
getListener()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 
ServiceLease(Object requestor, Object service)232     public ServiceLease(Object requestor, Object service)
233     {
234       super(requestor);
235       this.service = service;
236     }
237 
equals(Object obj)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 
getService()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    */
BeanContextServicesSupport()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    */
BeanContextServicesSupport(BeanContextServices peer)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    */
BeanContextServicesSupport(BeanContextServices peer, Locale locale)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    */
BeanContextServicesSupport(BeanContextServices peer, Locale locale, boolean dtime)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    */
BeanContextServicesSupport(BeanContextServices peer, Locale locale, boolean dtime, boolean visible)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    */
addBeanContextServicesListener(BeanContextServicesListener listener)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    */
addService(Class serviceClass, BeanContextServiceProvider bcsp)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    */
addService(Class serviceClass, BeanContextServiceProvider bcsp, boolean fireEvent)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    */
bcsPreDeserializationHook(ObjectInputStream ois)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    */
bcsPreSerializationHook(ObjectOutputStream oos)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    */
childJustRemovedHook(Object child, BeanContextSupport.BCSChild bcsc)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    */
createBCSChild(Object targetChild, Object peer)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
createBCSSServiceProvider(Class sc, BeanContextServiceProvider bcsp)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    */
fireServiceAdded(BeanContextServiceAvailableEvent bcssae)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    */
fireServiceAdded(Class serviceClass)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    */
fireServiceRevoked(BeanContextServiceRevokedEvent event)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    */
fireServiceRevoked(Class serviceClass, boolean revokeNow)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    */
getBeanContextServicesPeer()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
getChildBeanContextServicesListener(Object child)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    */
getCurrentServiceClasses()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    */
getCurrentServiceSelectors(Class serviceClass)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    */
getService(BeanContextChild child, Object requestor, Class serviceClass, Object serviceSelector, BeanContextServiceRevokedListener bcsrl)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    */
hasService(Class serviceClass)752   public boolean hasService (Class serviceClass)
753   {
754     synchronized (globalHierarchyLock)
755       {
756         synchronized (services)
757           {
758             return services.containsKey(serviceClass);
759           }
760       }
761   }
762 
initialize()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    */
initializeBeanContextResources()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    */
releaseBeanContextResources()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    */
releaseService(BeanContextChild child, Object requestor, Object service)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 
removeBeanContextServicesListener(BeanContextServicesListener listener)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    */
revokeService(Class serviceClass, BeanContextServiceProvider bcsp, boolean revokeCurrentServicesNow)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 
serviceAvailable(BeanContextServiceAvailableEvent bcssae)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 
serviceRevoked(BeanContextServiceRevokedEvent bcssre)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 }
897