/*******************************************************************************
 *  Copyright (c) 2007, 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.metadata.repository;

import java.io.*;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.metadata.repository.SimpleMetadataRepositoryFactory;
import org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager;
import org.eclipse.equinox.internal.p2.updatesite.metadata.UpdateSiteMetadataRepositoryFactory;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.ProvisioningListener;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.SynchronousProvisioningListener;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.IAgentLocation;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.IRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.spi.MetadataRepositoryFactory;
import org.eclipse.equinox.p2.tests.*;

/**
 * Tests for API of {@link IMetadataRepositoryManager}.
 */
public class MetadataRepositoryManagerTest extends AbstractProvisioningTest {
	protected IMetadataRepositoryManager manager;
	/**
	 * Contains temp File handles that should be deleted at the end of the test.
	 */
	private final List toDelete = new ArrayList();

	public static Test suite() {
		return new TestSuite(MetadataRepositoryManagerTest.class);
	}

	protected void setUp() throws Exception {
		super.setUp();
		manager = (IMetadataRepositoryManager) getAgent().getService(IMetadataRepositoryManager.SERVICE_NAME);
		//only enable the failing repository factory for this test to avoid noise in other tests.
		FailingMetadataRepositoryFactory.FAIL = true;
	}

	protected void tearDown() throws Exception {
		super.tearDown();
		for (Iterator it = toDelete.iterator(); it.hasNext();)
			delete((File) it.next());
		toDelete.clear();
		FailingMetadataRepositoryFactory.FAIL = false;
	}

	public void testBasicAddRemove() {
		File tempFile = new File(System.getProperty("java.io.tmpdir"));
		URI location = tempFile.toURI();
		assertTrue(!managerContains(location));
		manager.addRepository(location);
		assertTrue(managerContains(location));
		manager.removeRepository(location);
		assertTrue(!managerContains(location));
	}

	/**
	 * Tests for {@link IRepositoryManager#contains(URI).
	 */
	public void testContains() {
		File site = getTestData("Repositoy", "/testData/metadataRepo/good/");
		URI location = site.toURI();
		manager.removeRepository(location);
		assertEquals("1.0", false, manager.contains(location));
		manager.addRepository(location);
		assertEquals("1.1", true, manager.contains(location));
		manager.removeRepository(location);
		assertEquals("1.2", false, manager.contains(location));
	}

	public void testEnablement() {
		File site = getTestData("Repositoy", "/testData/metadataRepo/good/");
		URI location = site.toURI();
		manager.addRepository(location);
		assertEquals("1.0", true, manager.isEnabled(location));
		TestRepositoryListener listener = new TestRepositoryListener(location);
		getEventBus().addListener(listener);

		manager.setEnabled(location, false);
		listener.waitForEvent();
		assertEquals("2.0", false, listener.lastEnablement);
		assertEquals("2.1", false, manager.isEnabled(location));
		listener.reset();

		manager.setEnabled(location, true);
		listener.waitForEvent();
		assertEquals("3.0", true, listener.lastEnablement);
		assertEquals("3.1", true, manager.isEnabled(location));
		listener.reset();
	}

	/**
	 * Adds a repository that has a non-standard (non ECF) scheme.  This should
	 * return REPOSITORY_NOT_FOUND, since any other status code gets logged.
	 * 
	 * @throws URISyntaxException
	 */
	public void testFailedConnection() throws URISyntaxException {
		URI location = new URI("invalid://example");
		MetadataRepositoryFactory factory;

		factory = new SimpleMetadataRepositoryFactory();
		factory.setAgent(getAgent());
		try {
			factory.load(location, 0, new NullProgressMonitor());
		} catch (ProvisionException e) {
			assertEquals(ProvisionException.REPOSITORY_INVALID_LOCATION, e.getStatus().getCode());
		}
		factory = new UpdateSiteMetadataRepositoryFactory();
		factory.setAgent(getAgent());
		try {
			factory.load(location, 0, new NullProgressMonitor());
		} catch (ProvisionException e) {
			assertEquals(ProvisionException.REPOSITORY_INVALID_LOCATION, e.getStatus().getCode());
		}
	}

	/**
	 * Tests that adding a repository that is already known but disabled
	 * causes the repository to be enabled. See bug 241307 for discussion.
	 */
	public void testEnablementOnAdd() {
		File site = getTestData("Repositoy", "/testData/metadataRepo/good/");
		URI location = site.toURI();
		manager.addRepository(location);
		manager.setEnabled(location, false);
		TestRepositoryListener listener = new TestRepositoryListener(location);
		getEventBus().addListener(listener);

		//adding the location again should cause it to be enabled
		manager.addRepository(location);
		listener.waitForEvent();
		assertEquals("1.0", true, listener.lastEnablement);
		assertEquals("1.1", true, manager.isEnabled(location));
	}

