/*******************************************************************************
 * Copyright (c) 2003, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.osgi.framework.internal.core;

import java.lang.reflect.Array;
import java.util.*;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.util.Headers;
import org.osgi.framework.*;

/**
 * A registered service.
 *
 * The framework returns a ServiceRegistration object when a
 * {@link BundleContextImpl#registerService(String, Object, Dictionary) BundleContext.registerService}
 * method is successful. This object is for the private use of
 * the registering bundle and should not be shared with other bundles.
 * <p>The ServiceRegistration object may be used to update the properties
 * for the service or to unregister the service.
 *
 * <p>If the ServiceRegistration is garbage collected the framework may remove
 * the service. This implies that if a
 * bundle wants to keep its service registered, it should keep the
 * ServiceRegistration object referenced.
 */
//TODO That's kind of big
public class ServiceRegistrationImpl implements ServiceRegistration {
	/** Reference to this registration. */
	protected ServiceReferenceImpl reference;

	/** Internal framework object. */
	protected Framework framework;

	/** context which registered this service. */
	protected BundleContextImpl context;

	/** bundle which registered this service. */
	protected AbstractBundle bundle;

	/** list of contexts using the service.
	 * Access to this should be protected by the registrationLock */
	protected ArrayList contextsUsing;

	/** service classes for this registration. */
	protected String[] clazzes;

	/** service object for this registration. */
	protected Object service;

	/** properties for this registration. */
	protected Properties properties;

	/** service id. */
	protected long serviceid;

	/** service ranking. */
	protected int serviceranking;

	/* internal object to use for synchronization */
	protected Object registrationLock = new Object();

	/** The registration state */
	protected int state = REGISTERED;
	public static final int REGISTERED = 0x00;
	public static final int UNREGISTERING = 0x01;
	public static final int UNREGISTERED = 0x02;

	/**
	 * Construct a ServiceRegistration and register the service
	 * in the framework's service registry.
	 *
	 */
	protected ServiceRegistrationImpl(BundleContextImpl context, String[] clazzes, Object service, Dictionary properties) {
		this.context = context;
		this.bundle = context.bundle;
		this.framework = context.framework;
		this.clazzes = clazzes; /* must be set before calling createProperties. */
		this.service = service;
		this.contextsUsing = null;
		this.reference = new ServiceReferenceImpl(this);

		synchronized (framework.serviceRegistry) {
			serviceid = framework.getNextServiceId(); /* must be set before calling createProperties. */
			this.properties = createProperties(properties); /* must be valid after unregister is called. */

			if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
				Debug.println("registerService[" + bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}

			framework.serviceRegistry.publishService(context, this);
		}

		/* must not hold the registrations lock when this event is published */
		framework.publishServiceEvent(ServiceEvent.REGISTERED, reference);
	}

	/**
	 * Unregister the service.
	 * Remove a service registration from the framework's service
	 * registry.
	 * All {@link ServiceReferenceImpl} objects for this registration
	 * can no longer be used to interact with the service.
	 *
	 * <p>The following steps are followed to unregister a service:
	 * <ol>
	 * <li>The service is removed from the framework's service
	 * registry so that it may no longer be used.
	 * {@link ServiceReferenceImpl}s for the service may no longer be used
	 * to get a service object for the service.
	 * <li>A {@link ServiceEvent} of type {@link ServiceEvent#UNREGISTERING}
	 * is synchronously sent so that bundles using this service
	 * may release their use of the service.
	 * <li>For each bundle whose use count for this service is greater
	 * than zero:
	 * <ol>
	 * <li>The bundle's use count for this service is set to zero.
	 * <li>If the service was registered with a {@link ServiceFactory},
	 * the {@link ServiceFactory#ungetService ServiceFactory.ungetService} method
	 * is called to release the service object for the bundle.
	 * </ol>
	 * </ol>
	 *
	 * @exception java.lang.IllegalStateException If
	 * this ServiceRegistration has already been unregistered.
	 * @see BundleContextImpl#ungetService
	 */
	public void unregister() {
		synchronized (registrationLock) {
			if (state != REGISTERED) /* in the process of unregisterING */
			{
				throw new IllegalStateException(Msg.SERVICE_ALREADY_UNREGISTERED_EXCEPTION);
			}

			/* remove this object from the service registry */
			if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
				Debug.println("unregisterService[" + bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}

			synchronized (framework.serviceRegistry) {
				framework.serviceRegistry.unpublishService(context, this);
			}

			state = UNREGISTERING; /* mark unregisterING */
		}

		/* must not hold the registrationLock when this event is published */
		framework.publishServiceEvent(ServiceEvent.UNREGISTERING, reference);

		/* we have published the ServiceEvent, now mark the service fully unregistered */
		service = null;
		state = UNREGISTERED;

		int size = 0;
		BundleContextImpl[] users = null;

		synchronized (registrationLock) {
			if (contextsUsing != null) {
				size = contextsUsing.size();

				if (size > 0) {
					if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
						Debug.println("unregisterService: releasing users"); //$NON-NLS-1$
					}
					users = (BundleContextImpl[]) contextsUsing.toArray(new BundleContextImpl[size]);
				}
			}
		}

