/* BeanContextServicesSupport.java --
   Copyright (C) 2003, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.beans.beancontext;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TooManyListenersException;

/**
 * This is a helper class for implementing a bean context which
 * supplies services.  It is intended to be used either by
 * subclassing or by calling methods of this implementation
 * from another.
 *
 * @author Michael Koch
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @since 1.2
 */
public class BeanContextServicesSupport
  extends BeanContextSupport
  implements BeanContextServices
{
  private static final long serialVersionUID = -8494482757288719206L;
  
  protected class BCSSChild
    extends BeanContextSupport.BCSChild
  {
    private static final long serialVersionUID = -3263851306889194873L;

    BCSSChild(Object targetChild, Object peer)
    {
      super(targetChild, peer);
    }
  }

  protected class BCSSProxyServiceProvider
    implements BeanContextServiceProvider,
    BeanContextServiceRevokedListener
  {
    private static final long serialVersionUID = 7078212910685744490L;

    private BeanContextServiceProvider provider;

    BCSSProxyServiceProvider(BeanContextServiceProvider p)
    {
      provider = p;
    }

    public Iterator getCurrentServiceSelectors (BeanContextServices bcs,
                                                Class serviceClass)
    {
      return provider.getCurrentServiceSelectors(bcs, serviceClass);
    }

    public Object getService (BeanContextServices bcs,
                              Object requestor,
                              Class serviceClass,
                              Object serviceSelector)
    {
      return provider.getService(bcs, requestor, serviceClass,
				 serviceSelector);
    }

    public void releaseService (BeanContextServices bcs,
                                Object requestor,
                                Object service)
    {
      provider.releaseService(bcs, requestor, service);
    }

    public void serviceRevoked (BeanContextServiceRevokedEvent bcsre)
    {
      if (provider instanceof BeanContextServiceRevokedListener)
	((BeanContextServiceRevokedListener) provider).serviceRevoked(bcsre);
    }
  }

  protected static class BCSSServiceProvider
    implements Serializable
  {
    private static final long serialVersionUID = 861278251667444782L;

    protected BeanContextServiceProvider serviceProvider;

    private Class serviceClass;

    private BCSSServiceProvider(Class serviceClass,
				BeanContextServiceProvider provider)
    {
      this.serviceClass = serviceClass;
      serviceProvider = provider;
    }

    protected BeanContextServiceProvider getServiceProvider()
    {
      return serviceProvider;
    }

    private Class getServiceClass()
    {
      return serviceClass;
    }

  }

  /**
   * Represents a request for a service.  This is
   * a common superclass used by the classes which maintain
   * the listener-requestor and service-requestor relationships.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   */
  private static abstract class Request
  {
    private Object requestor;

    public Request(Object requestor)
    {
      this.requestor = requestor;
    }

    public boolean equals(Object obj)
    {
      if (obj instanceof Request)
	{
	  Request req = (Request) obj;
	  return req.getRequestor().equals(requestor);
	}
      return false;
    }

    public Object getRequestor()
    {
      return requestor;
    }

  }

  /**
   * Represents a relationship between a service requestor
   * and a revocation listener.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   */
  private static class ServiceRequest
    extends Request
  {

    private BeanContextServiceRevokedListener listener;

    public ServiceRequest(Object requestor,
			  BeanContextServiceRevokedListener listener)
    {
      super(requestor);
      this.listener = listener;
    }

    public boolean equals(Object obj)
    {
      if (obj instanceof ServiceRequest)
	{
	  ServiceRequest sr = (ServiceRequest) obj;
	  return (super.equals(obj) &&
		  sr.getListener().equals(listener));
	}
      return false;
    }

    public BeanContextServiceRevokedListener getListener()
    {
      return listener;
    }
  }

  /**
   * Represents a relationship between a service requestor
   * and a service instance.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   */
  private static class ServiceLease
    extends Request
  {

    private Object service;

    public ServiceLease(Object requestor, Object service)
    {
      super(requestor);
      this.service = service;
    }

    public boolean equals(Object obj)
    {
      if (obj instanceof ServiceLease)
	{
	  ServiceLease sl = (ServiceLease) obj;
	  return (super.equals(obj) &&
		  sl.getService().equals(service));
	}
      return false;
    }

    public Object getService()
    {
      return service;
    }
  }

  /**
   * A collection of listeners who receive availability
   * and revocation notifications.
   */
  protected transient ArrayList bcsListeners;
    
  protected transient BCSSProxyServiceProvider proxy;

  /**
   * The number of serializable service providers.
   */
  protected transient int serializable;

  /**
   * A map of registered services, linking the service
   * class to its associated {@link BCSSServiceProvider}.
   */
  protected transient HashMap services;

  /**
   * A map of children to a list of services they
   * have obtained.
   */
  private transient HashMap serviceUsers;

  /**
   * A map of services to {@link ServiceRequest}s.
   */
  private transient HashMap serviceRequests;

  /**
   * A map of {@link ServiceLease}s to providers.
   */
  private transient HashMap serviceLeases;

  /**
   * Construct a {@link BeanContextServicesSupport} instance.
   */
  public BeanContextServicesSupport ()
  {
    super();
  }

  /**
   * Construct a {@link BeanContextServicesSupport} instance.
   * 
   * @param peer the bean context services peer (<code>null</code> permitted).
   */
  public BeanContextServicesSupport (BeanContextServices peer)
  {
    super(peer);
  }

  /**
   * Construct a {@link BeanContextServicesSupport} instance.
   * 
   * @param peer the bean context peer (<code>null</code> permitted).
   * @param locale the locale (<code>null</code> permitted, equivalent to 
   *     the default locale).
   */
  public BeanContextServicesSupport(BeanContextServices peer, Locale locale)
  {
    super(peer, locale);
  }

  /**
   * Construct a {@link BeanContextServicesSupport} instance.
   * 
   * @param peer  the bean context peer (<code>null</code> permitted).
   * @param locale  the locale (<code>null</code> permitted, equivalent to 
   *     the default locale).
   * @param dtime  a flag indicating whether or not the bean context is in
   *     design time mode.
   */
  public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
                                    boolean dtime)
  {
    super(peer, locale, dtime);
  }

  /**
   * Construct a {@link BeanContextServicesSupport} instance.
   * 
   * @param peer  the bean context peer (<code>null</code> permitted).
   * @param locale  the locale (<code>null</code> permitted, equivalent to 
   *     the default locale).
   * @param dtime  a flag indicating whether or not the bean context is in
   *     design time mode.
   * @param visible  initial value of the <code>okToUseGui</code> flag.
   */
  public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
                                    boolean dtime, boolean visible)
  {
    super(peer, locale, dtime, visible);
  }
  
  /**
   * Adds a new listener for service availability and
   * revocation events.
   *
   * @param listener the listener to add.
   */
  public void addBeanContextServicesListener
    (BeanContextServicesListener listener)
  {
    synchronized (bcsListeners)
      {
        if (! bcsListeners.contains(listener))
          bcsListeners.add(listener);
      }
  }

  /**
   * Registers a new service from the specified service provider.
   * The service is internally associated with the service provider
   * and a <code>BeanContextServiceAvailableEvent</code> is fired.  If
   * the service is already registered, then this method instead
   * returns <code>false</code>.  This is equivalent to calling
   * <code>addService(serviceClass, bcsp, true)</code>.
   *
   * @param serviceClass the class of the service to be registered.
   * @param bcsp the provider of the given service.
   * @return true if the service was registered successfully.
   * @see #addService(Class, BeanContextServiceProvider, boolean)
   */
  public boolean addService (Class serviceClass,
                             BeanContextServiceProvider bcsp)
  {
    return addService(serviceClass, bcsp, true);
  }

  /**
   * Registers a new service from the specified service provider.
   * The service is internally associated with the service provider
   * and (if <code>fireEvent</code> is true) a
   * <code>BeanContextServiceAvailableEvent</code> is fired.  If
   * the service is already registered, then this method instead
   * returns <code>false</code>.
   *
   * @param serviceClass the class of the service to be registered.
   * @param bcsp the provider of the given service.
   * @param fireEvent true if a service availability event should
   *                  be fired.
   * @return true if the service was registered successfully.
   */
  protected boolean addService (Class serviceClass,
                                BeanContextServiceProvider bcsp,
                                boolean fireEvent)
  {
    synchronized (globalHierarchyLock)
      {
	synchronized (services)
	  {
	    if (services.containsKey(serviceClass))
	      return false;
	    services.put(serviceClass,
			 createBCSSServiceProvider(serviceClass, bcsp));
	    if (bcsp instanceof Serializable)
	      ++serializable;
	    if (fireEvent)
	      fireServiceAdded(serviceClass);
	    return true;
	  }
      }
  }
  
  /**
   * Deserializes any service providers which are serializable.  This
   * method is called by the <code>readObject</code> method of
   * {@link BeanContextSupport} prior to deserialization of the children.
   * Subclasses may envelope its behaviour in order to read further
   * serialized data to the stream.
   *
   * @param ois the stream from which data is being deserialized.
   * @throws IOException if an I/O error occurs.
   * @throws ClassNotFoundException if the class of a deserialized object
   *                                can not be found.
   */
  protected void bcsPreDeserializationHook (ObjectInputStream ois)
    throws ClassNotFoundException, IOException
  {
    serializable = ois.readInt();
    for (int a = 0; a < serializable; ++a)
      {
	BCSSServiceProvider bcsssp = (BCSSServiceProvider) ois.readObject();
	addService(bcsssp.getServiceClass(), bcsssp.getServiceProvider());
      }
  }

  /**
   * Serializes any service providers which are serializable.  This
   * method is called by the <code>writeObject</code> method of
   * {@link BeanContextSupport} prior to serialization of the children.
   * Subclasses may envelope its behaviour in order to add further
   * serialized data to the stream.
   *
   * @param oos the stream to which data is being serialized.
   * @throws IOException if an I/O error occurs.
   */
  protected void bcsPreSerializationHook (ObjectOutputStream oos) 
    throws IOException
  {
    oos.writeInt(serializable);
    synchronized (services)
      {
	Iterator i = services.values().iterator();
	while (i.hasNext())
	  {
	    BCSSServiceProvider bcsssp = (BCSSServiceProvider) i.next();
	    if (bcsssp.getServiceProvider() instanceof Serializable)
	      oos.writeObject(bcsssp);
	  }
      }
  }

  /**
   * Revokes any services used by a child that has just been removed.
   * The superclass ({@link BeanContextSupport}) calls this method
   * when a child has just been successfully removed.  Subclasses can
   * extend this method in order to perform additional operations
   * on child removal.
   *
   * @param child the child being removed.
   * @param bcsc the support object for the child.
   */ 
  protected void childJustRemovedHook (Object child,
                                       BeanContextSupport.BCSChild bcsc)
  {
    if (child instanceof BeanContextChild)
      {
	BeanContextChild bcchild = (BeanContextChild) child;
	Iterator childServices = ((List) serviceUsers.get(bcchild)).iterator();
	while (childServices.hasNext())
	  releaseService(bcchild, this, childServices.next());
	serviceUsers.remove(bcchild);
      }
  }

  /**
   * Overrides the {@link BeanContextSupport#createBCSChild} method
   * so as to use a {@link BCSSChild} instead.
   *
   * @param targetChild the child to create the child for.
   * @param peer the peer which relates to the child if a proxy is used.
   * @return a new instance of {@link BCSSChild}.
   */
  protected BeanContextSupport.BCSChild createBCSChild (Object targetChild,
                                                        Object peer)
  {
    return new BCSSChild(targetChild, peer);
  }

  /**
   * Provides a hook so that subclasses can replace the
   * {@link BCSSServiceProvider} class, used to store registered
   * service providers, with a subclass without replacing the
   * {@link #addService(Class, BeanContextServiceProvider)} method.
   *
   * @param sc the class of service being registered.
   * @param bcsp the provider of the service.
   * @return a instance of {@link BCSSServiceProvider} wrapping the provider.
   */
  protected BeanContextServicesSupport.BCSSServiceProvider
  createBCSSServiceProvider (Class sc, BeanContextServiceProvider bcsp)
  {
    return new BCSSServiceProvider(sc, bcsp);
  }

  /**
   * Sends a <code>BeanContextServiceAvailableEvent</code> to all
   * registered listeners.
   *
   * @param bcssae the event to send.
   */
  protected final void fireServiceAdded (BeanContextServiceAvailableEvent bcssae)
  {
    synchronized (bcsListeners)
      {
        int size = bcsListeners.size();
        for (int i = 0; i < size; ++i)
          {
            BeanContextServicesListener bcsl
              = (BeanContextServicesListener) bcsListeners.get(i);
            bcsl.serviceAvailable(bcssae);
          }
      }
  }

  /**
   * Sends a <code>BeanContextServiceAvailableEvent</code> to all
   * registered listeners.
   *
   * @param serviceClass the service that is now available.
   * @see #fireServiceAdded(BeanContextServiceAvailableEvent)
   */
  protected final void fireServiceAdded (Class serviceClass)
  {
    fireServiceAdded(new BeanContextServiceAvailableEvent(this,
                                                          serviceClass));
  }

  /**
   * Sends a <code>BeanContextServiceRevokedEvent</code> to all
   * registered listeners.
   *
   * @param event the event to send.
   */
  protected final void fireServiceRevoked(BeanContextServiceRevokedEvent event)
  {
    synchronized (bcsListeners)
      {
        int size = bcsListeners.size();
        for (int i = 0; i < size; ++i)
          {
            BeanContextServicesListener bcsl
              = (BeanContextServicesListener) bcsListeners.get(i);
            bcsl.serviceRevoked(event);
          }
	List requests = (List) serviceRequests.get(event.getServiceClass());
	if (requests != null)
	  {
	    Iterator i = requests.iterator();
	    while (i.hasNext())
	      {
		ServiceRequest r = (ServiceRequest) i.next();
		r.getListener().serviceRevoked(event);
	      }
	  }
      }
  }

  /**
   * Sends a <code>BeanContextServiceRevokedEvent</code> to all
   * registered listeners.
   *
   * @param serviceClass the service that has been revoked.
   * @see #fireServiceRevoked(BeanContextServiceRevokedEvent)
   */
  protected final void fireServiceRevoked (Class serviceClass,
                                           boolean revokeNow)
  {
    fireServiceRevoked(new BeanContextServiceRevokedEvent(this, serviceClass,
                                                          revokeNow));
  }

  /**
   * Returns the services peer given at construction time,
   * or <code>null</code> if no peer was given.
   *
   * @return the {@link BeanContextServices} peer.
   */
  public BeanContextServices getBeanContextServicesPeer ()
  {
    return (BeanContextServices) beanContextChildPeer;
  }

  /**
   * Returns <code>child</code> as an instance of 
   * {@link BeanContextServicesListener}, or <code>null</code> if 
   * <code>child</code> does not implement that interface.
   * 
   * @param child  the child (<code>null</code> permitted).
   * 
   * @return The child cast to {@link BeanContextServicesListener}.
   */
  protected static final BeanContextServicesListener
      getChildBeanContextServicesListener(Object child)
  {
    if (child instanceof BeanContextServicesListener) 
      return (BeanContextServicesListener) child;
    else 
      return null;
  }

  /**
   * Returns an iterator over the currently available
   * services.
   *
   * @return an iterator over the currently available services.
   */
  public Iterator getCurrentServiceClasses ()
  {
    synchronized (globalHierarchyLock)
      {
	synchronized (services)
	  {
	    return services.keySet().iterator();
	  }
      }
  }

  /**
   * Returns an iterator over the service selectors of the service
   * provider for the given service.  The iterator is actually
   * obtained by calling the
   * {@link BeanContextServiceProvider#getCurrentServiceSelectors}
   * of the provider itself.  If the specified service is not available,
   * <code>null</code> is returned.
   *
   * @param serviceClass the service whose provider's selectors should
   *                     be iterated over.
   * @return an {@link Iterator} over the service selectors of the
   *         provider of the given service.
   */
  public Iterator getCurrentServiceSelectors (Class serviceClass)
  {
    synchronized (globalHierarchyLock)
      {
	synchronized (services)
	  {
	    BeanContextServiceProvider bcsp
	      = ((BCSSServiceProvider)
		 services.get(serviceClass)).getServiceProvider();
	    if (bcsp == null)
	      return null;
	    else
	      return bcsp.getCurrentServiceSelectors(this, serviceClass);
	  }
      }
  }

  /**
   * Retrieves the specified service.  If a provider for the service
   * is registered in this context, then the request is passed on to
   * the provider and the service returned.  Otherwise, the request
   * is delegated to a parent {@link BeanContextServices}, if possible.
   * If the service can not be found at all, then <code>null</code>
   * is returned.
   *
   * @param child the child obtaining the reference.
   * @param requestor the requestor of the service, which may be the
   *                  child itself.
   * @param serviceClass the service being requested.
   * @param serviceSelector an additional service-dependent parameter
   *                        (may be <code>null</code> if not appropriate).
   * @param bcsrl a listener used to notify the requestor that the service
   *              has since been revoked.
   * @return a reference to the service requested, or <code>null</code>.
   * @throws TooManyListenersException according to Sun's documentation.
   */
  public Object getService (BeanContextChild child, Object requestor,
                            Class serviceClass, Object serviceSelector,
                            BeanContextServiceRevokedListener bcsrl)
    throws TooManyListenersException
  {
    synchronized (globalHierarchyLock)
      {
	synchronized (services)
	  {
	    Object service;
	    BeanContextServiceProvider provider = ((BCSSServiceProvider)
	      services.get(serviceClass)).getServiceProvider();
	    if (provider != null)
	      {
		service = provider.getService(this, requestor, serviceClass,
					      serviceSelector);
		List childServices = (List) serviceUsers.get(child);
		if (childServices == null)
		  {
		    childServices = new ArrayList();
		    serviceUsers.put(child, childServices);
		  }
		childServices.add(serviceClass);
	      }
	    else 
	      {
		BeanContextServices peer = getBeanContextServicesPeer();
		if (peer != null)
		  service = peer.getService(child, requestor, serviceClass,
					    serviceSelector, bcsrl);
		else
		  service = null;
	      }    								    
	    if (service != null)
	      {
		ServiceRequest request = new ServiceRequest(requestor, bcsrl);
		Set requests = (Set) serviceRequests.get(serviceClass);
		if (requests == null)
		  {
		    requests = new HashSet();
		    serviceRequests.put(serviceClass, requests);
		  }
		requests.add(request);
		ServiceLease lease = new ServiceLease(requestor, service);
		serviceLeases.put(lease, provider);
	      }
	    return service;
	  }
      }
  }

  /**
   * Returns true if the specified service is available.
   *
   * @param serviceClass the service to check for.
   * @return true if the service is available.
   */
  public boolean hasService (Class serviceClass)
  {
    synchronized (globalHierarchyLock)
      {
	synchronized (services)
	  {
	    return services.containsKey(serviceClass);
	  }
      }
  }

  public void initialize ()
  {
    super.initialize();

    bcsListeners = new ArrayList();
    services = new HashMap();
    serviceUsers = new HashMap();
    serviceRequests = new HashMap();
    serviceLeases = new HashMap();
  }

  /**
   * Subclasses may override this method to allocate resources
   * from the nesting bean context.
   */
  protected  void initializeBeanContextResources()
  {
    /* Purposefully left empty */
  }

  /**
   * Relinquishes any resources obtained from the parent context.
   * Specifically, those services obtained from the parent are revoked.
   * Subclasses may override this method to deallocate resources
   * from the nesting bean context.  
   */
  protected void releaseBeanContextResources()
  {
    /* Purposefully left empty */
  }

  /**
   * Releases the reference to a service held by a
   * {@link BeanContextChild} (or an arbitrary object associated
   * with it).  It simply calls the appropriate method on the
   * underlying provider.
   *
   * @param child the child who holds the reference.
   * @param requestor the object that requested the reference.
   * @param service the service being released.
   */
  public void releaseService (BeanContextChild child, Object requestor,
                              Object service)
  {
    synchronized (globalHierarchyLock)
      {
	synchronized (services)
	  {
	    ServiceLease lease = new ServiceLease(requestor, service);
	    BeanContextServiceProvider provider = (BeanContextServiceProvider)
	      serviceLeases.get(lease);
	    if (provider != null)
	      provider.releaseService(this, requestor, service);
	    else
	      {
		BeanContextServices peer = getBeanContextServicesPeer();
		if (peer != null)
		  peer.releaseService(child, requestor, service);
	      }
	    serviceLeases.remove(lease);
	  }
      }
  }

  public void removeBeanContextServicesListener
    (BeanContextServicesListener listener)
  {
    synchronized (bcsListeners)
      {
	bcsListeners.remove(listener);
      }
  }

  /**
   * Revokes the given service.  A {@link BeanContextServiceRevokedEvent} is
   * emitted to all registered {@link BeanContextServiceRevokedListener}s
   * and {@link BeanContextServiceListener}s.  If <code>revokeCurrentServicesNow</code>
   * is true, termination of the service is immediate.  Otherwise, prior
   * acquisitions of the service by requestors remain valid.
   *
   * @param serviceClass the service to revoke.
   * @param bcsp the provider of the revoked service.
   * @param revokeCurrentServicesNow true if this is an exceptional circumstance
   *                                 where service should be immediately revoked.
   */
  public void revokeService (Class serviceClass, BeanContextServiceProvider bcsp,
                             boolean revokeCurrentServicesNow)
  {
    synchronized (globalHierarchyLock)
      {
	synchronized (services)
	  {
	    fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
	    services.remove(serviceClass);
	    if (bcsp instanceof Serializable)
	      --serializable;
	  }
      }
  }

  public void serviceAvailable (BeanContextServiceAvailableEvent bcssae)
  {
    synchronized (services)
      {
        Class klass = bcssae.getServiceClass();
        if (services.containsKey(klass))
          return;
        Iterator it = bcsChildren();
        while (it.hasNext())
          {
            Object obj = it.next();
            if (obj instanceof BeanContextServices)
              ((BeanContextServices) obj).serviceAvailable(bcssae);
          }
      }
  }

  public void serviceRevoked (BeanContextServiceRevokedEvent bcssre)
  {
    synchronized (services)
      {
        Class klass = bcssre.getServiceClass();
        if (services.containsKey(klass))
          return;
        Iterator it = bcsChildren();
        while (it.hasNext())
          {
            Object obj = it.next();
            if (obj instanceof BeanContextServices)
              ((BeanContextServices) obj).serviceRevoked(bcssre);
          }
      }
  }
}
