/*******************************************************************************
 *  Copyright (c) 2008, 2015 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 * 
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *     Ericsson AB - Ongoing development
 *     Red Hat, Inc. - Fragment support added. Bug 460967
 *******************************************************************************/
package org.eclipse.equinox.p2.tests.reconciler.dropins;

import java.io.*;
import java.net.*;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.p2.core.helpers.*;
import org.eclipse.equinox.internal.p2.engine.SimpleProfileRegistry;
import org.eclipse.equinox.internal.p2.engine.SurrogateProfileHandler;
import org.eclipse.equinox.internal.p2.jarprocessor.StreamProcessor;
import org.eclipse.equinox.internal.p2.update.*;
import org.eclipse.equinox.internal.p2.updatesite.Activator;
import org.eclipse.equinox.internal.simpleconfigurator.manipulator.SimpleConfiguratorManipulatorImpl;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.p2.tests.TestActivator;
import org.eclipse.equinox.simpleconfigurator.manipulator.SimpleConfiguratorManipulator;
import org.eclipse.osgi.service.datalocation.Location;
import org.osgi.framework.Bundle;

public class AbstractReconcilerTest extends AbstractProvisioningTest {
	public static final String VERIFIER_BUNDLE_ID = "org.eclipse.equinox.p2.tests.verifier";
	protected static File output;
	protected static Set toRemove = new HashSet();
	private static boolean initialized = false;
	private static Properties archiveAndRepositoryProperties = null;

	private String propertyToPlatformArchive;
	protected boolean debug = false;

	static {
		loadPlatformZipPropertiesFromFile();
	}

	/*
			 * Constructor for the class.
			 */
	public AbstractReconcilerTest(String name) {
		super(name);
	}

	public AbstractReconcilerTest(String name, String propertyToPlatformArchive) {
		super(name);
		this.propertyToPlatformArchive = propertyToPlatformArchive;
	}

	/*
	 * Set up the platform binary download and get it ready to run the tests.
	 * This method is not intended to be called by clients, it will be called
	 * automatically when the clients use a ReconcilerTestSuite. If the executable isn't
	 * found on the file-system after the call, then we fail.
	 */
	public void initialize() throws Exception {
		initialized = false;
		File file = getPlatformZip();
		output = getUniqueFolder();
		toRemove.add(output);
		// for now we will exec to un-tar archives to keep the executable bits
		if (file.getName().toLowerCase().endsWith(".zip")) {
			try {
				FileUtils.unzipFile(file, output);
			} catch (IOException e) {
				fail("0.99", e);
			}
		} else {
			untar("1.0", file);
		}
		File exe = new File(output, getExeFolder() + "eclipse.exe");
		if (!exe.exists()) {
			exe = new File(output, getExeFolder() + "eclipse");
			if (!exe.exists())
				fail("Executable file: " + exe.getAbsolutePath() + "(or .exe) not found after extracting: " + file.getAbsolutePath() + " to: " + output);
		}
		initialized = true;
	}

	public void assertInitialized() {
		assertTrue("Test suite not initialized, check log for previous errors.", initialized);
	}

	/*
	 * Run the given command.
	 */
	protected static int run(String message, String[] commandArray) {
		try {
			Process process = Runtime.getRuntime().exec(commandArray, null, output);
			StreamProcessor.start(process.getErrorStream(), StreamProcessor.STDERR, true);
			StreamProcessor.start(process.getInputStream(), StreamProcessor.STDOUT, true);
			process.waitFor();
			return process.exitValue();
		} catch (IOException e) {
			fail(message, e);
		} catch (InterruptedException e) {
			fail(message, e);
		}
		return -1;
	}

	protected static int run(String message, String[] commandArray, File outputFile) {
		PrintStream out = System.out;
		PrintStream err = System.err;
		PrintStream fileStream = null;
		try {
			outputFile.getParentFile().mkdirs();
			fileStream = new PrintStream(new FileOutputStream(outputFile));
			System.setErr(fileStream);
			System.setOut(fileStream);
			return run(message, commandArray);
		} catch (FileNotFoundException e) {
			return -1;
		} finally {
			System.setOut(out);
			System.setErr(err);
			if (fileStream != null)
				fileStream.close();
		}
	}

