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

package org.eclipse.osgi.framework.launcher;

import java.lang.reflect.Constructor;
import java.util.*;
import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.internal.core.OSGi;
import org.eclipse.osgi.framework.util.Tokenizer;

/**
 * <p>This class provides an entry point for launching the OSGi framework.
 * It configures the OSGi framework according to the command line arguments:
 * <ul>
 * <li><b>-con[sole][:<i>port</i>]</b><br>
 *   Starts the OSGi framework with a console window.  Any command line arguments not recognized are passed
 *   to the console for it to execute.  If a port is specified the console will listen on that
 *   port for commands.  If no port is specified, the console will use System.in and System.out.
 * </li>
 * <li><b>-adaptor[:adaptor-name][adaptor-args]</b>
 * <pre>
 * [adaptor-name] := "" | fully qualified class name of the FrameworkAdapter
 * [adaptor-args] := *( ":" [value])
 * [value] := [token] | [quoted-string]
 *
 * This allows
 *
 * -adaptor::"bundledir=c:\jarbundles":reset 		DefaultAdaptor is chosen with args[] {"bundledir=c:\jarbundles", "reset"}
 * -adaptor:com.foo.MyAdaptor				com.foo.MyAdaptor chosen with args[] {}
 * </pre>
 *   <p>-adaptor specifies the implementation class for the FrameworkAdapter to be used.
 *   args contains a list of FrameworkAdaptor arguments, separated by ":".  FrameworkAdaptor arguments
 *   format is defined by the adaptor implementation class.  They
 *   are passed to the adaptor class as an array of Strings.
 *   Example arguments used by the DefaultAdaptor are:
 *   <ul>
 *   <li>"bundledir=<i>directory"</i>.  The directory to be used by the adaptor to store data.
 *   <li>reset</i>.  Perform the reset action to clear the bundledir.
 *   <p>Actions can be defined by an adaptor.  Multiple actions can be specified,
 *   separated by ":".
 *   </ul>
 *   <p>It is up to the adaptor implementation to define reasonable defaults if it's required
 *   arguments are not specified.
 *   <p>If -adaptor is not specified, or if no adaptor classname is specified, DefaultAdaptor will be
 *   used, which is file based and stores the files in the \bundles directory
 *   relative to the current directory.
 * </ul>
 * <li>-app[lication]:application-args
 * <pre>
 *    [application-args] := *( ":" [value])
 *    [value] := [token] | [quoted-string]
 * </pre>
 * <p>This argument allows arguments to be passed to specific applications at launch time.  This is for eclipse
 * plugins installed as applications.  The arguments are as Eclipse currently needs them - one list of key=value pairs 
 * which are parsed by the applications.  The application peels off only the args that apply to it.  Others are ignored. 
 * </li>
 * <p>
 * Any other command line arguments are passed on to the console window
 * of the framework if started with the -console option.  If the console is not started,
 * any unrecognized arguments will be ignored and a message displayed.
 * <p>
 * If none of the options above are specified, the OSGi framework is started:
 * <ul>
 * <li>with the Default FrameworkAdaptor
 * <li>without a console window
 * <li>without the remote agent
 * </ul>
 */
public class Launcher {
	// :TODO Need to NLS enable this class.

	/** default console port */
	protected String consolePort = "";

	/** flag to indicate whether or not to start the console */
	protected boolean console = false;

	/** string containing the classname of the adaptor to be used in this framework instance */
	protected String adaptorClassName = "org.eclipse.osgi.framework.internal.defaultadaptor.DefaultAdaptor";

	protected final String IdeAdentClassName = "org.eclipse.osgi.framework.internal.core.ide.IdeAgent";

	protected final String osgiConsoleClazz = "org.eclipse.osgi.framework.internal.core.FrameworkConsole";

	/** array of adaptor arguments to be passed to FrameworkAdaptor.initialize() */
	String[] adaptorArgs = null;

	/** array of application arguments to be passed to Eclipse applications */
	String[] applicationArgs = null;

	/* Components that can be installed and activated optionally. */
	private static final String OSGI_CONSOLE_COMPONENT_NAME = "OSGi Console";
	private static final String OSGI_CONSOLE_COMPONENT = "osgiconsole.jar";

	/**
	 * main method for Launcher. This method creates an Launcher object
	 * and kicks off the actual launch of a Framework instance.
	 *
	 * @param args The command line arguments
	 */
	public static void main(String args[]) {

		new Launcher().doIt(args);

	}

	/**
	 *  Default constructor.  Nothing at all to do here.
	 */
	public Launcher() {
	}

