/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * Portions Copyright  2000-2005 The Apache Software Foundation
 *
 * This program and the accompanying materials are made 
 * available under the terms of the Apache Software License v2.0 which 
 * accompanies this distribution and is available at 
 * http://www.apache.org/licenses/LICENSE-2.0.
 * 
 * Contributors:
 *     IBM Corporation - derived implementation
 *     Rob Stryker - Bug 459188 - InternalAntRunner tries to set null user property
 *******************************************************************************/

package org.eclipse.ant.internal.launching.remote;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

import org.apache.tools.ant.AntTypeDefinition;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.DemuxOutputStream;
import org.apache.tools.ant.Diagnostics;
import org.apache.tools.ant.Main;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskAdapter;
import org.apache.tools.ant.util.FileUtils;
import org.eclipse.ant.internal.launching.remote.logger.RemoteAntBuildLogger;

/**
 * Eclipse application entry point into Ant in a separate VM. Derived from the original Ant Main class to ensure that the functionality is equivalent
 * when running in the platform.
 */
public class InternalAntRunner {

	/**
	 * Message priority for project help messages.
	 */
	public static final int MSG_PROJECT_HELP = Project.MSG_DEBUG + 1;

	private List<String> buildListeners;

	private String buildFileLocation;

	/**
	 * Targets we want to run.
	 */
	private Vector<String> targets;

	private Map<String, String> userProperties;

	private Project currentProject;

	private BuildLogger buildLogger = null;

	private Map<String, String> eclipseSpecifiedTasks;
	private Map<String, String> eclipseSpecifiedTypes;

	/**
	 * Cache of the Ant version number when it has been loaded
	 */
	private String antVersionNumber = null;

	/** Our current message output status. Follows Project.MSG_XXX */
	private int messageOutputLevel = Project.MSG_INFO;

	/** Indicates whether output to the log is to be unadorned. */
	private boolean emacsMode = false;

	/** Indicates we should only parse and display the project help information */
	private boolean projectHelp = false;

	/** Stream that we are using for logging */
	private PrintStream out = System.out;

	/** Stream that we are using for logging error messages */
	private PrintStream err = System.err;

	/**
	 * The Ant logger class. There may be only one logger. It will have the right to use the 'out' PrintStream. The class must implement the
	 * BuildLogger interface. An empty String indicates that no logger is to be used. A <code>null</code> name indicates that the
	 * <code>org.apache.tools.ant.DefaultLogger</code> will be used.
	 */
	private String loggerClassname = null;

	/** Extra arguments to be parsed as command line arguments. */
	private String[] extraArguments = null;

	private boolean scriptExecuted = false;

	@SuppressWarnings("unused")
	private List<String> propertyFiles = new ArrayList<String>();

	/**
	 * The Ant InputHandler class. There may be only one input handler.
	 */
	private String inputHandlerClassname = null;

	/**
	 * Indicates whether to execute all targets that do not depend on failed targets
	 * 
	 * @since Ant 1.6.0
	 */
	private boolean keepGoing = false;

	/**
	 * Indicates whether this build is to support interactive input
	 * 
	 * @since Ant 1.6.0
	 */
	private boolean allowInput = true;

	private String fEarlyErrorMessage = null;

	public static void main(String[] args) {
		try {
			new InternalAntRunner().run(getArrayList(args));
		}
		catch (Throwable t) {
			t.printStackTrace();
			System.exit(1);
		}
		System.exit(0);
	}

	/*
	 * Helper method to ensure an array is converted into an ArrayList.
	 */
	@SuppressWarnings("unused")
	static ArrayList<String> getArrayList(String[] args) {
		if (args == null) {
			return null;
		}
		// We could be using Arrays.asList() here, but it does not specify
		// what kind of list it will return. We need a list that
		// implements the method List.remove(Object) and ArrayList does.
		ArrayList<String> result = new ArrayList<String>(args.length);
		for (int i = 0; i < args.length; i++) {
			result.add(args[i]);
		}
		return result;
	}