		/* must not hold the registrationLock while releasing services */
		for (int i = 0; i < size; i++) {
			releaseService(users[i]);
		}

		contextsUsing = null;

		reference = null; /* mark registration dead */
		context = null;

		/* These fields must be valid after unregister is called:
		 *   properties
		 */
	}

	/**
	 * Returns a {@link ServiceReferenceImpl} object for this registration.
	 * The {@link ServiceReferenceImpl} object may be shared with other bundles.
	 *
	 * @exception java.lang.IllegalStateException If
	 * this ServiceRegistration has already been unregistered.
	 * @return A {@link ServiceReferenceImpl} object.
	 */
	public org.osgi.framework.ServiceReference getReference() {
		/* use reference instead of unregistered so that ServiceFactorys, called
		 * by releaseService after the registration is unregistered, can
		 * get the ServiceReference. Note this technically may voilate the spec
		 * but makes more sense.
		 */
		if (reference == null) {
			throw new IllegalStateException(Msg.SERVICE_ALREADY_UNREGISTERED_EXCEPTION);
		}

		return (reference);
	}

	/**
	 * Update the properties associated with this service.
	 *
	 * <p>The key "objectClass" cannot be modified by this method. It's
	 * value is set when the service is registered.
	 *
	 * <p>The following steps are followed to modify a service's properties:
	 * <ol>
	 * <li>The service's properties are replaced with the provided properties.
	 * <li>A {@link ServiceEvent} of type {@link ServiceEvent#MODIFIED}
	 * is synchronously sent.
	 * </ol>
	 *
	 * @param props The properties for this service.
	 *        Changes should not be made to this object after calling this method.
	 *        To update the service's properties this method should be called again.
	 * @exception java.lang.IllegalStateException If
	 * this ServiceRegistration has already been unregistered.
	 *
	 * @exception IllegalArgumentException If the <tt>properties</tt>
	 * parameter contains case variants of the same key name.
	 */
	public void setProperties(Dictionary props) {
		synchronized (registrationLock) {
			if (state != REGISTERED) /* in the process of unregistering */
			{
				throw new IllegalStateException(Msg.SERVICE_ALREADY_UNREGISTERED_EXCEPTION);
			}

			this.properties = createProperties(props);
		}

		/* must not hold the registrationLock when this event is published */
		framework.publishServiceEvent(ServiceEvent.MODIFIED, reference);
	}

	/**
	 * Construct a properties object from the dictionary for this
	 * ServiceRegistration.
	 *
	 * @param props The properties for this service.
	 * @return A Properties object for this ServiceRegistration.
	 */
	protected Properties createProperties(Dictionary props) {
		Properties properties = new Properties(props);

		properties.set(Constants.OBJECTCLASS, clazzes, true);
		properties.set(Constants.SERVICE_ID, new Long(serviceid), true);

		Object ranking = properties.getProperty(Constants.SERVICE_RANKING);

		serviceranking = (ranking instanceof Integer) ? ((Integer) ranking).intValue() : 0;

		return (properties);
	}

	/**
	 * Get the value of a service's property.
	 *
	 * <p>This method will continue to return property values after the
	 * service has been unregistered. This is so that references to
	 * unregistered service can be interrogated.
	 * (For example: ServiceReference objects stored in the log.)
	 *
	 * @param key Name of the property.
	 * @return Value of the property or <code>null</code> if there is
	 * no property by that name.
	 */
	protected Object getProperty(String key) {
		synchronized (registrationLock) {
			return (properties.getProperty(key));
		}
	}

	/**
	 * Get the list of key names for the service's properties.
	 *
	 * <p>This method will continue to return the keys after the
	 * service has been unregistered. This is so that references to
	 * unregistered service can be interrogated.
	 * (For example: ServiceReference objects stored in the log.)
	 *
	 * @return The list of property key names.
	 */
	protected String[] getPropertyKeys() {
		synchronized (registrationLock) {
			return (properties.getPropertyKeys());
		}
	}

	/**
	 * Return the bundle which registered the service.
	 *
	 * <p>This method will always return <code>null</code> when the
	 * service has been unregistered. This can be used to
	 * determine if the service has been unregistered.
	 *
	 * @return The bundle which registered the service.
	 */
	protected AbstractBundle getBundle() {
		if (reference == null) {
			return (null);
		}

		return (bundle);
	}

	/**
	 * Get a service object for the using BundleContext.
	 *
	 * @param user BundleContext using service.
	 * @return Service object
	 */
	protected Object getService(BundleContextImpl user) {
		synchronized (registrationLock) {
			if (state == UNREGISTERED) /* service unregistered */
			{
				return (null);
			}

			if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
				Debug.println("getService[" + user.bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}

			Hashtable servicesInUse = user.servicesInUse;

			ServiceUse use = (ServiceUse) servicesInUse.get(reference);

			if (use == null) {
				use = new ServiceUse(user, this);

				Object service = use.getService();

				if (service != null) {
					servicesInUse.put(reference, use);

					if (contextsUsing == null) {
						contextsUsing = new ArrayList(10);
					}

					contextsUsing.add(user);
				}

				return (service);
			} else {
				return (use.getService());
			}
		}
	}

	/**
	 * Unget a service for the using BundleContext.
	 *
	 * @param user BundleContext using service.
	 * @return <code>false</code> if the context bundle's use count for the service
	 *         is zero or if the service has been unregistered,
	 *         otherwise <code>true</code>.
	 */
	protected boolean ungetService(BundleContextImpl user) {
		synchronized (registrationLock) {
			if (state == UNREGISTERED) {
				return (false);
			}

			if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
				String bundle = (user.bundle == null) ? "" : user.bundle.toString(); //$NON-NLS-1$
				Debug.println("ungetService[" + bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}

			Hashtable servicesInUse = user.servicesInUse;

			if (servicesInUse != null) {
				ServiceUse use = (ServiceUse) servicesInUse.get(reference);

				if (use != null) {
					if (use.ungetService()) {
						/* use count is now zero */
						servicesInUse.remove(reference);

						contextsUsing.remove(user);
					}
					return (true);
				}
			}

			return (false);
		}
	}

	/**
	 * Release the service for the using BundleContext.
	 *
	 * @param user BundleContext using service.
	 */
	protected void releaseService(BundleContextImpl user) {
		synchronized (registrationLock) {
			if (reference == null) /* registration dead */
			{
				return;
			}

			if (Debug.DEBUG && Debug.DEBUG_SERVICES) {
				String bundle = (user.bundle == null) ? "" : user.bundle.toString(); //$NON-NLS-1$
				Debug.println("releaseService[" + bundle + "](" + this + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}

			Hashtable servicesInUse = user.servicesInUse;

			if (servicesInUse != null) {
				ServiceUse use = (ServiceUse) servicesInUse.remove(reference);

				if (use != null) {
					use.releaseService();
					// contextsUsing may have been nulled out by use.releaseService() if the registrant bundle
					// is listening for events and unregisters the service
					if (contextsUsing != null)
						contextsUsing.remove(user);
				}
			}
		}
	}

	/**
	 * Return the list of bundle which are using this service.
	 *
	 * @return Array of Bundles using this service.
	 */
	protected AbstractBundle[] getUsingBundles() {
		synchronized (registrationLock) {
			if (state == UNREGISTERED) /* service unregistered */
				return (null);

			if (contextsUsing == null)
				return (null);

			int size = contextsUsing.size();
			if (size == 0)
				return (null);

			/* Copy list of BundleContext into an array of Bundle. */
			AbstractBundle[] bundles = new AbstractBundle[size];
			for (int i = 0; i < size; i++)
				bundles[i] = ((BundleContextImpl) contextsUsing.get(i)).bundle;

			return (bundles);
		}
	}

	/**
	 * Return a String representation of this object.
	 *
	 * @return String representation of this object.
	 */
	public String toString() {
		String[] clazzes = this.clazzes;
		int size = clazzes.length;
		StringBuffer sb = new StringBuffer(50 * size);

		sb.append('{');

		for (int i = 0; i < size; i++) {
			if (i > 0) {
				sb.append(", "); //$NON-NLS-1$
			}
			sb.append(clazzes[i]);
		}

		sb.append("}="); //$NON-NLS-1$
		sb.append(properties);

		return (sb.toString());
	}

	/**
	 * Hashtable for service properties.
	 */
	static class Properties extends Headers {
		/**
		 * Create a properties object for the service.
		 *
		 * @param props The properties for this service.
		 */
		private Properties(int size, Dictionary props) {
			super(size);

			if (props != null) {
				synchronized (props) {
					Enumeration keysEnum = props.keys();

					while (keysEnum.hasMoreElements()) {
						Object key = keysEnum.nextElement();

						if (key instanceof String) {
							String header = (String) key;

							setProperty(header, props.get(header));
						}
					}
				}
			}
		}

		/**
		 * Create a properties object for the service.
		 *
		 * @param props The properties for this service.
		 */
		protected Properties(Dictionary props) {
			this((props == null) ? 2 : props.size() + 2, props);
		}

		/**
		 * Get a clone of the value of a service's property.
		 *
		 * @param key header name.
		 * @return Clone of the value of the property or <code>null</code> if there is
		 * no property by that name.
		 */
		protected Object getProperty(String key) {
			return (cloneValue(get(key)));
		}

		/**
		 * Get the list of key names for the service's properties.
		 *
		 * @return The list of property key names.
		 */
		protected synchronized String[] getPropertyKeys() {
			int size = size();

			String[] keynames = new String[size];

			Enumeration keysEnum = keys();

			for (int i = 0; i < size; i++) {
				keynames[i] = (String) keysEnum.nextElement();
			}

			return (keynames);
		}

		/**
		 * Put a clone of the property value into this property object.
		 *
		 * @param key Name of property.
		 * @param value Value of property.
		 * @return previous property value.
		 */
		protected synchronized Object setProperty(String key, Object value) {
			return (set(key, cloneValue(value)));
		}

		/**
		 * Attempt to clone the value if necessary and possible.
		 *
		 * For some strange reason, you can test to see of an Object is
		 * Cloneable but you can't call the clone method since it is
		 * protected on Object!
		 *
		 * @param value object to be cloned.
		 * @return cloned object or original object if we didn't clone it.
		 */
		protected static Object cloneValue(Object value) {
			if (value == null)
				return null;
			if (value instanceof String) /* shortcut String */
				return (value);
			if (value instanceof Number) /* shortcut Number */
				return value;
			if (value instanceof Character) /* shortcut Character */
				return value;
			if (value instanceof Boolean) /* shortcut Boolean */
				return value;

			Class clazz = value.getClass();
			if (clazz.isArray()) {
				// Do an array copy
				Class type = clazz.getComponentType();
				int len = Array.getLength(value);
				Object clonedArray = Array.newInstance(type, len);
				System.arraycopy(value, 0, clonedArray, 0, len);
				return clonedArray;
			}
			// must use reflection because Object clone method is protected!!
			try {
				return (clazz.getMethod("clone", null).invoke(value, null)); //$NON-NLS-1$
			} catch (Exception e) {
				/* clone is not a public method on value's class */
			} catch (Error e) {
				/* JCL does not support reflection; try some well known types */
				if (value instanceof Vector)
					return (((Vector) value).clone());
				if (value instanceof Hashtable)
					return (((Hashtable) value).clone());
			}
			return (value);
		}

		public synchronized String toString() {
			String keys[] = getPropertyKeys();

			int size = keys.length;

			StringBuffer sb = new StringBuffer(20 * size);

			sb.append('{');

			int n = 0;
			for (int i = 0; i < size; i++) {
				String key = keys[i];
				if (!key.equals(Constants.OBJECTCLASS)) {
					if (n > 0)
						sb.append(", "); //$NON-NLS-1$

					sb.append(key);
					sb.append('=');
					Object value = get(key);
					if (value.getClass().isArray()) {
						sb.append('[');
						int length = Array.getLength(value);
						for (int j = 0; j < length; j++) {
							if (j > 0)
								sb.append(',');
							sb.append(Array.get(value, j));
						}
						sb.append(']');
					} else {
						sb.append(value);
					}
					n++;
				}
			}

			sb.append('}');

			return (sb.toString());
		}
	}
}