	/**
	 *  Performs the actual launch based on the command line arguments
	 *
	 *  @param args The command line arguments
	 */
	protected void doIt(String[] args) {
		String[] consoleArgs = parseArgs(args);

		FrameworkAdaptor adaptor = null;
		try {
			adaptor = doAdaptor();
		} catch (Exception e) {
			System.out.println("Unable to create FrameworkAdaptor: ");
			e.printStackTrace();
			return;
		}

		OSGi osgi = doOSGi(adaptor);
		if (osgi != null) {
			if (console) {
				doConsole(osgi, consoleArgs);
			} else {
				osgi.launch();
			}
		}
		doApplication();
	}

	/**
	 *  Parses the command line arguments and remembers them so they can be processed later.
	 *
	 *  @param args The command line arguments
	 *  @return String [] Any arguments that should be passed to the console
	 */
	private String[] parseArgs(String[] args) {
		Vector consoleArgsVector = new Vector();
		for (int i = 0; i < args.length; i++) {
			boolean match = false;

			// Have to check for args that may be contained in double quotes but broken up by spaces - for example
			// -adaptor::"bundledir=c:/my bundle dir":reset should all be one arg, but java breaks it into 3 args, 
			// ignoring the quotes.  Must put it back together into one arg.
			String fullarg = args[i];
			int quoteidx = fullarg.indexOf("\"");
			if (quoteidx > 0) {
				if (quoteidx == fullarg.lastIndexOf("\"")) {
					boolean stillparsing = true;
					i++;
					while (i < args.length && stillparsing) {
						fullarg = fullarg + " " + args[i];
						i++;
						if (quoteidx < fullarg.lastIndexOf("\"")) {
							stillparsing = false;
						}
					}
				}
			} else {
				// IDE can't pass double quotes due to known eclipse bug (see Bugzilla 93201).  Allowing for use of single quotes.
				quoteidx = fullarg.indexOf("'");
				if (quoteidx > 0) {
					if (quoteidx == fullarg.lastIndexOf("'")) {
						boolean stillparsing = true;
						i++;
						while (i < args.length && stillparsing) {
							fullarg = fullarg + " " + args[i];
							i++;
							if (quoteidx < fullarg.lastIndexOf("'")) {
								stillparsing = false;
							}
						}
					}
					fullarg = fullarg.replace('\'', '\"');
				}
			}

			Tokenizer tok = new Tokenizer(fullarg);
			if (tok.hasMoreTokens()) {
				String command = tok.getString(" ");
				StringTokenizer subtok = new StringTokenizer(command, ":");
				String subcommand = subtok.nextToken().toLowerCase();

				if (matchCommand("-console", subcommand, 4)) {
					_console(command);
					match = true;
				}
				if (matchCommand("-adaptor", subcommand, 2)) {
					_adaptor(command);
					match = true;
				}
				if (matchCommand("-application", subcommand, 3)) {
					_application(command);
					match = true;
				}

				if (match == false) {
					// if the command doesn't match any of the known commands, save it to pass
					// to the console
					consoleArgsVector.addElement(fullarg);
				}
			}
		}
		// convert arguments to be passed to console into a string array for the Console
		String[] consoleArgsArray = new String[consoleArgsVector.size()];
		Enumeration e = consoleArgsVector.elements();
		for (int i = 0; i < consoleArgsArray.length; i++) {
			consoleArgsArray[i] = (String) e.nextElement();
		}
		return consoleArgsArray;
	}

	public static boolean matchCommand(String command, String input, int minLength) {
		if (minLength <= 0) {
			minLength = command.length();
		}

		int length = input.length();

		if (minLength > length) {
			length = minLength;
		}

		return (command.regionMatches(0, input, 0, length));
	}

	/**
	 *  Remembers that the -console option has been requested.
	 */
	protected void _console(String command) {
		console = true;
		StringTokenizer tok = new StringTokenizer(command, ":");
		// first token is always "-console"
		String cmd = tok.nextToken();
		if (tok.hasMoreTokens()) {
			consolePort = tok.nextToken();
		}
	}