	public void testGetKnownRepositories() throws ProvisionException {
		int nonSystemCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_NON_SYSTEM).length;
		int systemCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_SYSTEM).length;
		int allCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length;
		assertEquals("1.0", allCount, nonSystemCount + systemCount);

		//create a new repository
		File repoLocation = getTempLocation();
		IMetadataRepository testRepo = manager.createRepository(repoLocation.toURI(), "MetadataRepositoryManagerTest", IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		int newNonSystemCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_NON_SYSTEM).length;
		int newSystemCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_SYSTEM).length;
		int newAllCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length;

		//there should be one more non-system repository
		assertEquals("2.0", nonSystemCount + 1, newNonSystemCount);
		assertEquals("2.1", systemCount, newSystemCount);
		assertEquals("2.2", allCount + 1, newAllCount);

		//make the repository a system repository
		testRepo.setProperty(IRepository.PROP_SYSTEM, Boolean.TRUE.toString());

		//there should be one more system repository
		newNonSystemCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_NON_SYSTEM).length;
		newSystemCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_SYSTEM).length;
		newAllCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length;
		assertEquals("3.0", nonSystemCount, newNonSystemCount);
		assertEquals("3.1", systemCount + 1, newSystemCount);
		assertEquals("3.2", allCount + 1, newAllCount);

		int disabledCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_DISABLED).length;
		allCount = newAllCount;

		//mark the repository as disabled
		manager.setEnabled(testRepo.getLocation(), false);

		//should be one less enabled repository and one more disabled repository
		int newDisabledCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_DISABLED).length;
		newAllCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length;
		assertEquals("4.0", disabledCount + 1, newDisabledCount);
		assertEquals("4.1", allCount - 1, newAllCount);

		//re-loading the repository should not change anything
		manager.loadRepository(testRepo.getLocation(), null);
		newDisabledCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_DISABLED).length;
		newAllCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length;
		assertEquals("5.0", disabledCount + 1, newDisabledCount);
		assertEquals("5.1", allCount - 1, newAllCount);

		//re-enable the repository
		manager.setEnabled(testRepo.getLocation(), true);

		//should be back to the original counts
		newDisabledCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_DISABLED).length;
		newAllCount = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length;
		assertEquals("6.0", disabledCount, newDisabledCount);
		assertEquals("6.1", allCount, newAllCount);
	}

	/**
	 * Tests contention for the repository load lock
	 */
	public void testLoadContention() {
		File site = getTestData("Repositoy", "/testData/metadataRepo/good/");
		final URI location = site.toURI();
		final List<Exception> failures = new ArrayList<Exception>();
		final IMetadataRepositoryManager repoManager = getMetadataRepositoryManager();
		class LoadJob extends Job {
			LoadJob() {
				super("");
			}

			@Override
			protected IStatus run(IProgressMonitor monitor) {
				for (int i = 0; i < 100; i++) {
					try {
						repoManager.loadRepository(location, null);
					} catch (Exception e) {
						failures.add(e);
					}
				}
				return Status.OK_STATUS;
			}
		}
		Job job1 = new LoadJob();
		Job job2 = new LoadJob();
		job1.schedule();
		job2.schedule();
		try {
			job1.join();
			job2.join();
		} catch (InterruptedException e) {
			fail("4.99", e);
		}
		if (!failures.isEmpty())
			fail("1.0", failures.iterator().next());
	}

	/**
	 * Tests loading a repository that does not exist throws an appropriate exception.
	 */
	public void testLoadMissingRepository() throws IOException {
		File tempFile = File.createTempFile("testLoadMissingArtifactRepository", null);
		tempFile.delete();
		URI location = tempFile.toURI();
		PrintStream out = System.out;
		try {
			System.setOut(new PrintStream(new StringBufferStream()));
			manager.loadRepository(location, null);
			fail("1.0");//should fail
		} catch (ProvisionException e) {
			assertEquals("1.1", IStatus.ERROR, e.getStatus().getSeverity());
			assertEquals("1.2", ProvisionException.REPOSITORY_NOT_FOUND, e.getStatus().getCode());
		} finally {
			System.setOut(out);
		}
	}

	/**
	 * Tests that loading a disabled system repository does not damage its properties.
	 * This is a regression test for bug 267707.
	 */
	public void testLoadDisabledSystemRepository() throws ProvisionException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
		File site = getTestData("Repositoy", "/testData/metadataRepo/goodNonSystem/");
		URI location = site.toURI();
		manager.removeRepository(location);
		manager.addRepository(location);
		manager.setEnabled(location, false);
		manager.setRepositoryProperty(location, IRepository.PROP_SYSTEM, String.valueOf(true));
		manager.loadRepository(location, getMonitor());

		//simulate shutdown/restart by bashing repository manager field
		Field field = AbstractRepositoryManager.class.getDeclaredField("repositories");
		field.setAccessible(true);
		field.set(manager, null);

		String system = manager.getRepositoryProperty(location, IRepository.PROP_SYSTEM);
		assertEquals("true", system);
		assertFalse(manager.isEnabled(location));

	}

	/**
	 * Tests loading a repository that is malformed
	 */
	public void testLoadBrokenRepository() {
		File site = getTestData("Repository", "/testData/metadataRepo/bad/");
		URI location = site.toURI();
		PrintStream err = System.err;
		try {
			System.setErr(new PrintStream(new StringBufferStream()));
			manager.loadRepository(location, null);
			fail("1.0");//should fail
		} catch (ProvisionException e) {
			assertEquals("1.1", IStatus.ERROR, e.getStatus().getSeverity());
			assertEquals("1.2", ProvisionException.REPOSITORY_FAILED_READ, e.getStatus().getCode());
		} finally {
			System.setErr(err);
		}
	}

	/**
	 * Tests loading a repository that is malformed, that is co-located with a well-formed
	 * update site repository. The load should fail due to the malformed simple repository,
	 * and not fall back to the well-formed update site repository. See bug 247566 for details.
	 */
	public void testLoadBrokenSimpleRepositoryWithGoodUpdateSite() {
		File site = getTestData("Repository", "/testData/metadataRepo/badSimpleGoodUpdateSite/");
		URI location = site.toURI();
		PrintStream err = System.err;
		try {
			System.setErr(new PrintStream(new StringBufferStream()));
			manager.loadRepository(location, null);
			fail("1.0");//should fail
		} catch (ProvisionException e) {
			assertEquals("1.1", IStatus.ERROR, e.getStatus().getSeverity());
			assertEquals("1.2", ProvisionException.REPOSITORY_FAILED_READ, e.getStatus().getCode());
		} finally {
			System.setErr(err);
		}
	}

	/**
	 * Tests that we don't create a local cache when contacting a local metadata repository.
	 */
	public void testMetadataCachingLocalRepo() throws ProvisionException {
		File repoLocation = getTempLocation();
		IAgentLocation agentLocation = (IAgentLocation) ServiceHelper.getService(TestActivator.getContext(), IAgentLocation.SERVICE_NAME);
		URI dataArea = agentLocation.getDataArea("org.eclipse.equinox.p2.metadata.repository/cache/");
		File dataAreaFile = URIUtil.toFile(dataArea);
		File cacheFileXML = new File(dataAreaFile, "content" + repoLocation.hashCode() + ".xml");
		File cacheFileJAR = new File(dataAreaFile, "content" + repoLocation.hashCode() + ".jar");

		// create a local repository
		manager.createRepository(repoLocation.toURI(), "MetadataRepositoryCachingTest", IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
		manager.loadRepository(repoLocation.toURI(), null);

		// check that a local cache was not created
		assertFalse("Cache file was created.", cacheFileXML.exists() || cacheFileJAR.exists());
	}

	/**
	 * Tests that local caching of remote metadata repositories works, and that the
	 * cache is updated when it becomes stale.
	 */
	public void testMetadataCachingRemoteRepo() throws URISyntaxException, ProvisionException {
		URI repoLocation = new URI("http://download.eclipse.org/eclipse/updates/3.4milestones/");
		if (!repoAvailable(repoLocation))
			return;
		IAgentLocation agentLocation = (IAgentLocation) ServiceHelper.getService(TestActivator.getContext(), IAgentLocation.SERVICE_NAME);
		URI dataArea = agentLocation.getDataArea("org.eclipse.equinox.p2.metadata.repository/cache/");
		File dataAreaFile = URIUtil.toFile(dataArea);
		File cacheFileXML = new File(dataAreaFile, "content" + repoLocation.hashCode() + ".xml");
		File cacheFileJAR = new File(dataAreaFile, "content" + repoLocation.hashCode() + ".jar");
		File cacheFile;

		// load a remote repository and check that a local cache was created
		manager.loadRepository(repoLocation, null);
		assertTrue("Cache file was not created.", cacheFileXML.exists() || cacheFileJAR.exists());
		if (cacheFileXML.exists())
			cacheFile = cacheFileXML;
		else
			cacheFile = cacheFileJAR;

		// modify the last modified date to be older than the remote file
		cacheFile.setLastModified(0);
		// reload the repository and check that the cache was updated
		manager.removeRepository(repoLocation);
		manager.loadRepository(repoLocation, null);
		long lastModified = cacheFile.lastModified();
		assertTrue(0 != lastModified);

		// reload the repository and check that the cache was not updated
		manager.loadRepository(repoLocation, null);
		assertEquals(lastModified, cacheFile.lastModified());

		cacheFile.delete();
	}

	public void testNickname() throws ProvisionException {
		File site = getTestData("Repositoy", "/testData/metadataRepo/good/");
		URI location = site.toURI();
		manager.addRepository(location);
		String nick = manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME);
		assertNull(nick);
		nick = "Nick";
		manager.setRepositoryProperty(location, IRepository.PROP_NICKNAME, nick);
		nick = manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME);
		assertEquals("Nick", nick);
		//ensure loading the repository doesn't affect the nickname
		manager.loadRepository(location, getMonitor());
		nick = manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME);
		assertEquals("Nick", nick);

		//remove and re-add the repository should lose the nickname
		manager.removeRepository(location);
		manager.loadRepository(location, getMonitor());
		nick = manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME);
		assertNull(nick);
	}

	public void testPathWithSpaces() {
		File site = getTestData("Repository", "/testData/metadataRepo/good with spaces/");
		URI location = site.toURI();
		try {
			IMetadataRepository repository = manager.loadRepository(location, getMonitor());
			IQueryResult result = repository.query(QueryUtil.createIUQuery("test.bundle"), getMonitor());
			assertEquals("1.0", 1, queryResultSize(result));
		} catch (ProvisionException e) {
			fail("=.99", e);
		}
	}

	public void testRelativePath() throws URISyntaxException {
		URI location = new URI("test");
		try {
			manager.loadRepository(location, getMonitor());
			fail();
		} catch (IllegalArgumentException e) {
			//expected
		} catch (ProvisionException e) {
			fail("4.99", e);
		}
	}

	/**
	 * Tests for {@link IMetadataRepositoryManager#refreshRepository(URI, org.eclipse.core.runtime.IProgressMonitor)}.
	 */
	public void testRefresh() throws ProvisionException {
		File site = getTestData("Repositoy", "/testData/metadataRepo/good/");
		URI location = site.toURI();
		manager.addRepository(location);
		manager.refreshRepository(location, getMonitor());
		assertTrue("1.0", manager.contains(location));
		assertTrue("1.1", manager.isEnabled(location));

		//tests that refreshing doesn't lose repository properties
		manager.setEnabled(location, false);
		manager.setRepositoryProperty(location, IRepository.PROP_NICKNAME, "MyNick");
		manager.refreshRepository(location, getMonitor());
		assertTrue("2.0", manager.contains(location));
		assertFalse("2.1", manager.isEnabled(location));
		assertEquals("2.2", "MyNick", manager.getRepositoryProperty(location, IRepository.PROP_NICKNAME));
	}

	/**
	 * Repository references were originally encoded as URL, but we now encode
	 * as URI. This test ensures we handle both old and new references.
	 */
	public void testRepositoryReferenceCompatibility() throws URISyntaxException {
		File site = getTestData("Repository", "/testData/metadataRepo/unencodedreporeferences/");
		URI location = site.toURI();
		final List references = new ArrayList();
		ProvisioningListener referenceCollector = new SynchronousProvisioningListener() {
			public void notify(EventObject o) {
				if (!(o instanceof RepositoryEvent))
					return;
				RepositoryEvent event = (RepositoryEvent) o;
				if (event.getKind() == RepositoryEvent.DISCOVERED)
					references.add(event.getRepositoryLocation());
			}
		};
		getEventBus().addListener(referenceCollector);
		try {
			manager.loadRepository(location, getMonitor());
		} catch (ProvisionException e) {
			fail("=.99", e);
		} finally {
			getEventBus().removeListener(referenceCollector);
		}
		assertEquals("1.0", 4, references.size());
		assertTrue("1.1", references.contains(new URI("http://download.eclipse.org/url/with/spaces/a%20b")));
		assertTrue("1.2", references.contains(new URI("file:/c:/tmp/url%20with%20spaces/")));
		assertTrue("1.3", references.contains(new URI("http://download.eclipse.org/uri/with/spaces/a%20b")));
		assertTrue("1.4", references.contains(new URI("file:/c:/tmp/uri%20with%20spaces/")));
	}

	/**
	 * Tests for {@link IRepositoryManager#setRepositoryProperty}.
	 */
	public void testSetRepositoryProperty() {
		File site = getTestData("Repositoy", "/testData/metadataRepo/good/");
		URI location = site.toURI();
		manager.removeRepository(location);
		manager.addRepository(location);

		//set some properties different from what the repository contains
		manager.setRepositoryProperty(location, IRepository.PROP_NAME, "TestName");
		manager.setRepositoryProperty(location, IRepository.PROP_DESCRIPTION, "TestDescription");
		manager.setRepositoryProperty(location, IRepository.PROP_SYSTEM, "false");
		assertEquals("1.0", "TestName", manager.getRepositoryProperty(location, IRepository.PROP_NAME));
		assertEquals("1.1", "TestDescription", manager.getRepositoryProperty(location, IRepository.PROP_DESCRIPTION));
		assertEquals("1.2", "false", manager.getRepositoryProperty(location, IRepository.PROP_SYSTEM));

		//loading the repository should overwrite test values
		try {
			manager.loadRepository(location, getMonitor());
		} catch (ProvisionException e) {
			fail("1.99", e);
		}

		assertEquals("2.0", "Good Test Repository", manager.getRepositoryProperty(location, IRepository.PROP_NAME));
		assertEquals("2.1", "Good test repository description", manager.getRepositoryProperty(location, IRepository.PROP_DESCRIPTION));
		assertEquals("2.2", "true", manager.getRepositoryProperty(location, IRepository.PROP_SYSTEM));
	}

	/**
	 * Tests that trailing slashes do not affect repository identity.
	 */
	public void testTrailingSlashes() {
		File site = getTestData("Repository", "/testData/metadataRepo/good/");
		URI locationSlash, locationNoSlash;
		try {
			locationSlash = site.toURI();
			String locationString = locationSlash.toString();
			locationString = locationString.substring(0, locationString.length() - 1);
			locationNoSlash = new URI(locationString);
		} catch (URISyntaxException e) {
			fail("0.99", e);
			return;
		}

		manager.addRepository(locationNoSlash);
		try {
			IMetadataRepository repoSlash = manager.loadRepository(locationSlash, null);
			IMetadataRepository repoNoSlash = manager.loadRepository(locationNoSlash, null);
			assertTrue("1.0", repoNoSlash == repoSlash);
		} catch (ProvisionException e) {
			fail("1.99", e);
		}
	}

	public void testReadableFilter() throws ProvisionException {
		File site = getTestData("readable", "/testData/metadataRepo/badFilter/readable");
		IMetadataRepository loadRepository = manager.loadRepository(site.toURI(), null);
		assertEquals(1, loadRepository.query(QueryUtil.createIUAnyQuery(), null).toSet().size());
	}

	public void testUnreadableFailingFilter() throws ProvisionException {
		File site = getTestData("unreadable", "/testData/metadataRepo/badFilter/unreadable");
		PrintStream out = System.out;
		try {
			System.setOut(new PrintStream(new StringBufferStream()));
			manager.loadRepository(site.toURI(), null);
		} catch (ProvisionException e) {
			return;
		} finally {
			System.setOut(out);
		}
		fail("Unexpected code path, the unreadable repo should not have loaded");

	}

	private boolean repoAvailable(URI repoLocation) {
		try {
			repoLocation.toURL().openStream().close();
		} catch (IOException e) {
			return false;
		}
		return true;
	}

	/**
	 * Returns a non-existent file that can be used to write a temporary
	 * file or directory. The location will be deleted in the test tearDown method.
	 */
	private File getTempLocation() {
		File tempDir = new File(System.getProperty("java.io.tmpdir"));
		File tempFile = new File(tempDir, "MetadataRepositoryManagerTest");
		delete(tempFile);
		assertTrue(!tempFile.exists());
		toDelete.add(tempFile);
		return tempFile;
	}

	public void testFailureAddRemove() {
		try {
			manager.addRepository(null);
			fail();
		} catch (RuntimeException e) {
			//expected
		}
		try {
			manager.removeRepository(null);
			fail();
		} catch (RuntimeException e) {
			//expected
		}
	}

	/**
	 * Returns whether {@link IMetadataRepositoryManager} contains a reference
	 * to a repository at the given location.
	 */
	private boolean managerContains(URI location) {
		URI[] locations = manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL);
		for (int i = 0; i < locations.length; i++) {
			if (locations[i].equals(location))
				return true;
		}
		return false;
	}
}