	/*
	 * Untar the given file in the output directory.
	 */
	private void untar(String message, File file) {
		String name = file.getName();
		File gzFile = new File(output, name);
		output.mkdirs();
		run(message, new String[] {"cp", file.getAbsolutePath(), gzFile.getAbsolutePath()});
		run(message, new String[] {"tar", "-zpxf", gzFile.getAbsolutePath()});
		gzFile.delete();
	}

	/*
	 * Return a file object with a unique name in a temporary location.
	 */
	public static File getUniqueFolder() {
		String tempDir = System.getProperty("java.io.tmpdir");
		return new File(tempDir, getUniqueString());
	}

	/*
	 * Helper method to return the install location. Return null if it is unavailable.
	 */
	public static File getInstallLocation() {
		Location installLocation = ServiceHelper.getService(TestActivator.getContext(), Location.class, Location.INSTALL_FILTER);
		if (installLocation == null || !installLocation.isSet())
			return null;
		URL url = installLocation.getURL();
		if (url == null)
			return null;
		return URLUtil.toFile(url);
	}

	private String getValueFor(String property) {
		if (property == null)
			return null;
		String result = TestActivator.getContext().getProperty(property);
		if (result == null && archiveAndRepositoryProperties == null)
			return null;
		if (result == null)
			archiveAndRepositoryProperties.getProperty(property);
		if (result == null)
			result = archiveAndRepositoryProperties.getProperty(property + '.' + Platform.getOS());
		return result;
	}

	/*
	 * Return a file handle pointing to the platform binary zip. Method never returns null because
	 * it will fail an assert before that.
	 */
	private File getPlatformZip() {
		String property = null;
		File file = null;
		if (propertyToPlatformArchive != null) {
			property = getValueFor(propertyToPlatformArchive);
			String message = "Need to set the " + "\"" + propertyToPlatformArchive + "\" system property with a valid path to the platform binary drop or copy the archive to be a sibling of the install folder.";
			if (property == null) {
				fail(message);
			}
			file = new File(property);
			assertNotNull(message, file);
			assertTrue(message, file.exists());
			assertTrue("File is zero length: " + file.getAbsolutePath(), file.length() > 0);
			return file;
		}

		property = getValueFor("org.eclipse.equinox.p2.reconciler.tests.platform.archive");
		if (property == null) {
			// the releng test framework copies the zip so let's look for it...
			// it will be a sibling of the eclipse/ folder that we are running
			File installLocation = getInstallLocation();
			if (Platform.getWS().equals(Platform.WS_COCOA))
				installLocation = installLocation.getParentFile().getParentFile();

			if (installLocation != null) {
				// parent will be "eclipse" and the parent's parent will be "eclipse-testing"
				File parent = installLocation.getParentFile();
				if (parent != null) {
					parent = parent.getParentFile();
					if (parent != null) {
						File[] children = parent.listFiles(new FileFilter() {
							public boolean accept(File pathname) {
								String name = pathname.getName();
								return name.startsWith("eclipse-platform-");
							}
						});
						if (children != null && children.length == 1)
							file = children[0];
					}
				}
			}
		} else {
			file = new File(property);
		}
		StringBuffer detailedMessage = new StringBuffer(600);
		detailedMessage.append(" propertyToPlatformArchive was ").append(propertyToPlatformArchive == null ? " not set " : propertyToPlatformArchive).append('\n');
		detailedMessage.append(" org.eclipse.equinox.p2.reconciler.tests.platform.archive was ").append(property == null ? " not set " : property).append('\n');
		detailedMessage.append(" install location is ").append(getInstallLocation()).append('\n');
		String message = "Need to set the \"org.eclipse.equinox.p2.reconciler.tests.platform.archive\" system property with a valid path to the platform binary drop or copy the archive to be a sibling of the install folder.";
		assertNotNull(message + "\n" + detailedMessage, file);
		assertTrue(message, file.exists());
		assertTrue("File is zero length: " + file.getAbsolutePath(), file.length() > 0);
		return file;
	}

