/*******************************************************************************
 * Copyright (c) 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
 * 
 *      
 *******************************************************************************/
package org.eclipse.europa.tools.versionchecker;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.core.runtime.IPlatformRunnable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.update.configurator.ConfiguratorUtils;
import org.eclipse.update.configurator.IPlatformConfiguration;
import org.eclipse.update.configurator.IPlatformConfiguration.IFeatureEntry;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * 
 * A simple, unsupported, little-tested utility to check version numbers of
 * currently installed plugins against a reference list that was previously
 * prepared by running this utility on some earlier installed stack.
 * 
 */
public class VersionLister implements IPlatformRunnable {

	private static final String REFERENCE_VERSIONING_DATA_XML = "referenceVersioningData.xml";

	private static final String VERSION_CHECKER_BUNDLE_NAME = "org.eclipse.europa.tools.versionchecker";

	private static final String EOL = System.getProperty("line.separator");

	private static final String[] alwaysExclude = new String[]{"org.eclipse.releng.tools", "org.tigris.mm.ui", "org.eclipse.core.resources.spysupport", "com.yourkit.profiler", "org.eclipse.core.tools.resources", "org.eclipse.core.tools", "org.eclipse.europa.tools.versionchecker"};
	private static final String[] alwaysExcludeFeatures = new String[]{"org.eclipse.releng.tools", "org.eclipse.test"};

	private static final int HELP = 0;
	private static final String HELP_ARG = "-help";

	private static final int LIST_TO_CONSOLE = 1;
	private static final String LIST_TO_CONSOLE_ARG = "-listToReferenceFile";

	private static final int TEST_TO_REFERENCE = 2;
	private static final String TEST_TO_REFERENCE_ARG = "-testToReference";

	private static final int MAJOR = 0;
	private static final int MINOR = 1;
	private static final int SERVICE = 2;
	private static final int QUALIFIER = 3;

	private static final String BUNDLE_DATA = "bundleData";

	private static final String FEATURE_DATA = "featureData";

	private static final int ERROR_BASE_CODE = 90000;
	private static final int ERROR_BUNDLE_DECREASE = 0x0001;
	private static final int ERROR_FEATURE_DECREASE = 0x0010;
	private static final int ERROR_EXCEPTION_OCCURRED = 0x0100;
	private static final Object OK_EXIT = IPlatformRunnable.EXIT_OK;

	public VersionLister() {
	}

	public static void main(String[] args) {
		// for quick tests, only
		VersionLister versionLister = new VersionLister();
		versionLister.clean("M-testing-123");
	}

	public Object run(Object o) throws Exception {

		int exitResult = ERROR_BASE_CODE;
		String args[] = null;
		if (o instanceof String[]) {
			args = (String[]) o;
		}
		else {
			doPrintHelp();
			return OK_EXIT;
		}

		printArgs(args);
		// printProperties();

		if (args == null) {
			exitResult = exitResult | doPrintHelp();
		}
		else if ((args != null) && (args.length == 0)) {
			exitResult = exitResult | doPrintHelp();
		}
		else {
			boolean someCommandExecuted = false;
			for (int i = 0; i < args.length; i++) {
				String arg = args[i].trim();
				System.out.println("command: " + arg);
				switch (getCommand(arg)) {
					case LIST_TO_CONSOLE : {
						// System.out.println(" executing list to console");
						String xmlId = null;
						int idPos = i + 1;
						if (idPos < args.length) {
							String possibleId = args[idPos];
							// sanity check just not another command
							if (!possibleId.startsWith("-")) {
								xmlId = possibleId;
							}
							else {
								xmlId = getDefaultID();
							}
						}
						else {
							xmlId = getDefaultID();
						}

						exitResult = exitResult | doListCurrentToConsole(xmlId);

						someCommandExecuted = true;
						break;
					}
					case TEST_TO_REFERENCE : {
						// System.out.println(" executing test to reference");
						String referenceId = "WTPSDK";
						String referenceFilename = REFERENCE_VERSIONING_DATA_XML;
						int idPos = i + 1;
						if (idPos < args.length) {
							String possibleId = args[idPos];
							// sanity check just not another command
							if (!possibleId.startsWith("-")) {
								referenceId = possibleId;
							}
						}
						idPos++;
						if (idPos < args.length) {
							String possibleFilename = args[idPos];
							// sanity check just not another command
							if (!possibleFilename.startsWith("-")) {
								referenceFilename = possibleFilename;
							}
						}


						String buildLabel = System.getProperty("buildLabel");
						if (buildLabel != null && buildLabel.length() != 0) {
							// leave buildLabel as found, for here (may adjust
							// later)
						}
						else {
							buildLabel = "NoBuildLabel";
						}
						someCommandExecuted = true;
						exitResult = exitResult | doTestToReference(referenceId, referenceFilename, buildLabel);

						// minor error in arguments
						if (!someCommandExecuted) {
							exitResult = exitResult | doPrintHelp();
						}
						break;
					}
					case HELP : {
						exitResult = exitResult | doPrintHelp();
						someCommandExecuted = true;
						break;
					}
					default : {
						/* do nothing, since in a loop */
						break;
					}
				}
			}
			if (!someCommandExecuted) {
				exitResult = exitResult | doPrintHelp();
			}
		}
		Object result = IPlatformRunnable.EXIT_OK;
		if (exitResult > ERROR_BASE_CODE) {
			result = new Integer(exitResult);
		}
		return result;
	}

