/*******************************************************************************
 *  Copyright (c) 2009, 2010 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
 *******************************************************************************/
package org.eclipse.equinox.p2.tests.ant;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.artifact.processors.md5.Messages;
import org.eclipse.equinox.internal.p2.core.helpers.CollectionUtils;
import org.eclipse.equinox.internal.p2.director.PermissiveSlicer;
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.internal.repository.comparator.MD5ArtifactComparator;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.artifact.*;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.tests.AbstractAntProvisioningTest;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
import org.eclipse.osgi.util.NLS;

public class MirrorTaskTest extends AbstractAntProvisioningTest {
	private static final String MIRROR_TASK = "p2.mirror";
	private static final String MIRROR_ARTIFACTS_TASK = "p2.artifact.mirror";
	private URI destinationRepo;
	private URI artifactRepo, sliceArtifactRepo, sliceRepo, sourceRepo2, zipRepo;

	public void setUp() throws Exception {
		super.setUp();
		// Get a random location to create a repository
		destinationRepo = (new File(getTestFolder(getName()), "destinationRepo")).toURI();
		artifactRepo = getTestData("error loading data", "testData/mirror/mirrorPackedRepo").toURI();
		sourceRepo2 = getTestData("error loading data", "testData/mirror/mirrorSourceRepo2").toURI();
		sliceRepo = getTestData("error loading data", "testData/permissiveSlicer").toURI();
		sliceArtifactRepo = getTestData("error loading data", "testData/testRepos/updateSite").toURI();
		zipRepo = getTestData("error loading data", "/testData/mirror/zippedRepo.zip").toURI();
	}

	public void tearDown() throws Exception {
		// Remove repository manager references
		getArtifactRepositoryManager().removeRepository(destinationRepo);
		getMetadataRepositoryManager().removeRepository(destinationRepo);
		getArtifactRepositoryManager().removeRepository(sliceRepo);
		getMetadataRepositoryManager().removeRepository(sliceRepo);
		getArtifactRepositoryManager().removeRepository(sourceRepo2);
		getMetadataRepositoryManager().removeRepository(sourceRepo2);
		getArtifactRepositoryManager().removeRepository(zipRepo);
		getMetadataRepositoryManager().removeRepository(zipRepo);
		// Cleanup disk
		delete(new File(destinationRepo).getParentFile());
		super.tearDown();
	}

	/*
	 * Test that it is possible to mirror by only specifying an Artifact repository
	 */
	public void testMirrorArtifactOnly() {
		AntTaskElement mirror = createMirrorTask(TYPE_ARTIFACT);
		mirror.addElement(createSourceElement(artifactRepo, null));
		runAntTask();

		assertEquals("Different number of Artifact Keys", getArtifactKeyCount(artifactRepo), getArtifactKeyCount(destinationRepo));
		assertEquals("Different number of ArtifactDescriptors", getArtifactDescriptorCount(artifactRepo), getArtifactDescriptorCount(destinationRepo));
	}

	/*
	 * Test that it is possible to mirror when only specifying a Metadata repository 
	 */
	public void testMirrorMetadataOnly() {
		AntTaskElement mirror = createMirrorTask(TYPE_METADATA);
		mirror.addElement(createSourceElement(null, sourceRepo2));
		runAntTask();

		assertEquals("Different number of IUs", getIUCount(sourceRepo2), getIUCount(destinationRepo));
	}

	public void testMirrorEmptyBaseline() throws Exception {
		File folder = getTestFolder("MirrorEmptyBaseline");
		String baseline = "file:" + new File(folder, "base").getAbsolutePath();
		String dest = "file:" + new File(folder, "destination").getAbsolutePath();
		String logFile = new File(folder, "log.txt").getAbsolutePath();

		AntTaskElement mirror = new AntTaskElement("p2.artifact.mirror");
		mirror.addAttribute("source", URIUtil.toUnencodedString(sourceRepo2));
		mirror.addAttribute("baseline", baseline);
		mirror.addAttribute("comparatorId", "org.eclipse.equinox.p2.repository.tools.jar.comparator");
		mirror.addAttribute("destination", dest);
		mirror.addAttribute("log", logFile);
		addTask(mirror);
		runAntTask();
		assertLogContainsLine(new File(folder, "log.txt"), "No repository found at " + URIUtil.toUnencodedString(URIUtil.fromString(baseline)));
	}

