/*******************************************************************************
 * Copyright (c) 1999, 2005 IBM Corporation.
 * 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.equinox.log;

import java.util.*;
import org.eclipse.osgi.framework.eventmgr.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.log.LogService;

/**
 * An array of LogEntries which wraps when full.
 */
public class Activator implements BundleActivator, EventDispatcher, BundleListener, FrameworkListener, ServiceListener, ManagedService {
	protected BundleContext context;

	/** List of LogReaderServices for bundle's LogEntry listeners. */
	protected EventListeners logEvent;
	/** EventManager for event delivery. */
	protected EventManager eventManager;

	protected ServiceRegistration logservice;
	protected ServiceRegistration logreaderservice;
	protected ServiceRegistration logmanagedservice;

	/** default log size value */
	protected static final int DEFAULT_LOG_SIZE = 100;

	/** default log threshold value */
	protected static final int DEFAULT_LOG_THRESHOLD = LogService.LOG_DEBUG;

	/** current logsize value */
	protected int logSize = DEFAULT_LOG_SIZE;
	/** current logthreshold value */
	protected int logThreshold = DEFAULT_LOG_THRESHOLD;

	protected LogEntry[] logEntries;
	protected int head;
	protected int tail;

	/** The timestamp of the last log entry (to avoid duplicates). */
	protected long lastTimestamp = 0;

	/** key into properties for logsize value */
	protected static final String keyLogSize = "log.size"; //$NON-NLS-1$
	/** key into properties for log threshold value */
	protected static final String keyLogThreshold = "log.threshold"; //$NON-NLS-1$
	/** Pid that log service uses when it registers a CM Managed Service */
	protected static final String LOGSERVICEPID = "org.eclipse.equinox.log.Log"; //$NON-NLS-1$

	/**
	 * BundleActivator.start method. We can now initialize the bundle
	 * and register the services.
	 *
	 */
	public void start(BundleContext bundleContext) {
		this.context = bundleContext;

		eventManager = new EventManager("Log Event Dispatcher"); //$NON-NLS-1$
		logEvent = new EventListeners();

		logEntries = new LogEntry[logSize];
		head = 0;
		tail = 0;
		String initmessage = NLS.bind(LogMsg.Log_created_Log_Size, String.valueOf(logSize), String.valueOf(logThreshold));
		logEntries[0] = new LogEntry(LogService.LOG_INFO, initmessage, bundleContext.getBundle(), null, null);

		bundleContext.addBundleListener(this);
		bundleContext.addServiceListener(this);
		bundleContext.addFrameworkListener(this);

		registerLogService();
		registerLogReaderService();

		registerManagedService();
	}

	/**
	 * BundleActivator.stop method. We must now clean up and terminate
	 * execution.
	 *
	 */
	public synchronized void stop(BundleContext bundleContext) {
		if (logmanagedservice != null) {
			logmanagedservice.unregister();
			logmanagedservice = null;
		}

		/* remove my listeners before unregistering myself */
		this.context.removeBundleListener(this);
		this.context.removeServiceListener(this);
		this.context.removeFrameworkListener(this);

		if (logservice != null) {
			logservice.unregister();
			logservice = null;
		}
		if (logreaderservice != null) {
			logreaderservice.unregister();
			logreaderservice = null;
		}

		/* destroy my event manager */
		if (logEvent != null) {
			logEvent.removeAllListeners();
			logEvent = null;
		}

		if (eventManager != null) {
			eventManager.close();
			eventManager = null;
		}

		logEntries = null;

		this.context = null;
	}

	/**
	 *  Log a bundle message.  This is used internally by all of the public
	 *  log() methods as the common point through which all logging must
	 *  go through.
	 *  @param level The severity of the message.  (Should be one of the four
	 *               predefined severities.)
	 *  @param message Human readable string describing the condition.
	 *  @param context The BundleContext creating the log entry
	 *  @param sd The ServiceDescription of the service that this message
	 *  is associated with.
	 *  @param exception The exception that reflects the condition.
	 */
	protected void log(int level, String message, Bundle bundle, ServiceReference reference, Throwable exception)