	/**
	 *  Remembers that the -adaptor option has been requested.  Parses off the adaptor class
	 *  file name, the adaptor file name, and the size if they are there.
	 *
	 * @param tok The rest of the -adaptor parameter string that contains the class file name,
	 * and possibly the adaptor file and file size.
	 */
	protected void _adaptor(String command) {
		Tokenizer tok = new Tokenizer(command);
		// first token is always "-adaptor"
		String cmd = tok.getToken(":");
		tok.getChar(); // advance to next token
		// and next token is either adaptor class name or ":" if we should use the default adaptor
		String adp = tok.getToken(":");
		if (adp.length() > 0) {
			adaptorClassName = adp;
		}

		// The following tokens are arguments to be processed by the adaptor implementation class.
		// They may be enclosed in quotes.
		// Store them in a vector until we know how many there are.
		Vector v = new Vector();
		parseloop: while (true) {
			tok.getChar(); // advance to next token
			String arg = tok.getString(":");
			if (arg == null) {
				break parseloop;
			} else {
				v.addElement(arg);
			}
		}
		// now that we know how many args there are, move args from vector to String[]
		if (v != null) {
			int numArgs = v.size();
			adaptorArgs = new String[numArgs];
			Enumeration e = v.elements();
			for (int i = 0; i < numArgs; i++) {
				adaptorArgs[i] = (String) e.nextElement();
			}
		}
	}

	/**
	 *  Remembers that the -application option has been requested.  Parses off the application parameters
	 *  into a String []
	 *
	 * @param tok The rest of the -application parameter string that contains the application arguments
	 */
	protected void _application(String command) {
		Tokenizer tok = new Tokenizer(command);
		// first token is always "-adaptor"
		String cmd = tok.getToken(":");
		// following tokens are arguments to be processed by the adaptor implementation class
		// they may be enclosed in quotes
		// store them in a vector until we know how many there are
		Vector v = new Vector();
		parseloop: while (true) {
			tok.getChar(); // advance to next token
			String arg = tok.getString(":");
			if (arg == null) {
				break parseloop;
			} else {
				v.addElement(arg);
			}
		}
		// now that we know how many args there are, move args from vector to String []
		if (v != null) {
			int numArgs = v.size();
			applicationArgs = new String[numArgs];
			Enumeration e = v.elements();
			for (int i = 0; i < numArgs; i++) {
				applicationArgs[i] = (String) e.nextElement();
			}
		}
	}

	/**
	 *  Processes the -adaptor command line argument.
	 * 
	 *  Parses the arguments to get the adaptor class name, the adaptor dir or filename,
	 *  and the adaptor file size.
	 *
	 *  @return a FrameworkAdaptor object
	 */
	protected FrameworkAdaptor doAdaptor() throws Exception {

		Class adaptorClass = Class.forName(adaptorClassName);
		Class[] constructorArgs = new Class[] {String[].class};
		Constructor constructor = adaptorClass.getConstructor(constructorArgs);
		return (FrameworkAdaptor) constructor.newInstance(new Object[] {adaptorArgs});
	}

	/**
	 *  Processes the -application command line argument.
	 * 
	 */
	protected void doApplication() {
		// nothing to do right now - these are argumnents for eclipse applications

	}

	/**
	 * Creates the OSGi framework object.
	 *
	 * @param The FrameworkAdaptor object
	 */
	protected OSGi doOSGi(FrameworkAdaptor adaptor) {
		return new OSGi(adaptor);
	}

	/**
	 *  Invokes the OSGi Console on another thread
	 *
	 * @param osgi The current OSGi instance for the console to attach to
	 * @param consoleArgs An String array containing commands from the command line
	 * for the console to execute
	 */
	protected void doConsole(OSGi osgi, String[] consoleArgs) {

		Constructor consoleConstructor;
		Object osgiconsole;
		Class[] parameterTypes;
		Object[] parameters;

		try {
			Class osgiconsoleClass = Class.forName(osgiConsoleClazz);
			if (consolePort.length() == 0) {
				parameterTypes = new Class[] {OSGi.class, String[].class};
				parameters = new Object[] {osgi, consoleArgs};
			} else {
				parameterTypes = new Class[] {OSGi.class, int.class, String[].class};
				parameters = new Object[] {osgi, new Integer(consolePort), consoleArgs};
			}
			consoleConstructor = osgiconsoleClass.getConstructor(parameterTypes);
			osgiconsole = consoleConstructor.newInstance(parameters);

			Thread t = new Thread(((Runnable) osgiconsole), OSGI_CONSOLE_COMPONENT_NAME);
			t.start();
		} catch (NumberFormatException nfe) {
			System.err.println("Invalid console port: " + consolePort);
		} catch (Exception ex) {
			informAboutMissingComponent(OSGI_CONSOLE_COMPONENT_NAME, OSGI_CONSOLE_COMPONENT);
		}

	}

	/**
	 * Informs the user about a missing component.
	 *
	 * @param component The name of the component
	 * @param jar The jar file that contains the component
	 */
	void informAboutMissingComponent(String component, String jar) {
		System.out.println();
		System.out.print("Warning: The requested component '" + component + "' is not included in this runtime.");
		System.out.println(" Add '" + jar + "' to the classpath or rebuild the jxe with it.");
		System.out.println();
	}
}