	/*
	 * Test we can mirror from a zipped repository
	 */
	public void testMirrorFromZip() {
		URI localAddress = null;
		try {
			localAddress = URIUtil.fromString(new File(zipRepo).toString());
		} catch (URISyntaxException e) {
			fail("failed to convert zip repo location");
		}
		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(localAddress, localAddress));
		runAntTask();

		assertEquals("Wrong number of ArtifactKeys", getArtifactKeyCount(URIUtil.toJarURI(zipRepo, null)), getArtifactKeyCount(destinationRepo));
		assertEquals("Wrong number of ArtifactDescriptors", getArtifactDescriptorCount(URIUtil.toJarURI(zipRepo, null)), getArtifactDescriptorCount(destinationRepo));
		assertEquals("Different number of IUs", getIUCount(sourceRepo2), getIUCount(destinationRepo));
	}

	/*
	 * Test that all IUs can be mirrored
	 */
	public void testMirrorAllIUSpecified() throws ProvisionException {
		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(sourceRepo2, sourceRepo2));
		addAllIUs(mirror, getMetadataRepositoryManager().loadRepository(sourceRepo2, null));
		runAntTask();

		assertEquals("Different number of Artifact Keys", getArtifactKeyCount(sourceRepo2), getArtifactKeyCount(destinationRepo));
		assertContentEquals("IUs differ", getMetadataRepositoryManager().loadRepository(sourceRepo2, null), getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		assertEquals("Different number of IUs", getIUCount(sourceRepo2), getIUCount(destinationRepo));
		assertContentEquals("Artifacts differ", getArtifactRepositoryManager().loadRepository(sourceRepo2, null), getArtifactRepositoryManager().loadRepository(destinationRepo, null));
	}

	/*
	 * Test that we only mirror specified IUs & Artifacts
	 */
	public void testMirrorSomeIUSpecified() {
		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(sourceRepo2, sourceRepo2));
		mirror.addElement(createIUElement("anotherplugin", "1.0.0"));

		runAntTask();

		assertEquals("Wrong number of ArtifactKeys", 1, getArtifactKeyCount(destinationRepo));
		assertEquals("Wrong number of IUs", 1, getIUCount(destinationRepo));
	}

	/*
	 * Test what occurs with a missing IU
	 */
	public void testMirrorMissingIU() {
		String id = "My_Missing_IU";
		String version = "1.0.0";
		String iu = "Installable Unit [ id=" + id + " version=" + version + " ]";

		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(sourceRepo2, sourceRepo2));
		mirror.addElement(createIUElement(id, version));
		Exception exception = null;
		try {
			runAntTaskWithExceptions();
		} catch (CoreException e) {
			exception = e;
		}
		if (exception == null)
			fail("No Exception was thrown");

		assertEquals("Unexpected message", NLS.bind(org.eclipse.equinox.p2.internal.repository.tools.Messages.AbstractRepositoryTask_unableToFind, iu), rootCause(exception).getMessage());
	}

	/*
	 * Test that the proper exception is thrown when no IU is provided
	 */
	public void testMirrorMetadataDestinationWithoutSource() {
		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(sourceRepo2, null));

		Exception exception = null;
		try {
			runAntTaskWithExceptions();
		} catch (CoreException e) {
			exception = e;
		}
		if (exception == null)
			fail("No exception thrown");
		if (!(rootCause(exception) instanceof ProvisionException && rootCause(exception).getMessage().equals(org.eclipse.equinox.p2.internal.repository.tools.Messages.MirrorApplication_metadataDestinationNoSource)))
			fail("Exception is of an unexpected type or message", rootCause(exception));
	}

	/*
	 * Test that the proper exception is thrown when no IU is provided
	 */
	public void testMirrorArtifactDestinationWithoutSource() {
		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(null, sourceRepo2));

		Exception exception = null;
		try {
			runAntTaskWithExceptions();
		} catch (CoreException e) {
			exception = e;
		}
		if (exception == null)
			fail("No exception thrown");
		if (!(rootCause(exception) instanceof ProvisionException) && rootCause(exception).getMessage().contains(org.eclipse.equinox.p2.internal.repository.tools.Messages.MirrorApplication_artifactDestinationNoSource))
			fail("Exception is of an unexpected type or message", rootCause(exception));
	}

	/*
	 * Test that all IUs are mirrored when none are specified
	 */
	public void testMirrorNoIUSpecified() {
		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(sourceRepo2, sourceRepo2));

		runAntTask();

		try {
			assertEquals("Different number of Artifact Keys", getArtifactKeyCount(sourceRepo2), getArtifactKeyCount(destinationRepo));
			assertContentEquals("Artifacts differ", getArtifactRepositoryManager().loadRepository(sourceRepo2, null), getArtifactRepositoryManager().loadRepository(destinationRepo, null));
			assertEquals("Different number of IUs", getIUCount(sourceRepo2), getIUCount(destinationRepo));
			assertContentEquals("IUs differ", getMetadataRepositoryManager().loadRepository(sourceRepo2, null), getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		} catch (ProvisionException e) {
			fail("Failed to compare results", e);
		}
	}

	/*
	 * Test the handling of invalid destinations with the mirror task
	 */
	public void testMirrorWithInvalidDestination() throws URISyntaxException {
		URI location = new URI("invalid:/scheme");

		AntTaskElement mirror = new AntTaskElement(MIRROR_TASK);
		mirror.addElement(getRepositoryElement(location, TYPE_BOTH));
		mirror.addElement(createSourceElement(sourceRepo2, sourceRepo2));
		addTask(mirror);

		Throwable exception = null;
		try {
			runAntTaskWithExceptions();
		} catch (Exception e) {
			exception = e;
		}
		if (exception == null)
			fail("No Exception thrown");

		while (exception.getCause() != null && !(exception instanceof ProvisionException))
			exception = exception.getCause();
		assertTrue("Unexpected error", NLS.bind(org.eclipse.equinox.p2.internal.repository.tools.Messages.exception_invalidDestination, location).equals(exception.getMessage()));
	}

	/*
	 * Test the behavior when a valid path is provided as source, but no repository is present at the location
	 */
	public void testMirrorWithNoRepositoryAtSource() {
		URI location = getTempFolder().toURI();
		try {
			AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
			mirror.addElement(createSourceElement(location, location));
			addTask(mirror);

			Throwable exception = null;
			try {
				runAntTaskWithExceptions();
			} catch (Exception e) {
				exception = e;
			}
			if (exception == null)
				fail("No Exception thrown");

			while (exception.getCause() != null && !(exception instanceof ProvisionException))
				exception = exception.getCause();
			assertTrue("Unexpected error", NLS.bind("No repository found at {0}.", location).equals(exception.getMessage()));
		} finally {
			delete(new File(location));
		}
	}

	/*
	 * Test the handling of invalid destinations with the mirror task
	 */
	public void testMirrorWithInvalidSource() throws URISyntaxException {
		URI location = new URI("invalid:/scheme2");

		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(location, location));
		addTask(mirror);

		Throwable exception = null;
		try {
			runAntTaskWithExceptions();
		} catch (Exception e) {
			exception = e;
		}
		if (exception == null)
			fail("No Exception thrown");

		while (exception.getCause() != null && !(exception instanceof ProvisionException))
			exception = exception.getCause();
		assertTrue("Unexpected error", NLS.bind(org.eclipse.equinox.p2.internal.repository.tools.Messages.exception_invalidSource, location).equals(exception.getMessage()));
	}

	/*
	 * Test slicing options
	 */
	public void testSlicingFollowStrict() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("org.eclipse.rcp.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		AntTaskElement mirror = createMirrorTask(TYPE_METADATA);
		mirror.addElement(createSourceElement(null, sliceRepo));
		mirror.addElement(createSlicingOption(null, null, true, null, "win32,win32,x86", null));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		Map<String, String> p = getSliceProperties();
		p.put("org.eclipse.update.install.features", String.valueOf(true));
		PermissiveSlicer slicer = new PermissiveSlicer(repo, p, true, true, true, true, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu}, new NullProgressMonitor());
		assertEquals("Different number of IUs", queryResultSize(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getIUCount(destinationRepo));

		try {
			assertIUContentEquals("IUs differ", result, getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		} catch (ProvisionException e) {
			fail("Failed to compare contents", e);
		}
	}

	public void testSlicingIncludeNonGreedy() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("org.eclipse.rcp.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		AntTaskElement mirror = createMirrorTask(TYPE_METADATA);
		mirror.addElement(createSourceElement(null, sliceRepo));
		mirror.addElement(createSlicingOption(null, false, null, null, null, null));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		PermissiveSlicer slicer = new PermissiveSlicer(repo, CollectionUtils.<String, String> emptyMap(), true, false, true, false, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu}, new NullProgressMonitor());

		assertEquals("Different number of IUs", queryResultSize(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getIUCount(destinationRepo));
		try {
			assertIUContentEquals("IUs differ", result, getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		} catch (ProvisionException e) {
			fail("Failed to compare contents", e);
		}
	}

	public void testSlicingIncludeOptionalDependencies() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("org.eclipse.rcp.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		AntTaskElement mirror = createMirrorTask(TYPE_METADATA);
		mirror.addElement(createSourceElement(null, sliceRepo));
		mirror.addElement(createSlicingOption(false, null, null, null, "win32,win32,x86", null));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		Map<String, String> p = getSliceProperties();
		p.put("org.eclipse.update.install.features", String.valueOf(true));
		PermissiveSlicer slicer = new PermissiveSlicer(repo, p, false, true, true, false, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu}, new NullProgressMonitor());
		assertEquals("Different number of IUs", queryResultSize(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getIUCount(destinationRepo));
		try {
			assertIUContentEquals("IUs differ", result, getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		} catch (ProvisionException e) {
			fail("Failed to compare contents", e);
		}
	}

	public void testSlicingFilter() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("org.eclipse.rcp.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		AntTaskElement mirror = createMirrorTask(TYPE_METADATA);
		mirror.addElement(createSourceElement(null, sliceRepo));
		mirror.addElement(createSlicingOption(null, null, null, null, "win32,win32,x86", "org.eclipse.update.install.features=false"));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		Map<String, String> p = getSliceProperties();
		PermissiveSlicer slicer = new PermissiveSlicer(repo, p, true, true, true, false, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu}, new NullProgressMonitor());
		assertEquals("Different number of IUs", queryResultSize(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getIUCount(destinationRepo));
		try {
			assertIUContentEquals("IUs differ", result, getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		} catch (ProvisionException e) {
			fail("Failed to compare contents", e);
		}
	}

	/*
	 * Test the platform filter
	 */
	public void testSlicingPlatformFilter() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("org.eclipse.rcp.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		AntTaskElement mirror = createMirrorTask(TYPE_METADATA);
		mirror.addElement(createSourceElement(null, sliceRepo));
		mirror.addElement(createSlicingOption(null, null, null, null, "win32,win32,x86", null));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		Map<String, String> p = getSliceProperties();
		p.put("org.eclipse.update.install.features", String.valueOf(true));
		PermissiveSlicer slicer = new PermissiveSlicer(repo, p, true, true, true, false, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu}, new NullProgressMonitor());
		assertEquals("Different number of IUs", queryResultSize(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getIUCount(destinationRepo));
		try {
			assertIUContentEquals("IUs differ", result, getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		} catch (ProvisionException e) {
			fail("Failed to compare contents", e);
		}
	}

	/*
	 * Test disabling includeFeatures for SlicingOptions
	 */
	public void testSlicingIncludeFeaturesFalse() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("org.eclipse.rcp.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		// Create task
		AntTaskElement mirror = createMirrorTask(TYPE_METADATA);
		mirror.addElement(createSourceElement(null, sliceRepo));
		mirror.addElement(createSlicingOption(null, null, null, false, "win32,win32,x86", null));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		Map<String, String> p = getSliceProperties();
		PermissiveSlicer slicer = new PermissiveSlicer(repo, p, true, true, true, false, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu}, new NullProgressMonitor());
		assertEquals("Different number of IUs", queryResultSize(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getIUCount(destinationRepo));
		try {
			assertIUContentEquals("IUs differ", result, getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		} catch (ProvisionException e) {
			fail("Failed to compare contents", e);
		}
	}

	/*
	 * Tests the results of a slice are used to mirror artifacts
	 */
	public void testSlicingMetadataAndArtifactsMirrored() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceArtifactRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("test.feature.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		// Create task
		AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
		mirror.addElement(createSourceElement(sliceArtifactRepo, sliceArtifactRepo));
		mirror.addElement(createSlicingOption(null, null, null, false, "win32,win32,x86", null));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		Map<String, String> p = getSliceProperties();
		PermissiveSlicer slicer = new PermissiveSlicer(repo, p, true, true, true, false, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu}, new NullProgressMonitor());

		assertEquals("Different number of IUs", queryResultSize(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getIUCount(destinationRepo));
		assertEquals("Different number of ArtifactKeys", getArtifactKeyCount(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getArtifactKeyCount(destinationRepo));
		try {
			assertArtifactKeyContentEquals("Different ArtifactKeys", result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor()), destinationRepo);
			assertIUContentEquals("IUs differ", result, getMetadataRepositoryManager().loadRepository(destinationRepo, null));
		} catch (ProvisionException e) {
			fail("Failed to compare contents", e);
		}

	}

	/*
	 * Test the ability to slice an IU and mirror only the artifacts
	 */
	public void testMirrorSlicedIUtoArtifact() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceArtifactRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("test.feature.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		// Create task
		AntTaskElement mirror = createMirrorTask(TYPE_ARTIFACT);
		mirror.addElement(createSourceElement(sliceArtifactRepo, sliceArtifactRepo));
		mirror.addElement(createSlicingOption(null, null, null, false, "win32,win32,x86", null));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		Map<String, String> p = getSliceProperties();
		PermissiveSlicer slicer = new PermissiveSlicer(repo, p, true, true, true, false, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu}, new NullProgressMonitor());

		assertEquals("Different number of ArtifactKeys", getArtifactKeyCount(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getArtifactKeyCount(destinationRepo));
		assertArtifactKeyContentEquals("Different ArtifactKeys", result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor()), destinationRepo);
	}

	/*
	 * Test the ability to slice an IU and mirror only the artifacts
	 */
	public void testMirrorSlicedMultipleIUsToArtifact() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceArtifactRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("test.feature.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		c = repo.query(QueryUtil.createIUQuery("RCP_Browser_Example.feature.group"), new NullProgressMonitor());
		IInstallableUnit iu2 = (IInstallableUnit) c.iterator().next();

		// Create task
		AntTaskElement mirror = createMirrorTask(TYPE_ARTIFACT);
		mirror.addElement(createSourceElement(sliceArtifactRepo, sliceArtifactRepo));
		mirror.addElement(createSlicingOption(null, null, null, false, "win32,win32,x86", null));
		mirror.addElement(createIUElement(iu));
		mirror.addElement(createIUElement(iu2));

		runAntTask();

		Map<String, String> p = getSliceProperties();
		PermissiveSlicer slicer = new PermissiveSlicer(repo, p, true, true, true, false, false);
		IQueryable result = slicer.slice(new IInstallableUnit[] {iu, iu2}, new NullProgressMonitor());

		assertEquals("Different number of ArtifactKeys", getArtifactKeyCount(result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor())), getArtifactKeyCount(destinationRepo));
		assertArtifactKeyContentEquals("Different ArtifactKeys", result.query(QueryUtil.createIUAnyQuery(), new NullProgressMonitor()), destinationRepo);
	}

	public void testMirrorCompareWithIgnore() throws Exception {
		File testFolder = getTestFolder("mirrorWithIgnore");
		File base = new File(testFolder, "base");
		File source = new File(testFolder, "source");
		File dest = new File(testFolder, "destination");

		//some content for our fake bundles
		Properties props = new Properties();
		props.put("key", "value");

		IArtifactKey key = new ArtifactKey("osgi.bundle", "a", Version.parseVersion("1.0.0"));
		IArtifactRepository[] repos = new IArtifactRepository[] {createArtifactRepository(base.toURI(), null), createArtifactRepository(source.toURI(), null)};
		for (int i = 0; i < 2; i++) {
			ZipOutputStream stream = new ZipOutputStream(repos[i].getOutputStream(repos[i].createArtifactDescriptor(key)));
			ZipEntry entry = new ZipEntry("file.properties");
			stream.putNextEntry(entry);
			props.store(stream, String.valueOf(i));
			stream.closeEntry();
			stream.close();
		}
		key = new ArtifactKey("osgi.bundle", "b", Version.parseVersion("1.0.0"));
		for (int i = 0; i < 2; i++) {
			ZipOutputStream stream = new ZipOutputStream(repos[i].getOutputStream(repos[i].createArtifactDescriptor(key)));
			ZipEntry entry = new ZipEntry("file.properties");
			stream.putNextEntry(entry);
			props.put("boo", String.valueOf(i));
			props.store(stream, String.valueOf(i));
			stream.closeEntry();
			stream.close();
		}

		AntTaskElement mirror = createMirrorTask(TYPE_ARTIFACT);
		mirror.addElement(new AntTaskElement("source", new String[] {"location", URIUtil.toUnencodedString(source.toURI()), "kind", "artifact"}));
		mirror.addElement(new AntTaskElement("destination", new String[] {"location", URIUtil.toUnencodedString(dest.toURI()), "kind", "artifact"}));
		AntTaskElement comparator = new AntTaskElement("comparator");
		comparator.addAttribute("comparator", "org.eclipse.equinox.p2.repository.tools.jar.comparator");
		comparator.addAttribute("comparatorLog", new File(testFolder, "log.txt").getAbsolutePath());
		comparator.addElement(new AntTaskElement("repository", new String[] {"location", URIUtil.toUnencodedString(base.toURI())}));
		AntTaskElement exclude = new AntTaskElement("exclude");
		exclude.addElement(new AntTaskElement("artifact", new String[] {"id", "b"}));
		comparator.addElement(exclude);
		mirror.addElement(comparator);
		runAntTask();
	}

	/*
	 * Test the ability to slice an IU and mirror only the artifacts
	 */
	public void testMirrorIUtoArtifact() {
		IMetadataRepository repo = null;
		try {
			repo = loadMetadataRepository(sliceArtifactRepo);
		} catch (ProvisionException e) {
			fail("Loading repository failed", e);
		}
		IQueryResult c = repo.query(QueryUtil.createIUQuery("org.eclipse.ui.examples.readmetool"), new NullProgressMonitor());
		IInstallableUnit iu = (IInstallableUnit) c.iterator().next();

		// Create task
		AntTaskElement mirror = createMirrorTask(TYPE_ARTIFACT);
		mirror.addElement(createSourceElement(sliceArtifactRepo, sliceArtifactRepo));
		mirror.addElement(createIUElement(iu));

		runAntTask();

		Collector collector = new Collector();
		collector.accept(iu);

		assertEquals("Different number of ArtifactKeys", getArtifactKeyCount(collector), getArtifactKeyCount(destinationRepo));
		assertArtifactKeyContentEquals("Different ArtifactKeys", collector, destinationRepo);
	}

	/*
	 * Test the result of a slice which results in no IUs
	 */
	public void testSlicingInvalid() {
		AntTaskElement mirror = createMirrorTask(TYPE_METADATA);
		mirror.addElement(createSourceElement(null, sliceRepo));
		mirror.addElement(createSlicingOption(null, null, null, null, "win32,win32,x86", null));

		Exception exception = null;
		try {
			runAntTaskWithExceptions();
		} catch (Exception e) {
			exception = e;
		}

		if (exception == null || !(rootCause(exception) instanceof ProvisionException)) {
			fail("Unexpected exception type", exception);
		}
	}

	public void testMirrorPackedRepo() {
		AntTaskElement mirror = new AntTaskElement(MIRROR_ARTIFACTS_TASK);
		mirror.addAttribute("destination", URIUtil.toUnencodedString(destinationRepo));
		mirror.addAttribute("source", URIUtil.toUnencodedString(artifactRepo));
		addTask(mirror);
		runAntTask();

		File repo = new File(destinationRepo);

		assertTrue(new File(repo, "plugins/org.eclipse.core.filebuffers_3.4.0.v20080603-2000.jar.pack.gz").exists());
		assertTrue(new File(repo, "plugins/org.eclipse.osgi.services.source_3.1.200.v20071203.jar.pack.gz").exists());
	}

	/*
	 * Modified from org.eclipse.equinox.p2.tests.mirror.ArtifactMirrorApplicationTest
	 */
	public void testBaselineCompareUsingMD5Comparator() {
		//Setup create descriptors with different md5 values
		IArtifactKey dupKey = PublisherHelper.createBinaryArtifactKey("testKeyId", Version.create("1.2.3"));
		File artifact1 = getTestData("0.0", "/testData/mirror/mirrorSourceRepo1 with space/content.xml");
		File artifact2 = getTestData("0.0", "/testData/mirror/mirrorSourceRepo2/content.xml");

		//Setup Copy the file to the baseline
		File repoLocation = getTestFolder(getUniqueString());
		File baselineLocation = getTestFolder(getUniqueString());
		File baselineBinaryDirectory = new File(baselineLocation, "binary");
		baselineBinaryDirectory.mkdir();
		File baselineContentLocation = new File(baselineBinaryDirectory, "testKeyId_1.2.3");
		AbstractProvisioningTest.copy("Copying File to baseline", artifact2, baselineContentLocation);

		IArtifactDescriptor descriptor1 = PublisherHelper.createArtifactDescriptor(dupKey, artifact1);
		IArtifactDescriptor descriptor2 = PublisherHelper.createArtifactDescriptor(dupKey, baselineContentLocation);

		assertEquals("Ensuring Descriptors are the same", descriptor1, descriptor2);
		assertNotSame("Ensuring MD5 values are different", descriptor1.getProperty(IArtifactDescriptor.DOWNLOAD_MD5), descriptor2.getProperty(IArtifactDescriptor.DOWNLOAD_MD5));

		//Setup make repositories
		IArtifactRepository repo = null;
		IArtifactRepository baseline = null;
		try {
			repo = createRepositoryWithIU(repoLocation.toURI(), descriptor1);
			baseline = createRepositoryWithIU(baselineLocation.toURI(), descriptor2);
		} catch (ProvisionException e) {
			fail("Error creating repositories", e);
		}

		//Comparator prints to stderr, redirect that to a file
		PrintStream oldErr = System.err;
		PrintStream newErr = null;
		PrintStream oldOut = System.out;
		PrintStream newOut = null;
		try {
			(new File(destinationRepo)).mkdir();
			newErr = new PrintStream(new FileOutputStream(new File(new File(destinationRepo), "sys.err")));
			newOut = new PrintStream(new FileOutputStream(new File(new File(destinationRepo), "sys.out")));
		} catch (FileNotFoundException e) {
			fail("Error redirecting outputs", e);
		}

		try {
			System.setErr(newErr);
			System.setOut(newOut);

			// Create task
			AntTaskElement mirror = createMirrorTask(TYPE_BOTH);
			// Add source
			mirror.addElement(createSourceElement(repoLocation.toURI(), repoLocation.toURI()));
			// set verbose
			mirror.addAttribute("verbose", String.valueOf(true));

			// Create a comparator element 
			AntTaskElement comparator = new AntTaskElement("comparator");
			comparator.addAttribute("comparator", MD5ArtifactComparator.MD5_COMPARATOR_ID);
			comparator.addElement(getRepositoryElement(baselineLocation.toURI(), null));
			mirror.addElement(comparator);

			runAntTaskWithExceptions();
		} catch (Exception e) {
			fail("Running mirror application with baseline compare", rootCause(e));
		} finally {
			System.setErr(oldErr);
			newErr.close();
			System.setOut(oldOut);
			newOut.close();
		}

		IArtifactRepository destination = null;
		try {
			destination = getArtifactRepositoryManager().loadRepository(destinationRepo, null);
		} catch (ProvisionException e) {
			fail("Error loading destination", e);
		}

		IArtifactDescriptor[] destDescriptors = destination.getArtifactDescriptors(descriptor2.getArtifactKey());
		assertEquals("Ensuring destination has correct number of descriptors", 1, destDescriptors.length);
		assertEquals("Ensuring destination contains the descriptor from the baseline", descriptor2.getProperty(IArtifactDescriptor.DOWNLOAD_MD5), destDescriptors[0].getProperty(IArtifactDescriptor.DOWNLOAD_MD5));
		String msg = NLS.bind(Messages.warning_differentMD5, new Object[] {URIUtil.toUnencodedString(baseline.getLocation()), URIUtil.toUnencodedString(repo.getLocation()), descriptor1});

		assertLogContains(msg);
	}

	private Map<String, String> getSliceProperties() {
		Map<String, String> p = new HashMap<String, String>();
		p.put("osgi.os", "win32");
		p.put("osgi.ws", "win32");
		p.put("osgi.arch", "x86");
		return p;
	}

	protected AntTaskElement createSlicingOption(Boolean includeOptional, Boolean includeNonGreedy, Boolean followStrict, Boolean includeFeatures, String platformFilter, String filter) {
		AntTaskElement slicing = new AntTaskElement("slicingoptions");
		if (followStrict != null)
			slicing.addAttribute("followstrict", followStrict.toString());
		if (includeFeatures != null)
			slicing.addAttribute("includefeatures", includeFeatures.toString());
		if (includeNonGreedy != null)
			slicing.addAttribute("includenongreedy", includeNonGreedy.toString());
		if (includeOptional != null)
			slicing.addAttribute("includeoptional", includeOptional.toString());
		if (platformFilter != null)
			slicing.addAttribute("platformfilter", platformFilter);
		if (filter != null)
			slicing.addAttribute("filter", filter);
		return slicing;
	}

	/*
	 * Create an IU for a descriptor and the IU+descriptor to the specified repo
	 */
	protected IArtifactRepository createRepositoryWithIU(URI repoLocation, IArtifactDescriptor descriptor) throws ProvisionException {
		IArtifactRepository artifactRepository = getArtifactRepositoryManager().createRepository(repoLocation, "Repo 1", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		artifactRepository.addDescriptor(descriptor);

		IMetadataRepository metaRepo = getMetadataRepositoryManager().createRepository(repoLocation, "Repo", IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		InstallableUnit iu = new InstallableUnit();
		iu.setId(descriptor.getArtifactKey().getId() + "IU");
		iu.setVersion(descriptor.getArtifactKey().getVersion());
		iu.setArtifacts(new IArtifactKey[] {descriptor.getArtifactKey()});
		metaRepo.addInstallableUnits(Arrays.asList((IInstallableUnit) iu));

		return artifactRepository;
	}

	/*
	 * Get the number of ArtifactKeys in a repository
	 */
	protected int getArtifactKeyCount(IQueryResult ius) {
		int count = 0;
		for (Iterator iter = ius.iterator(); iter.hasNext();)
			count += ((InstallableUnit) iter.next()).getArtifacts().size();
		return count;
	}

	/*
	 * Get the number of IUs in a repository
	 */
	protected int getIUCount(URI location) {
		try {
			return queryResultSize(getMetadataRepositoryManager().loadRepository(location, null).query(QueryUtil.createIUAnyQuery(), null));
		} catch (ProvisionException e) {
			fail("Failed to load repository " + URIUtil.toUnencodedString(location) + " for ArtifactDescriptor count");
			return -1;
		}
	}

	/*
	 * Add all IUs to the parent element
	 */
	protected void addAllIUs(AntTaskElement parent, IMetadataRepository repo) {
		IQueryResult queryResult = repo.query(QueryUtil.createIUAnyQuery(), null);

		for (Iterator iter = queryResult.iterator(); iter.hasNext();) {
			IInstallableUnit iu = (IInstallableUnit) iter.next();
			parent.addElement(createIUElement(iu));
		}
	}

	/*
	 * Create the base mirror task & add it to the script
	 */
	protected AntTaskElement createMirrorTask(String type) {
		AntTaskElement mirror = new AntTaskElement(MIRROR_TASK);
		mirror.addElement(getRepositoryElement(destinationRepo, type));
		addTask(mirror);
		return mirror;
	}

	/*
	 * Create a source element with the specified repositories
	 */
	protected AntTaskElement createSourceElement(URI artifact, URI metadata) {
		AntTaskElement source = new AntTaskElement("source");
		if (artifact != null)
			source.addElement(getRepositoryElement(artifact, AbstractAntProvisioningTest.TYPE_ARTIFACT));
		if (metadata != null)
			source.addElement(getRepositoryElement(metadata, AbstractAntProvisioningTest.TYPE_METADATA));
		return source;
	}
}