	{
		LogEntry logentry = new LogEntry(level, message, bundle, reference, exception);

		synchronized (this) {
			if (context == null) {
				return;
			}

			// Make the timestamp unique, log listener's might use it as a key
			if (logentry.time <= lastTimestamp) {
				logentry.time = ++lastTimestamp;
			} else {
				lastTimestamp = logentry.time;
			}

			if (level <= logThreshold) { /* if level is within logging threshold */
				addLogEntry(logentry);
			}
		}

		/* queue to hold set of listeners */
		ListenerQueue listeners = new ListenerQueue(eventManager);

		/* queue to hold set of BundleContexts w/ listeners */
		ListenerQueue contexts = new ListenerQueue(eventManager);

		/* add set of BundleContexts w/ listeners to queue */
		contexts.queueListeners(logEvent, this);

		/* synchronously dispatch to populate listeners queue */
		contexts.dispatchEventSynchronous(0, listeners);

		/* dispatch event to set of listeners */
		listeners.dispatchEventAsynchronous(0, logentry);
	}

	public void dispatchEvent(Object l, Object lo, int action, Object object) {
		LogReaderService logreader = (LogReaderService) l;

		EventListeners listeners = logreader.logEvent;

		if (listeners != null) {
			ListenerQueue queue = (ListenerQueue) object;

			queue.queueListeners(listeners, logreader);
		}
	}

	/**
	 * This method must be called while synchronized.
	 *
	 */
	protected void addLogEntry(LogEntry logentry) {
		tail = (tail + 1) % logSize;
		logEntries[tail] = logentry;
		if (head == tail) {
			head = (head + 1) % logSize;
		}
	}

	protected synchronized Enumeration logEntries() {
		final int tempHead = this.head;
		final int tempTail = this.tail;
		final int templogSize = this.logSize;
		final LogEntry[] tempLogEntries = this.logEntries;

		return (new Enumeration() {
			private int item;
			private LogEntry[] enumentries;

			{
				// The array is created in the log reader's memory space
				if (tempHead <= tempTail) {
					item = tempTail - tempHead + 1;
					enumentries = new LogEntry[item];
					System.arraycopy(tempLogEntries, tempHead, enumentries, 0, item);
				} else { // log is full
					int firstcopy = templogSize - tempHead;
					item = firstcopy + tempTail + 1;
					enumentries = new LogEntry[item];
					System.arraycopy(tempLogEntries, tempHead, enumentries, 0, firstcopy);
					System.arraycopy(tempLogEntries, 0, enumentries, firstcopy, item - firstcopy);
				}
			}

			public boolean hasMoreElements() {
				if (item > 0) {
					return (true);
				}
				enumentries = null; /* release the storage */
				return (false);
			}

			/** Returns an Object of type LogEntry */
			public Object nextElement() {
				if (item > 0) {
					item--;
					LogEntry entry = (enumentries[item]).copy();
					enumentries[item] = null; /* release the storage as we go */
					return (entry);
				}
				enumentries = null; /* release the storage */
				throw new NoSuchElementException();
			}
		});
	}

	/**
	 * BundleListener.bundleChanged method.
	 *
	 */
	public void bundleChanged(BundleEvent event) {
		log(LogService.LOG_INFO, getBundleEventTypeName(event.getType()), event.getBundle(), null, null);
	}

	/**
	 * ServiceListener.serviceChanged method.
	 *
	 */
	public void serviceChanged(ServiceEvent event) {
		ServiceReference reference = event.getServiceReference();

		int eventType = event.getType();

		int logType = (eventType == ServiceEvent.MODIFIED) ? LogService.LOG_DEBUG : LogService.LOG_INFO;

		log(logType, getServiceEventTypeName(eventType), reference.getBundle(), reference, null);
	}

	/**
	 * FrameworkListener.frameworkEvent method.
	 *
	 */
	public void frameworkEvent(FrameworkEvent event) {
		int type = event.getType();

		if (type == FrameworkEvent.ERROR) {
			log(LogService.LOG_ERROR, getFrameworkEventTypeName(type), event.getBundle(), null, event.getThrowable());
		} else {
			log(LogService.LOG_INFO, getFrameworkEventTypeName(type), event.getBundle(), null, null);
		}
	}