	void printArgs(String[] args) {
		System.out.println("\t Program Arguments: ");
		for (int i = 0; i < args.length; i++) {
			System.out.println("\t\t" + args[i]);
		}

	}

	void printProperties() {
		Properties properties = System.getProperties();
		properties.list(System.out);
	}

	private int doTestToReference(String id, String referenceFileName, String currentId) {
		int exit_code = ERROR_BASE_CODE;


		try {
			Map refMap = getReferenceBundleMap(id, referenceFileName);
			// will be null if no ID found.
			if (refMap != null) {
				String outputFileName = "versioningReport";
				File outfile = createOutputFile(outputFileName);
				Writer reportWriter = new FileWriter(outfile);
				reportWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL);

				reportWriter.write("<versioningReport>" + EOL);
				reportWriter.write("<versioningReportData id=\"" + id + "\"" + " current=\"" + clean(currentId) + "\"" + ">" + EOL);

				Map currMap = makeBundleMap();
				String checkingType = "bundle";
				int bundle_return = _compareReferenceAndCurrent(currMap, refMap, checkingType, ERROR_BUNDLE_DECREASE, reportWriter);
				exit_code = exit_code | bundle_return;

				refMap = getReferenceFeatureMap(id, referenceFileName);
				currMap = makeFeatureMap();
				checkingType = "feature";
				int feature_return = _compareReferenceAndCurrent(currMap, refMap, checkingType, ERROR_FEATURE_DECREASE, reportWriter);
				exit_code = exit_code | feature_return;

				reportWriter.write("</versioningReportData>" + EOL);
				reportWriter.write("</versioningReport>" + EOL);

				System.out.println("Note: versioning report written to " + outfile.getAbsolutePath());
				reportWriter.close();


			}
			else {
				System.out.println("No reference ID found named " + id);
			}
		}
		catch (ParserConfigurationException e) {
			e.printStackTrace();
			exit_code = exit_code & ERROR_EXCEPTION_OCCURRED;
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
			exit_code = exit_code & ERROR_EXCEPTION_OCCURRED;
		}
		catch (SAXException e) {
			e.printStackTrace();
			exit_code = exit_code & ERROR_EXCEPTION_OCCURRED;
		}

		catch (IOException e) {
			e.printStackTrace();
			exit_code = exit_code & ERROR_EXCEPTION_OCCURRED;
		}