	/*
	 * Add the given bundle to the given folder (do a copy).
	 * The folder can be one of dropins, plugins or features.
	 * If the file handle points to a directory, then do a deep copy.
	 */
	public void add(String message, String target, File file) {
		if (!(target.startsWith("dropins") || target.startsWith("plugins") || target.startsWith("features")))
			fail("Destination folder for resource copying should be either dropins, plugins or features.");
		File destinationParent = new File(output, getRootFolder() + target);
		destinationParent.mkdirs();
		copy(message, file, new File(destinationParent, file.getName()));
	}

	/*
	 * Create a link file in the links folder. Point it to the given extension location.
	 */
	public void createLinkFile(String message, String filename, String extensionLocation) {
		File file = new File(output, getRootFolder() + "links/" + filename + ".link");
		file.getParentFile().mkdirs();
		Properties properties = new Properties();
		properties.put("path", extensionLocation);
		OutputStream stream = null;
		try {
			stream = new BufferedOutputStream(new FileOutputStream(file));
			properties.store(stream, null);
		} catch (IOException e) {
			fail(message, e);
		} finally {
			try {
				if (stream != null)
					stream.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}

	/*
	 * Delete the link file with the given name from the links folder.
	 */
	public void removeLinkFile(String message, String filename) {
		File file = new File(output, getRootFolder() + "links/" + filename + ".link");
		file.delete();
	}

	public void add(String message, String target, File[] files) {
		assertNotNull(files);
		for (int i = 0; i < files.length; i++)
			add(message, target, files[i]);
	}

	/*
	 * Remove the given filename from the given folder.
	 */
	public boolean remove(String message, String target, String filename) {
		if (!(target.startsWith("dropins") || target.startsWith("plugins") || target.startsWith("features")))
			fail("Target folder for resource deletion should be either dropins, plugins or features.");
		File folder = new File(output, getRootFolder() + target);
		File targetFile = new File(folder, filename);
		if (!targetFile.exists())
			return false;
		return delete(targetFile);
	}

	/*
	 * Remove the files with the given names from the target folder.
	 */
	public void remove(String message, String target, String[] names) {
		assertNotNull(names);
		for (int i = 0; i < names.length; i++)
			remove(message, target, names[i]);
	}

	/*
	 * Return a boolean value indicating whether or not a bundle with the given id
	 * is listed in the bundles.info file. Ignore the version number and return true
	 * if there are any matches in the file.
	 */
	public boolean isInBundlesInfo(String bundleId) throws IOException {
		return isInBundlesInfo(bundleId, null);
	}

	protected File getBundlesInfo() {
		return new File(output, getRootFolder() + "configuration/org.eclipse.equinox.simpleconfigurator/bundles.info");
	}

	public boolean isInBundlesInfo(String bundleId, String version) throws IOException {
		return isInBundlesInfo(bundleId, version, null);
	}

	public boolean isInBundlesInfo(String bundleId, String version, String location) throws IOException {
		return isInBundlesInfo(getBundlesInfo(), bundleId, version, location);
	}

	public boolean isInBundlesInfo(File bundlesInfo, String bundleId, String version) throws IOException {
		return isInBundlesInfo(bundlesInfo, bundleId, version, null);
	}

	public BundleInfo[] loadBundlesInfo(File location) throws IOException {
		SimpleConfiguratorManipulator manipulator = new SimpleConfiguratorManipulatorImpl();
		InputStream input = null;
		try {
			input = new BufferedInputStream(new FileInputStream(location));
			return manipulator.loadConfiguration(input, new File(output, "eclipse").toURI());
		} finally {
			try {
				if (input != null)
					input.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}

	public void saveBundlesInfo(BundleInfo[] bundles, File location) throws IOException {
		SimpleConfiguratorManipulator manipulator = new SimpleConfiguratorManipulatorImpl();
		manipulator.saveConfiguration(bundles, location, null);
	}

	/*
	 * Return a boolean value indicating whether or not a bundle with the given id
	 * is listed in the bundles.info file. If the version is non-null, check to ensure the
	 * version is the expected one. If the location is non-null then do a String#contains check.
	 */
	public boolean isInBundlesInfo(File bundlesInfo, String bundleId, String version, String location) throws IOException {
		BundleInfo[] infos = loadBundlesInfo(bundlesInfo);
		for (int i = 0; infos != null && i < infos.length; i++) {
			BundleInfo info = infos[i];
			if (!bundleId.equals(info.getSymbolicName()))
				continue;
			if (version != null && !version.equals(info.getVersion()))
				continue;
			if (location == null)
				return true;
			return info.getLocation().toString().contains(location);
		}
		return false;
	}

	public void reconcile(String message) {
		reconcile(message, false);
	}

	/*
	 * Run the reconciler to discover changes in the drop-ins folder and update the system state.
	 */
	public void reconcile(String message, boolean clean) {
		List<String> args = new ArrayList<String>();
		args.add("-application");
		args.add("org.eclipse.equinox.p2.reconciler.application");
		if (clean)
			args.add("-clean");
		runEclipse(message, args.toArray(new String[args.size()]));
	}

	/*
	 * If a bundle with the given id and version exists in the bundles.info file then
	 * throw an AssertionFailedException.
	 */
	public void assertDoesNotExistInBundlesInfo(String message, String bundleId, String version) {
		try {
			assertTrue(message, !isInBundlesInfo(bundleId, version));
		} catch (IOException e) {
			fail(message, e);
		}
	}

	/*
	 * If a bundle with the given id in the bundles.info file then throw an AssertionFailedException.
	 */
	public void assertDoesNotExistInBundlesInfo(String message, String bundleId) {
		assertDoesNotExistInBundlesInfo(message, bundleId, null);
	}

	/*
	 * If a bundle with the given id and version does not exist in the bundles.info file then
	 * throw an AssertionFailedException.
	 */
	public void assertExistsInBundlesInfo(String message, String bundleId, String version) {
		assertExistsInBundlesInfo(message, bundleId, version, null);
	}

	public void assertExistsInBundlesInfo(String message, String bundleId, String version, String location) {
		try {
			assertTrue(message, isInBundlesInfo(bundleId, version, location));
		} catch (IOException e) {
			fail(message, e);
		}
	}

	/*
	 * If a bundle with the given id does not exist in the bundles.info file then throw an AssertionFailedException.
	 */
	public void assertExistsInBundlesInfo(String message, String bundleId) {
		assertExistsInBundlesInfo(message, bundleId, null);
	}

	/*
	 * Clean up the temporary data used to run the tests.
	 * This method is not intended to be called by clients, it will be called
	 * automatically when the clients use a ReconcilerTestSuite.
	 */
	public void cleanup() throws Exception {
		// rm -rf eclipse sub-dir
		boolean leaveDirty = Boolean.valueOf(TestActivator.getContext().getProperty("p2.tests.doNotClean")).booleanValue();
		if (leaveDirty)
			return;
		for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
			File next = (File) iter.next();
			delete(next);
		}
		output = null;
		toRemove.clear();
	}

	/*
	 * Read and return the configuration object. Will not return null.
	 */
	public Configuration getConfiguration() {
		File configLocation = new File(output, getRootFolder() + "configuration/org.eclipse.update/platform.xml");
		File installLocation = new File(output, getRootFolder());
		return loadConfiguration(configLocation, installLocation);
	}

	public Configuration loadConfiguration(File configLocation, File installLocation) {
		try {
			return Configuration.load(configLocation, installLocation.toURL());
		} catch (ProvisionException e) {
			fail("Error while reading configuration from " + configLocation);
		} catch (MalformedURLException e) {
			fail("Unable to convert install location to URL " + installLocation);
		}
		assertTrue("Unable to read configuration from " + configLocation, false);
		// avoid compiler error
		return null;
	}

	/*
	 * Save the given configuration to disk.
	 */
	public void save(String message, Configuration configuration) {
		File configLocation = new File(output, getRootFolder() + "configuration/org.eclipse.update/platform.xml");
		File installLocation = new File(output, getRootFolder());
		try {
			configuration.save(configLocation, installLocation.toURL());
		} catch (ProvisionException e) {
			fail(message, e);
		} catch (MalformedURLException e) {
			fail(message, e);
		}
	}

	/*
	 * Iterate over the sites in the given configuration and remove the one which
	 * has a url matching the given location.
	 */
	public boolean removeSite(Configuration configuration, String location) throws IOException, URISyntaxException {
		File left = new File(new URI(location)).getCanonicalFile();
		List sites = configuration.getSites();
		for (Iterator iter = sites.iterator(); iter.hasNext();) {
			Site tempSite = (Site) iter.next();
			String siteURL = tempSite.getUrl();
			File right = new File(new URI(siteURL)).getCanonicalFile();
			if (left.equals(right)) {
				return configuration.removeSite(tempSite);
			}
		}
		return false;
	}

	/*
	 * Create and return a new feature object with the given parameters.
	 */
	public Feature createFeature(Site site, String id, String version, String url) {
		Feature result = new Feature(site);
		result.setId(id);
		result.setVersion(version);
		result.setUrl(url);
		return result;
	}

	/*
	 * Create and return a new site object with the given parameters.
	 */
	public Site createSite(String policy, boolean enabled, boolean updateable, String uri, String[] plugins) {
		Site result = new Site();
		result.setPolicy(policy);
		result.setEnabled(enabled);
		result.setUpdateable(updateable);
		result.setUrl(uri);
		if (plugins != null)
			for (int i = 0; i < plugins.length; i++)
				result.addPlugin(plugins[i]);
		return result;
	}

	/*
	 * Copy the bundle with the given id to the specified location. (location
	 * is parent directory)
	 */
	public void copyBundle(String bundlename, File source, File destination) throws IOException {
		if (destination == null)
			destination = output;
		destination = new File(destination, "eclipse/plugins");
		if (source == null) {
			Bundle bundle = TestActivator.getBundle(bundlename);
			if (bundle == null) {
				throw new IOException("Could not find: " + bundlename);
			}
			String location = bundle.getLocation();
			if (location.startsWith("reference:"))
				location = location.substring("reference:".length());
			source = new File(FileLocator.toFileURL(new URL(location)).getFile());
		}
		destination = new File(destination, source.getName());
		if (destination.exists())
			return;
		FileUtils.copy(source, destination, new File(""), false);
		// if the target of the copy doesn't exist, then signal an error
		assertTrue("Unable to copy " + source + " to " + destination, destination.exists());
	}

	/*
	 * Assert that a feature with the given id exists in the configuration. If 
	 * a version is specified then match the version, otherwise any version will
	 * do.
	 */
	public void assertFeatureExists(String message, Configuration configuration, String id, String version) {
		List sites = configuration.getSites();
		assertNotNull(message, sites);
		boolean found = false;
		for (Iterator iter = sites.iterator(); iter.hasNext();) {
			Site site = (Site) iter.next();
			Feature[] features = site.getFeatures();
			for (int i = 0; features != null && i < features.length; i++) {
				if (id.equals(features[i].getId())) {
					if (version == null)
						found = true;
					else if (version.equals(features[i].getVersion()))
						found = true;
				}
			}
		}
		assertTrue(message, found);
	}

	/*
	 * Return a boolean value indicating whether or not the IU with the given ID and version
	 * is installed. We do this by loading the profile registry and seeing if it is there.
	 */
	public boolean isInstalled(String id, String version) {
		File location = new File(output, getRootFolder() + "/p2/org.eclipse.equinox.p2.engine/profileRegistry");
		SimpleProfileRegistry registry = new SimpleProfileRegistry(getAgent(), location, new SurrogateProfileHandler(getAgent()), false);
		IProfile[] profiles = registry.getProfiles();
		assertEquals("1.0 Should only be one profile in registry.", 1, profiles.length);
		IQueryResult queryResult = profiles[0].query(QueryUtil.createIUQuery(id, Version.create(version)), null);
		return !queryResult.isEmpty();
	}

	public IInstallableUnit getRemoteIU(String id, String version) {
		File location = new File(output, getRootFolder() + "/p2/org.eclipse.equinox.p2.engine/profileRegistry");
		SimpleProfileRegistry registry = new SimpleProfileRegistry(getAgent(), location, new SurrogateProfileHandler(getAgent()), false);
		IProfile[] profiles = registry.getProfiles();
		assertEquals("1.0 Should only be one profile in registry.", 1, profiles.length);
		IQueryResult queryResult = profiles[0].query(QueryUtil.createIUQuery(id, Version.create(version)), null);
		assertEquals("1.1 Should not have more than one IU wth the same ID and version.", 1, queryResultSize(queryResult));
		return (IInstallableUnit) queryResult.iterator().next();
	}

	protected int runEclipse(String message, String[] args) {
		return runEclipse(message, null, args);
	}

	/*
	 * Note: code modified so we no longer return int 13 if at all possible. Instead we try and
	 * read the error log and fail with the log contents as the fail message. Users of this method should
	 * not expect 13 to be returned.
	 */
	protected int runEclipse(String message, File location, String[] args) {
		return runEclipse(message, location, args, null);
	}

	protected int runEclipse(String message, File location, String[] args, File extensions) {
		File root = new File(Activator.getBundleContext().getProperty("java.home"));
		root = new File(root, "bin");
		File exe = new File(root, "javaw.exe");
		if (!exe.exists())
			exe = new File(root, "java");
		assertTrue("Java executable not found in: " + exe.getAbsolutePath(), exe.exists());
		List<String> command = new ArrayList<String>();
		Collections.addAll(command, new String[] {(new File(location == null ? output : location, getExeFolder() + "eclipse")).getAbsolutePath(), "--launcher.suppressErrors", "-nosplash", "-vm", exe.getAbsolutePath()});
		Collections.addAll(command, args);
		Collections.addAll(command, new String[] {"-vmArgs", "-Dosgi.checkConfiguration=true"});
		// command-line if you want to run and allow a remote debugger to connect
		if (debug)
			Collections.addAll(command, new String[] {"-Xdebug", "-Xnoagent", "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8787"});
		int result = run(message, command.toArray(new String[command.size()]));
		// 13 means that we wrote something out in the log file.
		// so try and parse it and fail via that message if we can.
		if (result == 13)
			parseExitdata(message);
		return result;
	}

	protected void debugEclipse(boolean on) {
		this.debug = on;
	}

	protected void parseExitdata(String message) {
		// if the exit data contains a message telling us the location of the log file, then get it
		String data = TestActivator.getContext().getProperty("eclipse.exitdata");
		if (data == null)
			return;
		String log = null;
		// big hack but for now assume the log file path is the last segment of the error message
		for (StringTokenizer tokenizer = new StringTokenizer(data); tokenizer.hasMoreTokens();)
			log = tokenizer.nextToken();
		if (log == null)
			return;
		// remove trailing "."
		if (log.endsWith("."))
			log = log.substring(0, log.length() - 1);
		String errors = read(log);
		if (errors == null)
			return;
		// fail using the text from the log file
		assertOK(message, new Status(IStatus.ERROR, TestActivator.PI_PROV_TESTS, errors));
	}

	// Fully read the file pointed to by the given path
	private String read(String path) {
		File file = new File(path);
		if (!file.exists())
			return null;
		StringBuffer buffer = new StringBuffer();
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			for (String line = reader.readLine(); line != null; line = reader.readLine()) {
				buffer.append(line);
				buffer.append('\n');
			}
		} catch (IOException e) {
			// TODO
		} finally {
			if (reader != null)
				try {
					reader.close();
				} catch (IOException e) {
					// ignore
				}
		}
		return buffer.toString();
	}

	public int runInitialize(String message) {
		return runEclipse(message, new String[] {"-initialize"});
	}

	public int runDirectorToUpdate(String message, String sourceRepo, String iuToInstall, String iuToUninstall) {
		return runEclipse(message, new String[] {"-application", "org.eclipse.equinox.p2.director", "-repository", sourceRepo, "-installIU", iuToInstall, "-uninstallIU", iuToUninstall});
	}

	public int runDirectorToRevert(String message, String sourceRepo, String timestampToRevertTo) {
		return runEclipse(message, new String[] {"-application", "org.eclipse.equinox.p2.director", "-repository", sourceRepo, "-revert", timestampToRevertTo});
	}

	public int runDirectorToInstall(String message, File installFolder, String sourceRepo, String iuToInstall) {
		String[] command = new String[] {//
				"-application", "org.eclipse.equinox.p2.director", //
				"-repository", sourceRepo, "-installIU", iuToInstall, //
				"-destination", installFolder.getAbsolutePath(), //
				"-bundlepool", installFolder.getAbsolutePath(), //
				"-roaming", "-profile", "PlatformProfile", "-profileProperties", "org.eclipse.update.install.features=true", // 
				"-p2.os", Platform.getOS(), "-p2.ws", Platform.getWS(), "-p2.arch", Platform.getOSArch()};
		return runEclipse(message, command);
	}

	public int runVerifierBundle(File destination) {
		if (destination == null)
			destination = output;
		String message = "Running the verifier bundle at: " + destination;
		return runEclipse(message, destination, new String[] {"-application", "org.eclipse.equinox.p2.tests.verifier.application", "-consoleLog"});
	}

	public int installAndRunVerifierBundle(File destination) {
		if (destination == null)
			destination = output;
		try {
			copyBundle(VERIFIER_BUNDLE_ID, null, destination);
		} catch (IOException e) {
			fail("Could not find the verifier bundle");
		}
		int returnCode = runVerifierBundle(destination);
		deleteVerifierBundle(destination);
		return returnCode;
	}

	public int installAndRunVerifierBundle35(File destination) {
		if (destination == null)
			destination = output;
		try {
			copyBundle(VERIFIER_BUNDLE_ID, getTestData(VERIFIER_BUNDLE_ID + "3.5", "testData/VerifierBundle35/org.eclipse.equinox.p2.tests.verifier_1.0.0.jar"), destination);
		} catch (IOException e) {
			fail("Could not find the verifier bundle");
		}
		int returnCode = runVerifierBundle(destination);
		deleteVerifierBundle(destination);
		return returnCode;
	}

	private void deleteVerifierBundle(File destination) {
		if (destination == null)
			destination = output;
		destination = new File(destination, getRootFolder() + "plugins");
		File[] verifierBundle = destination.listFiles(new FilenameFilter() {

			public boolean accept(File dir, String name) {
				if (name.startsWith(VERIFIER_BUNDLE_ID))
					return true;
				return false;
			}
		});
		if (verifierBundle != null && verifierBundle.length > 0)
			verifierBundle[0].delete();
	}

	private static void loadPlatformZipPropertiesFromFile() {
		File installLocation = getInstallLocation();
		if (installLocation != null) {
			// parent will be "eclipse" and the parent's parent will be "eclipse-testing"
			File parent = installLocation.getParentFile();
			if (parent != null) {
				parent = parent.getParentFile();
				if (parent != null) {
					File propertiesFile = new File(parent, "equinoxp2tests.properties");
					if (!propertiesFile.exists())
						return;
					archiveAndRepositoryProperties = new Properties();
					try {
						InputStream is = null;
						try {
							is = new BufferedInputStream(new FileInputStream(propertiesFile));
							archiveAndRepositoryProperties.load(is);
						} finally {
							is.close();
						}
					} catch (IOException e) {
						return;
					}
				}
			}
		}
	}

	static protected String getRootFolder() {
		String eclipseFolder = "eclipse/";
		if (Platform.getWS().equals(Platform.WS_COCOA))
			eclipseFolder = "Eclipse.app/Contents/Eclipse/";
		return eclipseFolder;
	}

	static protected String getExeFolder() {
		String eclipseFolder = "eclipse/";
		if (Platform.getWS().equals(Platform.WS_COCOA))
			eclipseFolder = "Eclipse.app/Contents/MacOS/";
		return eclipseFolder;
	}
}