/*******************************************************************************
 *  Copyright (c) 2009, 2012 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 static org.junit.Assert.assertNotEquals;

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.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("unknown:/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("Expecting a CoreException", exception instanceof CoreException);
		assertEquals("Unexpected error code.", ProvisionException.REPOSITORY_NOT_FOUND, ((CoreException) exception).getStatus().getCode());
	}

	/*
	 * 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, Collections.<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);
		assertNotEquals("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;
	}
}