		return exit_code;
	}

	private File createOutputFile(String outputFileName) throws IOException {
		File outputDirectory = null;
		String outputDirName = System.getProperty("buildDirectory");
		String dirLabel = System.getProperty("buildLabel");
		if (outputDirName != null && outputDirName.length() > 0) {
			if (dirLabel != null && dirLabel.length() > 0) {
				outputDirectory = new File(outputDirName + "/" + dirLabel);
			}
		}
		String localOutputFilename = null;
		String outputFileNameSuffix = System.getProperty("buildLabel");
		if (outputFileNameSuffix != null) {
			localOutputFilename = outputFileName + "_" + clean(outputFileNameSuffix) + ".xml";
		}
		else {
			localOutputFilename = outputFileName + ".xml";
		}
		File outfile = new File(outputDirectory, localOutputFilename);

		return outfile;
	}

	private int _compareReferenceAndCurrent(Map currMap, Map refMap, String checkingType, int errorExitCode, Writer reportWriter) throws IOException {

		String reportExtraInCurrentResult = "extraInCurrent";
		String reportExtraInReferenceResult = "extraInReference";


		// return zero for success
		int result = 0;
		List extrasInCurrent = compareKeys(currMap, refMap);
		if (extrasInCurrent.size() > 0) {
			Object[] extras = extrasInCurrent.toArray();
			for (int i = 0; i < extras.length; i++) {
				String key = (String) extras[i];
				Version refVersion = (Version) refMap.get(key);
				_printExtra(key, refVersion, checkingType, reportExtraInCurrentResult, reportWriter);
			}
		}
		List extrasInReferences = compareKeys(refMap, currMap);
		if (extrasInReferences.size() > 0) {
			Object[] extras = extrasInReferences.toArray();
			for (int i = 0; i < extras.length; i++) {
				String key = (String) extras[i];
				Version curVersion = (Version) currMap.get(key);
				_printExtra(key, curVersion, checkingType, reportExtraInReferenceResult, reportWriter);
			}
		}

		// now for the version compares -- first, look for errors
		Iterator currentIterator = currMap.keySet().iterator();
		while (currentIterator.hasNext()) {
			String key = (String) currentIterator.next();
			Version refVersion = (Version) refMap.get(key);
			Version curVersion = (Version) currMap.get(key);
			if ((refVersion != null) && (curVersion != null)) {
				int comp = refVersion.compareTo(curVersion);
				if (comp > 0) {
					_printError(key, refVersion, curVersion, checkingType, reportWriter);
					result = errorExitCode;
				}
			}
		}

		// now for the version compares -- first for MAJOR changes
		Iterator currentIterator2 = currMap.keySet().iterator();
		while (currentIterator2.hasNext()) {

			checkDifference(refMap, currMap, currentIterator2, MAJOR, checkingType, reportWriter);
		}
		Iterator currentIterator2a = currMap.keySet().iterator();
		while (currentIterator2a.hasNext()) {

			checkDifference(refMap, currMap, currentIterator2a, MINOR, checkingType, reportWriter);
		}
		Iterator currentIterator2b = currMap.keySet().iterator();
		while (currentIterator2b.hasNext()) {

			checkDifference(refMap, currMap, currentIterator2b, SERVICE, checkingType, reportWriter);
		}
		Iterator currentIterator2c = currMap.keySet().iterator();
		while (currentIterator2c.hasNext()) {

			checkDifference(refMap, currMap, currentIterator2c, QUALIFIER, checkingType, reportWriter);
		}

		// just as well list unchanged ones for completeness!
		Iterator currentIterator3 = currMap.keySet().iterator();
		while (currentIterator3.hasNext()) {
			String key = (String) currentIterator3.next();
			Version refVersion = (Version) refMap.get(key);
			Version curVersion = (Version) currMap.get(key);
			if ((refVersion != null) && (curVersion != null)) {
				int comp = refVersion.compareTo(curVersion);
				if (comp == 0) {
					_printNoChange(key, refVersion, curVersion, checkingType, reportWriter);
				}
			}
		}

		return result;
	}

	private void checkDifference(Map refMap, Map currMap, Iterator iterator, int fieldToCheck, String checkingType, Writer reportWriter) throws IOException {
		String key = (String) iterator.next();
		Version refVersion = (Version) refMap.get(key);
		Version curVersion = (Version) currMap.get(key);
		if ((refVersion != null) && (curVersion != null)) {
			int comp = refVersion.compareTo(curVersion);
			if (comp < 0) {
				if (fieldToCheck == MAJOR) {
					if (refVersion.getMajor() < curVersion.getMajor()) {
						_printIncrease(key, refVersion, curVersion, "major", checkingType, reportWriter);
						// if found, remove so no need to have complicated
						// check for minor, service, etc.
						iterator.remove();
					}
				}
				else if (fieldToCheck == MINOR) {
					if (refVersion.getMinor() < curVersion.getMinor()) {
						_printIncrease(key, refVersion, curVersion, "minor", checkingType, reportWriter);
						// if found, remove so no need to have complicated
						// check for minor, service, etc.
						iterator.remove();
					}
				}
				else if (fieldToCheck == SERVICE) {
					if (refVersion.getMicro() < curVersion.getMicro()) {
						_printIncrease(key, refVersion, curVersion, "service", checkingType, reportWriter);
						// if found, remove so no need to have complicated
						// check for minor, service, etc.
						iterator.remove();
					}
				}
				else if (fieldToCheck == QUALIFIER) {
					if (refVersion.compareTo(curVersion) < 0) {
						_printIncrease(key, refVersion, curVersion, "qualifier", checkingType, reportWriter);
						// if found, remove so no need to have complicated
						// check for minor, service, etc.
						iterator.remove();
					}
				}
			}
		}
	}

	private void _printIncrease(String key, Version refVersion, Version curVersion, String field, String codePackageType, Writer reportWriter) throws IOException {
		String name = key.trim();
		String reportResult = "increase";
		reportWriter.write("<versioningCompare kind=\"" + reportResult + "\"" + " field=\"" + field + "\"" + " codePackageType=\"" + codePackageType + "\"" + ">" + EOL);
		reportWriter.write("\t" + "<entry>" + EOL + "\t\t" + name + EOL + "\t" + "</entry>" + EOL);
		reportWriter.write("\t" + "<reference>" + EOL + "\t\t" + refVersion + EOL + "\t" + "</reference>" + EOL);
		reportWriter.write("\t" + "<current>" + EOL + "\t\t" + curVersion + EOL + "\t" + "</current>" + EOL);
		reportWriter.write("</versioningCompare>" + EOL);
	}

	private void _printNoChange(String key, Version refVersion, Version curVersion, String codePackageType, Writer reportWriter) throws IOException {
		String name = key.trim();
		String reportResult = "noChange";
		reportWriter.write("<versioningCompare kind=\"" + reportResult + "\"" + " codePackageType=\"" + codePackageType + "\"" + ">" + EOL);
		reportWriter.write("\t" + "<entry>" + EOL + "\t\t" + name + EOL + "\t" + "</entry>" + EOL);
		reportWriter.write("\t" + "<reference>" + EOL + "\t\t" + refVersion + EOL + "\t" + "</reference>" + EOL);
		reportWriter.write("\t" + "<current>" + EOL + "\t\t" + curVersion + EOL + "\t" + "</current>" + EOL);
		reportWriter.write("</versioningCompare>" + EOL);
	}

	private void _printError(String key, Version refVersion, Version curVersion, String codePackageType, Writer reportWriter) throws IOException {
		String name = key.trim();
		String reportResult = "error";
		reportWriter.write("<versioningCompare kind=\"" + reportResult + "\" codePackageType=\"" + codePackageType + "\"" + ">" + EOL);
		reportWriter.write("\t" + "<entry>" + EOL + "\t\t" + name + EOL + "\t" + "</entry>" + EOL);
		reportWriter.write("\t" + "<reference>" + EOL + "\t\t" + refVersion + EOL + "\t" + "</reference>" + EOL);
		reportWriter.write("\t" + "<current>" + EOL + "\t\t" + curVersion + EOL + "\t" + "</current>" + EOL);
		reportWriter.write("</versioningCompare>" + EOL);
	}

	private void _printExtra(String key, Version version, String codePackageType, String reportResult, Writer reportWriter) throws IOException {
		String name = key.trim();
		reportWriter.write("<versioningCompare kind=\"" + reportResult + "\" codePackageType=\"" + codePackageType + "\"" + ">" + EOL);
		reportWriter.write("\t" + "<entry>" + EOL + "\t\t" + name + EOL + "\t" + "</entry>" + EOL);
		reportWriter.write("\t" + "<reference>" + EOL + "\t\t" + version + EOL + "\t" + "</reference>" + EOL);
		reportWriter.write("</versioningCompare>" + EOL);
	}

	private List compareKeys(Map baseMap, Map compareMap) {
		List extras = new ArrayList();

		Iterator iterator = compareMap.keySet().iterator();
		while (iterator.hasNext()) {
			String key = (String) iterator.next();
			if (!baseMap.containsKey(key)) {
				extras.add(key);
			}
		}
		return extras;
	}

	private Map getReferenceBundleMap(String id, String referenceFileName) throws FactoryConfigurationError, ParserConfigurationException, FileNotFoundException, SAXException, IOException {

		SortedMap refSortedMap = null;
		Document dom = getReferenceDataDOM(referenceFileName);

		Element refereneDataElement = dom.getElementById(id);
		if (refereneDataElement != null) {
			NodeList childNodes = refereneDataElement.getElementsByTagName(BUNDLE_DATA);
			Element bundleElement = (Element) childNodes.item(0);

			childNodes = bundleElement.getChildNodes();

			refSortedMap = new TreeMap();
			_extractEntryList(refSortedMap, childNodes);
		}
		return refSortedMap;
	}

	private Map getReferenceFeatureMap(String id, String referenceFileName) throws FactoryConfigurationError, ParserConfigurationException, FileNotFoundException, SAXException, IOException {

		Document dom = getReferenceDataDOM(referenceFileName);

		Element refereneDataElement = dom.getElementById(id);
		NodeList childNodes = refereneDataElement.getElementsByTagName(FEATURE_DATA);
		Element bundleElement = (Element) childNodes.item(0);

		childNodes = bundleElement.getChildNodes();

		SortedMap refSortedMap = new TreeMap();
		_extractEntryList(refSortedMap, childNodes);

		return refSortedMap;
	}

	private Document getReferenceDataDOM(String referenceFileName) throws ParserConfigurationException, IOException, SAXException {
		Document dom = null;
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		documentBuilderFactory.setValidating(true);
		documentBuilderFactory.setIgnoringElementContentWhitespace(true);
		documentBuilderFactory.setIgnoringComments(true);
		DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
		Bundle versionCheckerBundle = Platform.getBundle(VERSION_CHECKER_BUNDLE_NAME);
		URL referenceDataURL = versionCheckerBundle.getResource(referenceFileName);
		if (referenceDataURL != null) {
			InputStream inStream = referenceDataURL.openStream();
			InputSource is = new InputSource(inStream);
			documentBuilder.setEntityResolver(new ClassPathResolver());
			dom = documentBuilder.parse(is);
		}
		else {
			System.out.println("Program Error: Could not find reference file: " + referenceFileName);
		}
		return dom;
	}

	private void _extractEntryList(SortedMap refSortedMap, NodeList childNodes) {
		int nNodes = childNodes.getLength();


		for (int i = 0; i < nNodes; i++) {
			Element entry = (Element) childNodes.item(i);
			Node name = entry.getElementsByTagName("name").item(0);
			Node version = entry.getElementsByTagName("version").item(0);
			String bundleNmae = getTextContent(name);
			String versionString = getTextContent(version);

			refSortedMap.put(bundleNmae, new Version(versionString));
		}
	}

	/**
	 * A convenience method for DOM2, that should behave as
	 * node.getTextContent in DOM3.
	 * 
	 * @param node
	 * @return the string of the text node, or consequtive text nodes, that
	 *         are children of node. If there are no children, the empty
	 *         string is returned.
	 */
	private String getTextContent(Node node) {
		StringBuffer buffer = new StringBuffer();
		NodeList childNodes = node.getChildNodes();
		for (int i = 0; i < childNodes.getLength(); i++) {
			Node textNode = childNodes.item(i);
			if (textNode.getNodeType() == Node.TEXT_NODE) {
				buffer.append(textNode.getNodeValue());
			}
			else {
				// break out at first occurance of non text node, if any
				break;
			}
		}
		return buffer.toString();
	}

	private int doPrintHelp() {
		int exitCode = ERROR_BASE_CODE;
		System.out.println();
		System.out.println("\tto use VersionChecker, include one of the following commands: ");
		System.out.println("\t\t" + LIST_TO_CONSOLE_ARG);
		System.out.println("\t\t" + TEST_TO_REFERENCE_ARG + " refId " + "[referenceDataFilename]");
		System.out.println();

		return exitCode;


	}

	private int getCommand(String arg) {
		int result = -1;

		if (HELP_ARG.equalsIgnoreCase(arg)) {
			result = HELP;
		}
		else if (LIST_TO_CONSOLE_ARG.equalsIgnoreCase(arg)) {
			result = LIST_TO_CONSOLE;
		}
		else if (TEST_TO_REFERENCE_ARG.equalsIgnoreCase(arg)) {
			result = TEST_TO_REFERENCE;
		}

		return result;
	}


	private Map makeFeatureMap() {
		IPlatformConfiguration config = ConfiguratorUtils.getCurrentPlatformConfiguration();
		IFeatureEntry[] features = config.getConfiguredFeatureEntries();


		SortedMap sortedMap = new TreeMap();
		for (int i = 0; i < features.length; i++) {
			String name = features[i].getFeatureIdentifier();
			name = name.trim();
			String versionString = features[i].getFeatureVersion();
			Version version = new Version(versionString);
			if (!contains(name, alwaysExcludeFeatures)) {
				sortedMap.put(name, version);
			}
		}
		return sortedMap;
	}


	private int doListCurrentToConsole(String xmlId) throws IOException {

		int exitResult = ERROR_BASE_CODE;
		String outputFileName = "versioningReference";
		File outputFile = createOutputFile(outputFileName);
		Writer referenceWriter = new FileWriter(outputFile);

		// TODO: needs to really write UTF-8, or better, serialize DOM
		referenceWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL);

		referenceWriter.write("<versioningData>" + EOL);

		referenceWriter.write("<referenceData id=\"" + xmlId + "\">" + EOL);


		Map featureMap = makeFeatureMap();
		referenceWriter.write("<featureData>" + EOL);
		referenceWriter.write("<!-- Number of features: " + featureMap.size() + " -->" + EOL);
		referenceWriter.write(EOL);

		_producePrintedPairs(featureMap, referenceWriter);

		referenceWriter.write("</featureData>" + EOL);



		Map bundleMap = makeBundleMap();

		referenceWriter.write("<bundleData>" + EOL);
		referenceWriter.write("<!-- Number of bundles: " + bundleMap.size() + " -->" + EOL);

		referenceWriter.write(EOL);

		_producePrintedPairs(bundleMap, referenceWriter);

		referenceWriter.write("</bundleData>" + EOL);


		referenceWriter.write("</referenceData>" + EOL);
		referenceWriter.write("</versioningData>" + EOL);

		System.out.println("Note: versioning reference data written to " + outputFile.getAbsolutePath());
		referenceWriter.close();

		return exitResult;
	}

	/**
	 * @return
	 */
	private String getCurrentInstallPath() {
		Location installLocation = Platform.getInstallLocation();
		URL installLoc = installLocation.getURL();
		String installLocationString = "no install location!?";
		if (installLoc != null) {
			installLocationString = installLoc.getPath();
		}
		return installLocationString;
	}

	private String getDefaultID() {
		String defaultID = null;
		String buildLabel = System.getProperty("buildLabel");
		if (buildLabel != null && buildLabel.length() != 0) {
			defaultID = clean(buildLabel);
		}
		else {
			defaultID = getCurrentInstallPath();
		}
		return defaultID;
	}

	private void _producePrintedPairs(Map map, Writer referenceWriter) throws IOException {
		Set referenceKeySet = map.keySet();
		Iterator refIterator = referenceKeySet.iterator();
		while (refIterator.hasNext()) {
			String name = (String) refIterator.next();
			Version version = (Version) map.get(name);

			referenceWriter.write("<entry>" + EOL);
			referenceWriter.write("\t" + "<name>" + name + "</name>" + EOL);
			referenceWriter.write("\t" + "<version>" + version + "</version>" + EOL);
			referenceWriter.write("</entry>" + EOL);
		}
		return;
	}

	private Map makeBundleMap() {
		BundleDescription bundles[] = Platform.getPlatformAdmin().getState().getBundles();

		SortedMap sortedMap = new TreeMap();
		for (int i = 0; i < bundles.length; i++) {
			String bundleName = bundles[i].getName();
			Version bundleVersion = bundles[i].getVersion();
			bundleName = bundleName.trim();
			if (!contains(bundleName, alwaysExclude)) {
				sortedMap.put(bundleName, bundleVersion);
			}
		}
		return sortedMap;
	}

	private boolean contains(String needle, String[] haystack) {
		boolean result = false;

		for (int i = 0; i < haystack.length; i++) {
			if (needle.equals(haystack[i])) {
				result = true;
				break;
			}
		}
		return result;
	}

	/**
	 * This method is entirely to shorten the (old) long, redundant form of a build label, 
	 * such as M-M200612071701-200612071701 to it's equivilant short form
	 * such as M200612071701
	 * @param label
	 * @return
	 */
	private String clean(String label) {
		String result = label;

		String possibleResult = null;
		int hPos = label.indexOf('-');
		if (hPos > -1) {
			possibleResult = label.substring(hPos + 1);
			hPos = possibleResult.indexOf('-');
			if (hPos > -1) {
				possibleResult = possibleResult.substring(0, hPos);
				result = possibleResult;
			}
		}


		return result;
	}

}