	private void addBuildListeners(Project project) {
		String clazz = null;
		try {
			BuildLogger logger = createLogger();
			if (logger != null) {
				project.addBuildListener(logger);
			}
			if (buildListeners != null) {
				for (String className : buildListeners) {
					clazz = className;
					Class<?> listener = Class.forName(className);
					project.addBuildListener((BuildListener) listener.newInstance());
				}
			}
		}
		catch (ClassCastException e) {
			String message = MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.{0}_which_was_specified_to_be_a_build_listener_is_not_an_instance_of_org.apache.tools.ant.BuildListener._1"), new Object[] { //$NON-NLS-1$
					clazz });
			logMessage(null, message, Project.MSG_ERR);
			throw new BuildException(message, e);
		}
		catch (BuildException e) {
			throw e;
		}
		catch (Exception e) {
			throw new BuildException(e);
		}
	}

	/**
	 * Parses the build file and adds necessary information into the given project.
	 * 
	 * @param project
	 *            The project to configure
	 */
	private void parseBuildFile(Project project) {
		File buildFile = new File(getBuildFileLocation());
		if (!buildFile.exists()) {
			throw new BuildException(MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Buildfile__{0}_does_not_exist_!_1"), //$NON-NLS-1$
					new Object[] { buildFile.getAbsolutePath() }));
		}
		if (!buildFile.isFile()) {
			throw new BuildException(MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Buildfile__{0}_is_not_a_file_1"), //$NON-NLS-1$
					new Object[] { buildFile.getAbsolutePath() }));
		}

		if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
			parseBuildFile(project, buildFile);
		} else {
			ProjectHelper helper = ProjectHelper.getProjectHelper();
			project.addReference("ant.projectHelper", helper); //$NON-NLS-1$
			helper.parse(project, buildFile);
		}
	}

	/**
	 * @deprecated support for Ant older than 1.5
	 */
	@Deprecated
	private void parseBuildFile(Project project, File buildFile) {
		ProjectHelper.configureProject(project, buildFile);
	}

	private void printArguments(Project project) {
		if ((messageOutputLevel != Project.MSG_DEBUG) && (messageOutputLevel != Project.MSG_VERBOSE)) {
			return;
		}
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < extraArguments.length; i++) {
			sb.append(extraArguments[i]);
			sb.append(' ');
		}
		project.log(MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Arguments__{0}_2"), new Object[] { sb.toString().trim() })); //$NON-NLS-1$
	}

	/**
	 * Logs a message with the client that lists the targets in a project
	 * 
	 * @param project
	 *            the project to list targets from
	 */
	@SuppressWarnings("unused")
	private void printTargets(Project project) {
		// notify the logger that project help message are coming
		// since there is no buildstarted or targetstarted to
		// to be used to establish the connection
		logMessage(project, IAntCoreConstants.EMPTY_STRING, MSG_PROJECT_HELP);
		// find the target with the longest name
		int maxLength = 0;
		Enumeration<Target> ptargets = project.getTargets().elements();
		String targetName;
		String targetDescription;
		Target currentTarget;
		// split the targets in top-level and sub-targets depending
		// on the presence of a description
		List<String> topNames = new ArrayList<String>();
		List<String> topDescriptions = new ArrayList<String>();
		List<String> subNames = new ArrayList<String>();

		while (ptargets.hasMoreElements()) {
			currentTarget = ptargets.nextElement();
			targetName = currentTarget.getName();
			targetDescription = currentTarget.getDescription();
			if (targetDescription == null) {
				subNames.add(targetName);
			} else {
				topNames.add(targetName);
				topDescriptions.add(targetDescription);
				if (targetName.length() > maxLength) {
					maxLength = targetName.length();
				}
			}
		}

		Collections.sort(subNames);
		Collections.sort(topNames);
		Collections.sort(topDescriptions);

		String defaultTargetName = project.getDefaultTarget();
		if (defaultTargetName != null && !IAntCoreConstants.EMPTY_STRING.equals(defaultTargetName)) { // shouldn't need to check but...
			List<String> defaultName = new ArrayList<String>(1);
			List<String> defaultDesc = null;
			defaultName.add(defaultTargetName);

			int indexOfDefDesc = topNames.indexOf(defaultTargetName);
			if (indexOfDefDesc >= 0) {
				defaultDesc = new ArrayList<String>(1);
				defaultDesc.add(topDescriptions.get(indexOfDefDesc));
			}
			printTargets(project, defaultName, defaultDesc, RemoteAntMessages.getString("InternalAntRunner.Default_target__3"), maxLength); //$NON-NLS-1$

		}

		printTargets(project, topNames, topDescriptions, RemoteAntMessages.getString("InternalAntRunner.Main_targets__4"), maxLength); //$NON-NLS-1$
		printTargets(project, subNames, null, RemoteAntMessages.getString("InternalAntRunner.Subtargets__5"), 0); //$NON-NLS-1$
	}

	/**
	 * Logs a message with the client that lists the target names and optional descriptions
	 * 
	 * @param project
	 *            the enclosing target
	 * @param names
	 *            the targets names
	 * @param descriptions
	 *            the corresponding descriptions
	 * @param heading
	 *            the message heading
	 * @param maxlen
	 *            maximum length that can be allocated for a name
	 */
	private void printTargets(Project project, List<String> names, List<String> descriptions, String heading, int maxlen) {
		// now, start printing the targets and their descriptions
		String lSep = System.getProperty("line.separator"); //$NON-NLS-1$

		String spaces = "    "; //$NON-NLS-1$
		while (spaces.length() < maxlen) {
			spaces += spaces;
		}
		StringBuffer msg = new StringBuffer();
		msg.append(heading + lSep + lSep);
		for (int i = 0; i < names.size(); i++) {
			msg.append(' ');
			msg.append(names.get(i));
			if (descriptions != null) {
				msg.append(spaces.substring(0, maxlen - names.get(i).length() + 2));
				msg.append(descriptions.get(i));
			}
			msg.append(lSep);
		}
		logMessage(project, msg.toString(), Project.MSG_INFO);
	}

	/*
	 * Note that the list passed to this method must support List#remove(Object)
	 */
	@SuppressWarnings("unused")
	private void run(List<String> argList) {
		setCurrentProject(new Project());
		if (isVersionCompatible("1.6.3")) { //$NON-NLS-1$
			new ExecutorSetter().setExecutor(getCurrentProject());
		}
		Throwable error = null;
		PrintStream originalErr = System.err;
		PrintStream originalOut = System.out;
		InputStream originalIn = System.in;

		SecurityManager originalSM = System.getSecurityManager();
		scriptExecuted = true;
		try {
			if (argList != null && (argList.remove("-projecthelp") || argList.remove("-p"))) { //$NON-NLS-1$ //$NON-NLS-2$
				projectHelp = true;
			}
			getCurrentProject().init();
			if (argList != null) {
				scriptExecuted = preprocessCommandLine(argList);

				if (!scriptExecuted) {
					return;
				}
			}

			boolean exceptionState = processProperties(argList);

			addBuildListeners(getCurrentProject());

			addInputHandler(getCurrentProject());

			remapSystemIn();
			System.setOut(new PrintStream(new DemuxOutputStream(getCurrentProject(), false)));
			System.setErr(new PrintStream(new DemuxOutputStream(getCurrentProject(), true)));

			if (!projectHelp) {
				fireBuildStarted(getCurrentProject());
			}

			if (fEarlyErrorMessage != null) {
				// an error occurred processing the properties
				// build started has fired and we have
				// listeners/loggers to report the error
				logMessage(getCurrentProject(), fEarlyErrorMessage, Project.MSG_ERR);
				if (exceptionState) {
					throw new BuildException(fEarlyErrorMessage);
				}
			}

			// properties can only be set after buildStarted as some listeners/loggers
			// depend on this (e.g. XMLLogger)
			setProperties(getCurrentProject());

			if (argList != null && !argList.isEmpty()) {
				try {
					scriptExecuted = processCommandLine(argList);
				}
				catch (BuildException e) {
					scriptExecuted = false;
					throw e;
				}
			}
			if (!scriptExecuted) {
				return;
			}

			// needs to occur after processCommandLine(List)
			if (allowInput && (inputHandlerClassname != null && inputHandlerClassname.length() > 0)) {
				if (isVersionCompatible("1.6")) { //$NON-NLS-1$
					getCurrentProject().setDefaultInputStream(originalIn);
				}
			} else {
				// set the system property that any input handler
				// can check to see if handling input is allowed
				System.setProperty("eclipse.ant.noInput", "true"); //$NON-NLS-1$//$NON-NLS-2$
				if (isVersionCompatible("1.5") && (inputHandlerClassname == null || inputHandlerClassname.length() == 0)) { //$NON-NLS-1$
					InputHandlerSetter setter = new InputHandlerSetter();
					setter.setInputHandler(getCurrentProject(), "org.eclipse.ant.internal.launching.remote.inputhandler.FailInputHandler"); //$NON-NLS-1$
				}
			}

			getCurrentProject().log(MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Build_file__{0}_1"), new Object[] { //$NON-NLS-1$
					getBuildFileLocation() }));

			setTasks();
			setTypes();

			if (isVersionCompatible("1.6")) { //$NON-NLS-1$
				getCurrentProject().setKeepGoingMode(keepGoing);
			}

			parseBuildFile(getCurrentProject());

			if (projectHelp) {
				printHelp(getCurrentProject());
				scriptExecuted = false;
				return;
			}

			if (extraArguments != null) {
				printArguments(getCurrentProject());
			}

			System.setSecurityManager(new AntSecurityManager(originalSM, Thread.currentThread()));

			if (targets == null) {
				targets = new Vector<String>(1);
			}
			if (targets.isEmpty() && getCurrentProject().getDefaultTarget() != null) {
				targets.add(getCurrentProject().getDefaultTarget());
			}
			if (!isVersionCompatible("1.6.3")) { //$NON-NLS-1$
				getCurrentProject().addReference(IAntCoreConstants.TARGET_VECTOR_NAME, targets);
			}
			getCurrentProject().executeTargets(targets);
		}
		catch (AntSecurityException e) {
			// expected
		}
		catch (Throwable e) {
			error = e;
		}
		finally {
			System.setErr(originalErr);
			System.setOut(originalOut);
			System.setIn(originalIn);
			if (System.getSecurityManager() instanceof AntSecurityManager) {
				System.setSecurityManager(originalSM);
			}

			if (!projectHelp) {
				fireBuildFinished(getCurrentProject(), error);
			}

			// close any user specified build log
			if (err != originalErr) {
				err.close();
			}
			if (out != originalOut) {
				out.close();
			}
		}
	}

	private void setTasks() {
		if (eclipseSpecifiedTasks != null) {
			String taskName;
			String taskClassName;
			for (Entry<String, String> entry : eclipseSpecifiedTasks.entrySet()) {
				taskName = entry.getKey();
				taskClassName = entry.getValue();

				if (isVersionCompatible("1.6")) { //$NON-NLS-1$
					AntTypeDefinition def = new AntTypeDefinition();
					def.setName(taskName);
					def.setClassName(taskClassName);
					def.setClassLoader(this.getClass().getClassLoader());
					def.setAdaptToClass(Task.class);
					def.setAdapterClass(TaskAdapter.class);
					ComponentHelper.getComponentHelper(getCurrentProject()).addDataTypeDefinition(def);
				} else {
					try {
						Class<?> taskClass = Class.forName(taskClassName);
						getCurrentProject().addTaskDefinition(taskName, taskClass);
					}
					catch (ClassNotFoundException e) {
						String message = MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.161"), new Object[] { taskClassName, //$NON-NLS-1$
								taskName });
						getCurrentProject().log(message, Project.MSG_WARN);
					}
				}
			}
		}
	}

	private void setTypes() {
		if (eclipseSpecifiedTypes != null) {
			String typeName;
			String typeClassName;
			for (Entry<String, String> entry : eclipseSpecifiedTypes.entrySet()) {
				typeName = entry.getKey();
				typeClassName = entry.getValue();
				if (isVersionCompatible("1.6")) { //$NON-NLS-1$
					AntTypeDefinition def = new AntTypeDefinition();
					def.setName(typeName);
					def.setClassName(typeClassName);
					def.setClassLoader(this.getClass().getClassLoader());
					ComponentHelper.getComponentHelper(getCurrentProject()).addDataTypeDefinition(def);
				} else {
					try {
						Class<?> typeClass = Class.forName(typeClassName);
						getCurrentProject().addDataTypeDefinition(typeName, typeClass);
					}
					catch (ClassNotFoundException e) {
						String message = MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.162"), new Object[] { typeClassName, //$NON-NLS-1$
								typeName });
						getCurrentProject().log(message, Project.MSG_WARN);
					}
				}
			}
		}
	}

	private void remapSystemIn() {
		if (!isVersionCompatible("1.6")) { //$NON-NLS-1$
			return;
		}
		DemuxInputStreamSetter setter = new DemuxInputStreamSetter();
		setter.remapSystemIn(getCurrentProject());
	}

	/**
	 * Creates and returns the default build logger for logging build events to the ant log.
	 * 
	 * @return the default build logger for logging build events to the ant log can return <code>null</code> if no logging is to occur
	 */
	private BuildLogger createLogger() {
		if (loggerClassname == null) {
			buildLogger = new DefaultLogger();
		} else if (!IAntCoreConstants.EMPTY_STRING.equals(loggerClassname)) {
			try {
				buildLogger = (BuildLogger) (Class.forName(loggerClassname).newInstance());
			}
			catch (ClassCastException e) {
				String message = MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.{0}_which_was_specified_to_perform_logging_is_not_an_instance_of_org.apache.tools.ant.BuildLogger._2"), new Object[] { //$NON-NLS-1$
						loggerClassname });
				logMessage(null, message, Project.MSG_ERR);
				throw new BuildException(message, e);
			}
			catch (Exception e) {
				String message = MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Unable_to_instantiate_logger__{0}_6"), new Object[] { //$NON-NLS-1$
						loggerClassname });
				logMessage(null, message, Project.MSG_ERR);
				throw new BuildException(message, e);
			}
		}

		if (buildLogger != null) {
			buildLogger.setMessageOutputLevel(messageOutputLevel);
			buildLogger.setOutputPrintStream(out);
			buildLogger.setErrorPrintStream(err);
			buildLogger.setEmacsMode(emacsMode);
			if (buildLogger instanceof RemoteAntBuildLogger) {
				((RemoteAntBuildLogger) buildLogger).configure(userProperties);
			}
		}

		return buildLogger;
	}

	/**
	 * Project.fireBuildStarted is protected in Ant earlier than 1.5.*. Provides backwards compatibility with old Ant installs.
	 */
	private void fireBuildStarted(Project project) {
		if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
			BuildEvent event = new BuildEvent(project);
			for (Iterator<BuildListener> iterator = project.getBuildListeners().iterator(); iterator.hasNext();) {
				BuildListener listener = iterator.next();
				listener.buildStarted(event);
			}
		} else {
			project.fireBuildStarted();
		}
	}

	private void fireBuildFinished(Project project, Throwable error) {
		if (error == null && scriptExecuted) {
			logMessage(project, RemoteAntMessages.getString("InternalAntRunner.BUILD_SUCCESSFUL_1"), messageOutputLevel); //$NON-NLS-1$
		}
		if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
			BuildEvent event = new BuildEvent(project);
			event.setException(error);
			Iterator<BuildListener> iter = project.getBuildListeners().iterator();
			while (iter.hasNext()) {
				BuildListener listener = iter.next();
				listener.buildFinished(event);
			}
		} else {
			project.fireBuildFinished(error);
		}
	}

	private void logMessage(Project project, String message, int priority) {
		if (project != null) {
			project.log(message, priority);
		}
	}

	/**
	 * Sets the buildFileLocation.
	 * 
	 * @param buildFileLocation
	 *            the file system location of the build file
	 */
	private void setBuildFileLocation(String buildFileLocation) {
		this.buildFileLocation = buildFileLocation;
		if (getCurrentProject() != null) {
			getCurrentProject().setUserProperty("ant.file", buildFileLocation); //$NON-NLS-1$
		}
	}

	private String getBuildFileLocation() {
		if (buildFileLocation == null) {
			buildFileLocation = new File("build.xml").getAbsolutePath(); //$NON-NLS-1$
		}
		return buildFileLocation;
	}

	/**
	 * Sets the message output level. Use -1 for none.
	 * 
	 * @param level
	 *            The message output level
	 */
	private void setMessageOutputLevel(int level) {
		messageOutputLevel = level;
		if (buildLogger != null) {
			buildLogger.setMessageOutputLevel(level);
		}
	}

	/**
	 * @return a String representation of the Ant version number as specified in the version.txt file
	 */
	private String getAntVersionNumber() throws BuildException {
		if (antVersionNumber == null) {
			try {
				InputStream in = Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt");//$NON-NLS-1$
				Properties props = new Properties();
				props.load(in);
				String versionNumber = props.getProperty("VERSION"); //$NON-NLS-1$
				antVersionNumber = versionNumber;
			}
			catch (IOException ioe) {
				throw new BuildException(MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Could_not_load_the_version_information._{0}_9"), new Object[] { //$NON-NLS-1$
						ioe.getMessage() }), ioe);
			}
			catch (NullPointerException npe) {
				throw new BuildException(RemoteAntMessages.getString("InternalAntRunner.Could_not_load_the_version_information._10"), npe); //$NON-NLS-1$
			}
		}
		return antVersionNumber;
	}

	/**
	 * Returns whether the given version is compatible with the current Ant version. A version is compatible if it is less than or equal to the
	 * current version.
	 */
	private boolean isVersionCompatible(String comparison) {
		String version = getAntVersionNumber();
		Version osgiVersion = new Version(version);
		Version osgiComparison = new Version(comparison);
		return osgiVersion.compareTo(osgiComparison) >= 0;
	}

	/**
	 * Copy of org.osgi.framework.Version.
	 * <p>
	 * We can't know how Ant version numbers will evolve in the future, but the OSGi version number format looks like a good bet.
	 */
	private static class Version {
		private final int major;
		private final int minor;
		private final int micro;
		private final String qualifier;
		private static final String SEPARATOR = "."; //$NON-NLS-1$

		public int compareTo(Version other) {
			if (other == this) { // quick test
				return 0;
			}

			int result = major - other.major;
			if (result != 0) {
				return result;
			}

			result = minor - other.minor;
			if (result != 0) {
				return result;
			}

			result = micro - other.micro;
			if (result != 0) {
				return result;
			}

			return qualifier.compareTo(other.qualifier);
		}

		public Version(String version) {
			int maj = 0;
			int min = 0;
			int mic = 0;
			String qual = ""; //$NON-NLS-1$

			try {
				StringTokenizer st = new StringTokenizer(version, SEPARATOR, true);
				maj = parseInt(st.nextToken(), version);

				if (st.hasMoreTokens()) { // minor
					st.nextToken(); // consume delimiter
					min = parseInt(st.nextToken(), version);

					if (st.hasMoreTokens()) { // micro
						st.nextToken(); // consume delimiter
						mic = parseInt(st.nextToken(), version);

						if (st.hasMoreTokens()) { // qualifier separator
							st.nextToken(); // consume delimiter
							qual = st.nextToken(""); // remaining string //$NON-NLS-1$

							if (st.hasMoreTokens()) { // fail safe
								throw new IllegalArgumentException("invalid version \"" + version + "\": invalid format"); //$NON-NLS-1$ //$NON-NLS-2$
							}
						}
					}
				}
			}
			catch (NoSuchElementException e) {
				IllegalArgumentException iae = new IllegalArgumentException("invalid version \"" + version + "\": invalid format");//$NON-NLS-1$ //$NON-NLS-2$
				iae.initCause(e);
				throw iae;
			}

			major = maj;
			minor = min;
			micro = mic;
			qualifier = qual;
			// validate();
		}

		private int parseInt(String value, String version) {
			try {
				return Integer.parseInt(value);
			}
			catch (NumberFormatException e) {
				IllegalArgumentException iae = new IllegalArgumentException("invalid version \"" + version + "\": non-numeric \"" + value + "\""); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
				iae.initCause(e);
				throw iae;
			}
		}
	}

	@SuppressWarnings("unused")
	private boolean preprocessCommandLine(List<String> commands) {

		String arg = getArgument(commands, "-listener"); //$NON-NLS-1$
		while (arg != null) {
			if (arg.length() == 0) {
				throw new BuildException(RemoteAntMessages.getString("InternalAntRunner.You_must_specify_a_classname_when_using_the_-listener_argument_1")); //$NON-NLS-1$
			}
			if (buildListeners == null) {
				buildListeners = new ArrayList<String>(1);
			}
			buildListeners.add(arg);
			arg = getArgument(commands, "-listener"); //$NON-NLS-1$
		}

		arg = getArgument(commands, "-logger"); //$NON-NLS-1$
		if (arg != null) {
			// allow empty string to mean no logger
			loggerClassname = arg;
		}
		arg = getArgument(commands, "-logger"); //$NON-NLS-1$
		if (arg != null) {
			throw new BuildException(RemoteAntMessages.getString("InternalAntRunner.Only_one_logger_class_may_be_specified_1")); //$NON-NLS-1$
		}

		arg = getArgument(commands, "-inputhandler"); //$NON-NLS-1$
		if (arg != null) {
			if (arg.length() == 0) {
				throw new BuildException(RemoteAntMessages.getString("InternalAntRunner.You_must_specify_a_classname_when_using_the_-inputhandler_argument_1")); //$NON-NLS-1$
			}
			inputHandlerClassname = arg;
		}
		arg = getArgument(commands, "-inputhandler"); //$NON-NLS-1$
		if (arg != null) {
			throw new BuildException(RemoteAntMessages.getString("InternalAntRunner.Only_one_input_handler_class_may_be_specified._2")); //$NON-NLS-1$
		}
		return true;
	}

	/*
	 * Looks for interesting command line arguments. Returns whether it is OK to run the script.
	 */
	private boolean processCommandLine(List<String> commands) {

		if (commands.remove("-help") || commands.remove("-h")) { //$NON-NLS-1$ //$NON-NLS-2$
			printUsage();
			return false;
		}

		if (commands.remove("-version")) { //$NON-NLS-1$
			printVersion();
			return false;
		}

		if (commands.remove("-verbose") || commands.remove("-v")) { //$NON-NLS-1$ //$NON-NLS-2$
			printVersion();
			setMessageOutputLevel(Project.MSG_VERBOSE);
		}

		if (commands.remove("-debug") || commands.remove("-d")) { //$NON-NLS-1$ //$NON-NLS-2$
			printVersion();
			setMessageOutputLevel(Project.MSG_DEBUG);
		}

		if (commands.remove("-quiet") || commands.remove("-q")) { //$NON-NLS-1$ //$NON-NLS-2$
			setMessageOutputLevel(Project.MSG_WARN);
		}

		if (commands.remove("-emacs") || commands.remove("-e")) { //$NON-NLS-1$ //$NON-NLS-2$
			emacsMode = true;
			if (buildLogger != null) {
				buildLogger.setEmacsMode(true);
			}
		}

		if (commands.remove("-diagnostics")) { //$NON-NLS-1$
			if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
				throw new BuildException(RemoteAntMessages.getString("InternalAntRunner.The_diagnositics_options_is_an_Ant_1.5.*_feature._Please_update_your_Ant_classpath_to_include_an_Ant_version_greater_than_this._4")); //$NON-NLS-1$
			}
			try {
				Diagnostics.doReport(System.out);
			}
			catch (NullPointerException e) {
				logMessage(getCurrentProject(), RemoteAntMessages.getString("InternalAntRunner.ANT_HOME_must_be_set_to_use_Ant_diagnostics_2"), Project.MSG_ERR); //$NON-NLS-1$
			}
			return false;
		}

		String arg = getArgument(commands, "-logfile"); //$NON-NLS-1$
		if (arg == null) {
			arg = getArgument(commands, "-l"); //$NON-NLS-1$
		}
		if (arg != null) {
			if (arg.length() == 0) {
				String message = RemoteAntMessages.getString("InternalAntRunner.You_must_specify_a_log_file_when_using_the_-log_argument_3"); //$NON-NLS-1$
				logMessage(currentProject, message, Project.MSG_ERR);
				throw new BuildException(message);
			}
			try {
				createLogFile(arg);
			}
			catch (IOException e) {
				// just log message and ignore exception
				logMessage(getCurrentProject(), MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Could_not_write_to_the_specified_log_file__{0}._Make_sure_the_path_exists_and_you_have_write_permissions._2"), new Object[] { //$NON-NLS-1$
						arg }), Project.MSG_ERR);
				return false;
			}

		}

		arg = getArgument(commands, "-buildfile"); //$NON-NLS-1$
		if (arg == null) {
			arg = getArgument(commands, "-file"); //$NON-NLS-1$
			if (arg == null) {
				arg = getArgument(commands, "-f"); //$NON-NLS-1$
			}
		}

		if (arg != null) {
			if (arg.length() == 0) {
				String message = RemoteAntMessages.getString("InternalAntRunner.You_must_specify_a_buildfile_when_using_the_-buildfile_argument_4"); //$NON-NLS-1$
				logMessage(currentProject, message, Project.MSG_ERR);
				throw new BuildException(message);
			}
			setBuildFileLocation(arg);
		}

		if (isVersionCompatible("1.6")) { //$NON-NLS-1$
			if (commands.remove("-k") || commands.remove("-keep-going")) { //$NON-NLS-1$ //$NON-NLS-2$
				keepGoing = true;
			}
			if (commands.remove("-noinput")) { //$NON-NLS-1$
				allowInput = false;
			}
			arg = getArgument(commands, "-lib"); //$NON-NLS-1$
			if (arg != null) {
				logMessage(currentProject, RemoteAntMessages.getString("InternalAntRunner.157"), Project.MSG_ERR); //$NON-NLS-1$
				return false;
			}
		}

		arg = getArgument(commands, "-find"); //$NON-NLS-1$
		if (arg == null) {
			arg = getArgument(commands, "-s"); //$NON-NLS-1$
		}
		if (arg != null) {
			logMessage(currentProject, RemoteAntMessages.getString("InternalAntRunner.-find_not_supported"), Project.MSG_ERR); //$NON-NLS-1$
			return false;
		}

		processTasksAndTypes(commands);

		if (!commands.isEmpty()) {
			processUnrecognizedCommands(commands);
		}

		if (!commands.isEmpty()) {
			processTargets(commands);
		}

		return true;
	}

	@SuppressWarnings("unused")
	private void processTasksAndTypes(List<String> commands) {
		String arg = getArgument(commands, "-eclipseTask"); //$NON-NLS-1$
		while (arg != null) {
			if (eclipseSpecifiedTasks == null) {
				eclipseSpecifiedTasks = new HashMap<String, String>();
			}
			int index = arg.indexOf(',');
			if (index != -1) {
				String name = arg.substring(0, index);
				String className = arg.substring(index + 1);
				eclipseSpecifiedTasks.put(name, className);
			}
			arg = getArgument(commands, "-eclipseTask"); //$NON-NLS-1$
		}

		arg = getArgument(commands, "-eclipseType"); //$NON-NLS-1$
		while (arg != null) {
			if (eclipseSpecifiedTypes == null) {
				eclipseSpecifiedTypes = new HashMap<String, String>();
			}
			int index = arg.indexOf(',');
			if (index != -1) {
				String name = arg.substring(0, index);
				String className = arg.substring(index + 1);
				eclipseSpecifiedTypes.put(name, className);
			}
			arg = getArgument(commands, "-eclipseType"); //$NON-NLS-1$
		}
	}

	/*
	 * Checks for unrecognized arguments on the command line. Since there is no syntactic way to distingush between ant -foo target1 target2 ant -foo
	 * fooarg target we remove everything up to the last argument that begins with a '-'. In the latter case, above, that means that there will be an
	 * extra target, 'fooarg', left lying around.
	 */
	private void processUnrecognizedCommands(List<String> commands) {
		int p = -1;

		// find the last arg that begins with '-'
		for (int i = commands.size() - 1; i >= 0; i--) {
			if (commands.get(0).startsWith("-")) { //$NON-NLS-1$
				p = i;
				break;
			}
		}
		if (p < 0) {
			return;
		}

		// remove everything preceding that last '-arg'
		String s = IAntCoreConstants.EMPTY_STRING;
		for (int i = 0; i <= p; i++) {
			s += " " + (commands.get(0)); //$NON-NLS-1$
			commands.remove(0);
		}

		// warn of ignored commands
		String message = MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Unknown_argument__{0}_2"), new Object[] { //$NON-NLS-1$
				s.substring(1) });
		logMessage(currentProject, message, Project.MSG_WARN);
	}

	/*
	 * Checks for targets specified at the command line.
	 */
	@SuppressWarnings("unused")
	private void processTargets(List<String> commands) {
		if (targets == null) {
			targets = new Vector<String>(commands.size());
		}
		for (String string : commands) {
			targets.add(string);
		}
	}

	/*
	 * Creates the log file with the name specified by the user. If the fileName is not absolute, the file will be created in the working directory if
	 * specified or in the same directory as the location of the build file.
	 */
	private void createLogFile(String fileName) throws FileNotFoundException, IOException {
		File logFile = getFileRelativeToBaseDir(fileName);

		// this stream is closed in the finally block of run(list)
		out = new PrintStream(new FileOutputStream(logFile));
		err = out;
		logMessage(getCurrentProject(), MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Using_{0}_file_as_build_log._1"), new Object[] { //$NON-NLS-1$
				logFile.getCanonicalPath() }), Project.MSG_INFO);
		if (buildLogger != null) {
			buildLogger.setErrorPrintStream(err);
			buildLogger.setOutputPrintStream(out);
		}
	}

	private File getFileRelativeToBaseDir(String fileName) {
		File parentFile = null;

		String base = getCurrentProject().getUserProperty("basedir"); //$NON-NLS-1$
		if (base != null) {
			parentFile = new File(base);
		} else {
			// relative to the build file location
			parentFile = new File(getBuildFileLocation()).getParentFile();
		}

		// remain backwards compatible for older Ant usage
		return FileUtils.getFileUtils().resolveFile(parentFile, fileName);
	}

	/*
	 * Processes cmd line properties and adds the user properties Any user properties that have been explicitly set are set as well. Ensures that -D
	 * properties take precedence.
	 */
	private boolean processProperties(List<String> commands) {
		boolean exceptionToBeThrown = false;
		// MULTIPLE property files are allowed
		String arg = getArgument(commands, "-propertyfile"); //$NON-NLS-1$
		while (arg != null) {
			if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
				fEarlyErrorMessage = RemoteAntMessages.getString("InternalAntRunner.Specifying_property_files_is_a_Ant_1.5.*_feature._Please_update_your_Ant_classpath._6"); //$NON-NLS-1$
				break;
			}
			if (arg.length() == 0) {
				fEarlyErrorMessage = RemoteAntMessages.getString("InternalAntRunner.You_must_specify_a_property_filename_when_using_the_-propertyfile_argument_3"); //$NON-NLS-1$
				exceptionToBeThrown = true;
				break;
			}

			propertyFiles.add(arg);
			arg = getArgument(commands, "-propertyfile"); //$NON-NLS-1$
		}

		if (propertyFiles != null && !propertyFiles.isEmpty()) {
			loadPropertyFiles();
		}

		if (commands != null) {
			processMinusDProperties(commands);
		}
		return exceptionToBeThrown;
	}

	@SuppressWarnings("unused")
	private void processMinusDProperties(List<String> commands) {
		String[] args = commands.toArray(new String[commands.size()]);
		for (int i = 0; i < args.length; i++) {
			String arg = args[i];
			if (arg.startsWith("-D")) { //$NON-NLS-1$
				String name = arg.substring(2, arg.length());
				String value = null;
				int posEq = name.indexOf("="); //$NON-NLS-1$
				if (posEq == 0) {
					value = name.substring(1);
					name = IAntCoreConstants.EMPTY_STRING;
				} else if (posEq > 0 && posEq != name.length() - 1) {
					value = name.substring(posEq + 1).trim();
					name = name.substring(0, posEq);
				}

				if (value == null) {
					// the user has specified something like "-Debug"
					continue;
				}
				if (userProperties == null) {
					userProperties = new HashMap<String, String>();
				}
				userProperties.put(name, value);
				commands.remove(args[i]);
			}
		}
	}

	private void setProperties(Project project) {
		setBuiltInProperties(project);
		if (userProperties != null) {
			for (Entry<String, String> entry : userProperties.entrySet()) {
				if (entry.getValue() != null)
					project.setUserProperty(entry.getKey(), entry.getValue());
			}
		}
	}

	private void setBuiltInProperties(Project project) {
		project.setUserProperty("ant.file", getBuildFileLocation()); //$NON-NLS-1$
		project.setUserProperty("ant.version", Main.getAntVersion()); //$NON-NLS-1$
	}

	/*
	 * Print the project description, if any
	 */
	private void printHelp(Project project) {
		if (project.getDescription() != null) {
			logMessage(project, project.getDescription(), Project.MSG_INFO);
		}
		printTargets(project);
	}

	/*
	 * Logs a message with the client indicating the version of <b>Ant</b> that this class fronts.
	 */
	private void printVersion() {
		logMessage(getCurrentProject(), Main.getAntVersion(), Project.MSG_INFO);
	}

	/*
	 * Logs a message with the client outlining the usage of <b>Ant</b>.
	 */
	private void printUsage() {
		String lSep = System.getProperty("line.separator"); //$NON-NLS-1$
		StringBuffer msg = new StringBuffer();
		msg.append("ant ["); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.options_13")); //$NON-NLS-1$
		msg.append("] ["); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.target_15")); //$NON-NLS-1$
		msg.append(" ["); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.target_15")); //$NON-NLS-1$
		msg.append("2 ["); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.target_15")); //$NON-NLS-1$
		msg.append("3] ...]]"); //$NON-NLS-1$
		msg.append(lSep);
		msg.append(RemoteAntMessages.getString("InternalAntRunner.Options___21")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-help, -h\t\t\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.print_this_message_23")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-projecthelp, -p\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.print_project_help_information_25")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-version\t\t\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.print_the_version_information_and_exit_27")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-diagnostics\t\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.12")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append(RemoteAntMessages.getString("InternalAntRunner.13")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-quiet, -q\t\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.be_extra_quiet_29")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-verbose, -v\t\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.be_extra_verbose_31")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-debug, -d\t\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.print_debugging_information_33")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-emacs, -e\t\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.produce_logging_information_without_adornments_35")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-logfile\t<file>\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.use_given_file_for_log_37")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t\t-l\t<file>"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.1")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-logger <classname>\t\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.the_class_which_is_to_perform_logging_39")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-listener <classname>\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.add_an_instance_of_class_as_a_project_listener_41")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-noinput\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.158")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-buildfile\t<file>\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.use_given_buildfile_43")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t\t-file\t<file>"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.1")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t\t-f\t\t<file>"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.1")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-D<property>=<value>\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.use_value_for_given_property_45")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-keep-going, -k"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.159")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append(RemoteAntMessages.getString("InternalAntRunner.160")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-propertyfile <name>\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.19")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append(RemoteAntMessages.getString("InternalAntRunner.20")); //$NON-NLS-1$
		msg.append(lSep);
		msg.append("\t-inputhandler <class>\t"); //$NON-NLS-1$
		msg.append(RemoteAntMessages.getString("InternalAntRunner.22")); //$NON-NLS-1$
		msg.append(lSep);

		logMessage(getCurrentProject(), msg.toString(), Project.MSG_INFO);
	}

	/*
	 * From a command line list, return the argument for the given parameter. The parameter and its argument are removed from the list.
	 * 
	 * @return <code>null</code> if the parameter is not found or an empty String if no arguments are found
	 */
	private String getArgument(List<String> commands, String param) {
		if (commands == null) {
			return null;
		}
		int index = commands.indexOf(param);
		if (index == -1) {
			return null;
		}
		commands.remove(index);
		if (index == commands.size()) {// if this is the last command
			return IAntCoreConstants.EMPTY_STRING;
		}

		String command = commands.get(index);
		if (command.startsWith("-")) { // new parameter //$NON-NLS-1$
			return IAntCoreConstants.EMPTY_STRING;
		}

		commands.remove(index);
		return command;
	}

	private Project getCurrentProject() {
		return currentProject;
	}

	private void setCurrentProject(Project currentProject) {
		this.currentProject = currentProject;
	}

	/**
	 * Load all properties from the files specified by -propertyfile.
	 */
	@SuppressWarnings("unused")
	private void loadPropertyFiles() {
		for (String filename : propertyFiles) {
			File file = getFileRelativeToBaseDir(filename);
			Properties props = new Properties();
			try {
				FileInputStream fis = new FileInputStream(file);
				props.load(fis);
			}
			catch (IOException e) {
				fEarlyErrorMessage = MessageFormat.format(RemoteAntMessages.getString("InternalAntRunner.Could_not_load_property_file_{0}__{1}_4"), new Object[] { //$NON-NLS-1$
						filename, e.getMessage() });
			}
			if (userProperties == null) {
				userProperties = new HashMap<String, String>();
			}
			Enumeration<?> propertyNames = props.propertyNames();
			while (propertyNames.hasMoreElements()) {
				String name = (String) propertyNames.nextElement();
				// most specific to global
				// do not overwrite specific with a global property
				if (userProperties.get(name) == null) {
					userProperties.put(name, props.getProperty(name));
				}
			}
		}
	}

	/*
	 * Creates the InputHandler and adds it to the project.
	 * 
	 * @exception BuildException if a specified InputHandler implementation could not be loaded.
	 */
	private void addInputHandler(Project project) {
		if (!isVersionCompatible("1.5")) { //$NON-NLS-1$
			return;
		}
		InputHandlerSetter setter = new InputHandlerSetter();
		setter.setInputHandler(project, inputHandlerClassname);
	}
}