	/**
	 * Convert BundleEvent type to a string.
	 *
	 */
	protected static String getBundleEventTypeName(int type) {
		switch (type) {
			case BundleEvent.INSTALLED :
				return ("BundleEvent INSTALLED"); //$NON-NLS-1$

			case BundleEvent.RESOLVED :
				return ("BundleEvent RESOLVED"); //$NON-NLS-1$

			case BundleEvent.STARTED :
				return ("BundleEvent STARTED"); //$NON-NLS-1$

			case BundleEvent.STARTING :
				return ("BundleEvent STARTING"); //$NON-NLS-1$
				
			case BundleEvent.STOPPED :
				return ("BundleEvent STOPPED"); //$NON-NLS-1$

			case BundleEvent.STOPPING :
				return ("BundleEvent STOPPING"); //$NON-NLS-1$
				
			case BundleEvent.UNINSTALLED :
				return ("BundleEvent UNINSTALLED"); //$NON-NLS-1$

			case BundleEvent.UNRESOLVED :
				return ("BundleEvent UNRESOLVED"); //$NON-NLS-1$
			
			case BundleEvent.UPDATED :
				return ("BundleEvent UPDATED"); //$NON-NLS-1$

			default :
				return (NLS.bind(LogMsg.BundleEvent, Integer.toHexString(type)));
		}
	}

	/**
	 * Convert ServiceEvent type to a string.
	 *
	 */
	protected static String getServiceEventTypeName(int type) {
		switch (type) {
			case ServiceEvent.REGISTERED :
				return ("ServiceEvent REGISTERED"); //$NON-NLS-1$

			case ServiceEvent.MODIFIED :
				return ("ServiceEvent MODIFIED"); //$NON-NLS-1$

			case ServiceEvent.UNREGISTERING :
				return ("ServiceEvent UNREGISTERING"); //$NON-NLS-1$

			default :
				return (NLS.bind(LogMsg.ServiceEvent, Integer.toHexString(type)));
		}
	}

	/**
	 * Convert FrameworkEvent type to a string.
	 *
	 */
	protected static String getFrameworkEventTypeName(int type) {
		switch (type) {
			case FrameworkEvent.ERROR :
				return ("FrameworkEvent ERROR"); //$NON-NLS-1$

			case FrameworkEvent.INFO :
				return ("FrameworkEvent INFO"); //$NON-NLS-1$
				
			case FrameworkEvent.PACKAGES_REFRESHED :
				return ("FrameworkEvent PACKAGES REFRESHED"); //$NON-NLS-1$

			case FrameworkEvent.STARTED :
				return ("FrameworkEvent STARTED"); //$NON-NLS-1$

			case FrameworkEvent.STARTLEVEL_CHANGED :
				return ("FrameworkEvent STARTLEVEL CHANGED"); //$NON-NLS-1$
				
			case FrameworkEvent.WARNING :
				return ("FrameworkEvent WARNING"); //$NON-NLS-1$

			default :
				return (NLS.bind(LogMsg.FrameworkEvent, Integer.toHexString(type)));
		}
	}

	/**
	 * Update the configuration for a ManagedService.
	 *
	 * <p> When the implementation of updated(Dictionary) detects any kind of
	 * error in the configuration properties, it should create a
	 * new ConfigurationException which describes the problem.  This
	 * can allow a management system to provide useful information to
	 * a human administrator.
	 * <p> If this method throws any other Exception, the
	 * ConfigurationAdmin must catch it and should log it.
	 * <p> The ConfigurationAdmin must call this method on a thread
	 * other than the thread which initiated the call-back. This
	 * implies that implementors of ManagedService can be assured
	 * that the call-back will not take place during registration
	 * when they execute the registration in a synchronized method.
	 *
	 * @param properties configuration properties, or null
	 * @throws ConfigurationException when the update fails
	 **/
	public synchronized void updated(Dictionary properties) throws ConfigurationException {
		/* Since updated is called asynchronously, we may have stopped
		 * after the decision was made to call.
		 */
		if (context != null) {
			if (properties == null) {
				/* We have no configuration; we will just use our defaults */
				return;
			}

			int size = logSize;
			int threshold = logThreshold;

			/* Get configuration values and validate */
			Object property = properties.get(keyLogSize);
			if (property != null) /* if null we will just use the default */
			{
				if (!(property instanceof Integer)) {
					throw new ConfigurationException(keyLogSize, "not an Integer"); //$NON-NLS-1$
				}

				size = ((Integer) property).intValue();

				if ((size < 10) || (size > 2000)) {
					throw new ConfigurationException(keyLogSize, "must be in the range 10-2000"); //$NON-NLS-1$
				}
			}

			property = properties.get(keyLogThreshold);
			if (property != null) /* if null we will just use the default */
			{
				if (!(property instanceof Integer)) {
					throw new ConfigurationException(keyLogThreshold, "not an Integer"); //$NON-NLS-1$
				}

				threshold = ((Integer) property).intValue();

				if ((threshold < LogService.LOG_ERROR) || (threshold > LogService.LOG_DEBUG)) {
					throw new ConfigurationException(keyLogThreshold, "must be one of the LogService defined Log levels"); //$NON-NLS-1$
				}
			}

			/* Configuration values have been validated */
			if (size != logSize) {
				updateLogSize(size);
			}

			if (threshold != logThreshold) {
				updateLogThreshold(threshold);
			}
		}
	}

	/**
	 * This method must be called while synchronized.
	 *
	 */
	private void updateLogSize(int size) {
		LogEntry[] newlog = new LogEntry[size];

		if (head <= tail) { /* log is not full */
			int count = tail - head + 1;
			if (size > count) { /* is new log bigger? */
				System.arraycopy(logEntries, head, newlog, 0, count);
				tail = count - 1;
			} else { /* new log smaller */
				System.arraycopy(logEntries, head + count - size, newlog, 0, size);
				tail = size - 1;
			}
		} else { /* log is full */
			int count = tail + 1 + logSize - head;
			if (size > count) { /* is new log bigger? */
				int boundary = logSize - head;
				System.arraycopy(logEntries, head, newlog, 0, boundary);
				System.arraycopy(logEntries, 0, newlog, boundary, count - boundary);
				tail = count - 1;
			} else { /* new log smaller */
				if ((tail + 1) < size) { /* is log big enough to hold first half? */
					int boundary = size - (tail + 1);
					System.arraycopy(logEntries, logSize - boundary, newlog, 0, boundary);
					System.arraycopy(logEntries, 0, newlog, boundary, tail + 1);
				} else {
					System.arraycopy(logEntries, tail + 1 - size, newlog, 0, size); //9626
				}
				tail = size - 1;
			}
		}

		logEntries = newlog;
		logSize = size;

		head = 0;

		String changemessage = NLS.bind(LogMsg.Log_modified_Log_Size, String.valueOf(logSize));

		log(LogService.LOG_INFO, changemessage, context.getBundle(), null, null);
	}

	/**
	 * This method must be called while synchronized.
	 *
	 */
	private void updateLogThreshold(int threshold) {
		logThreshold = threshold;

		String changemessage = NLS.bind(LogMsg.Log_modified_Log_Threshold, String.valueOf(logThreshold));

		log(LogService.LOG_INFO, changemessage, context.getBundle(), null, null);
	}

	protected void registerManagedService() {
		/* Register a Managed Service to handle updates to the Log configuration values */
		Hashtable properties = new Hashtable(7);

		properties.put(Constants.SERVICE_VENDOR, "IBM"); //$NON-NLS-1$
		properties.put(Constants.SERVICE_DESCRIPTION, LogMsg.OSGi_Log_Service_IBM_Implementation);
		properties.put(Constants.SERVICE_PID, LOGSERVICEPID);

		logmanagedservice = context.registerService(ManagedService.class.getName(), this, properties);
	}

	private void registerLogService() {
		Hashtable properties = new Hashtable(7);

		properties.put(Constants.SERVICE_VENDOR, "IBM"); //$NON-NLS-1$
		properties.put(Constants.SERVICE_DESCRIPTION, LogMsg.OSGi_Log_Service_IBM_Implementation);
		properties.put(Constants.SERVICE_PID, LogServiceImpl.class.getName());

		logservice = context.registerService(LogService.class.getName(), new LogServiceFactory(this), properties);

	}

	private void registerLogReaderService() {
		Hashtable properties = new Hashtable(7);

		properties.put(Constants.SERVICE_VENDOR, "IBM"); //$NON-NLS-1$
		properties.put(Constants.SERVICE_DESCRIPTION, LogMsg.OSGi_Log_Service_IBM_Implementation);
		properties.put(Constants.SERVICE_PID, LogReaderService.class.getName());

		logreaderservice = context.registerService(org.osgi.service.log.LogReaderService.class.getName(), new LogReaderServiceFactory(this), properties);
	}
}
