bug 241430 - limit director to provided repos
diff --git a/bundles/org.eclipse.equinox.p2.console/src/org/eclipse/equinox/internal/p2/console/ProvisioningHelper.java b/bundles/org.eclipse.equinox.p2.console/src/org/eclipse/equinox/internal/p2/console/ProvisioningHelper.java
index 1ff0ec3..7441ce6 100644
--- a/bundles/org.eclipse.equinox.p2.console/src/org/eclipse/equinox/internal/p2/console/ProvisioningHelper.java
+++ b/bundles/org.eclipse.equinox.p2.console/src/org/eclipse/equinox/internal/p2/console/ProvisioningHelper.java
@@ -163,7 +163,9 @@
 		} else {
 			queryable = getMetadataRepository(location);
 		}
-		return queryable.query(query, collector, monitor);
+		if (queryable != null)
+			return queryable.query(query, collector, monitor);
+		return collector;
 	}
 
 	public static URI[] getMetadataRepositories() {
diff --git a/bundles/org.eclipse.equinox.p2.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.core/META-INF/MANIFEST.MF
index eea5211..65b3838 100644
--- a/bundles/org.eclipse.equinox.p2.core/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.core/META-INF/MANIFEST.MF
@@ -125,7 +125,8 @@
    org.eclipse.equinox.p2.updatesite,
    org.eclipse.equinox.p2.console,
    org.eclipse.equinox.p2.directorywatcher,
-   org.eclipse.equinox.p2.publisher",
+   org.eclipse.equinox.p2.publisher,
+   org.eclipse.equinox.p2.director.app",
  org.eclipse.equinox.internal.provisional.p2.query;
   x-friends:="org.eclipse.equinox.p2.artifact.optimizers,
    org.eclipse.equinox.p2.artifact.processors,
diff --git a/bundles/org.eclipse.equinox.p2.director.app/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.director.app/META-INF/MANIFEST.MF
index fa184b8..4498dd2 100644
--- a/bundles/org.eclipse.equinox.p2.director.app/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.director.app/META-INF/MANIFEST.MF
@@ -12,6 +12,7 @@
  org.eclipse.equinox.internal.provisional.p2.artifact.repository,
  org.eclipse.equinox.internal.provisional.p2.core,
  org.eclipse.equinox.internal.provisional.p2.core.location,
+ org.eclipse.equinox.internal.provisional.p2.core.repository,
  org.eclipse.equinox.internal.provisional.p2.director,
  org.eclipse.equinox.internal.provisional.p2.engine,
  org.eclipse.equinox.internal.provisional.p2.engine.phases,
diff --git a/bundles/org.eclipse.equinox.p2.director.app/src/org/eclipse/equinox/internal/p2/director/app/Application.java b/bundles/org.eclipse.equinox.p2.director.app/src/org/eclipse/equinox/internal/p2/director/app/Application.java
index a2d2090..7bf22b5 100644
--- a/bundles/org.eclipse.equinox.p2.director.app/src/org/eclipse/equinox/internal/p2/director/app/Application.java
+++ b/bundles/org.eclipse.equinox.p2.director.app/src/org/eclipse/equinox/internal/p2/director/app/Application.java
@@ -19,7 +19,8 @@
 import org.eclipse.equinox.app.IApplication;
 import org.eclipse.equinox.app.IApplicationContext;
 import org.eclipse.equinox.internal.p2.console.ProvisioningHelper;
-import org.eclipse.equinox.internal.p2.core.helpers.*;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
 import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
 import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
 import org.eclipse.equinox.internal.provisional.p2.director.*;
@@ -46,20 +47,16 @@
 
 	public static final String[] COMMAND_NAMES = {"-installIU", "-uninstallIU", "-list"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
-	//	private ServiceRegistration directorRegistration;
-	//	private ServiceRegistration plannerRegistration;
-	//	private ServiceRegistration engineRegistration;
-	//	private ServiceRegistration busRegistration;
-	//	private ServiceRegistration metadataManagerRegistration;
-	//	private ServiceRegistration artifactManagerRegistration;
-	//	private IProvisioningEventBus bus;
-
 	private Path destination;
 
 	private URI[] artifactRepositoryLocations;
-
 	private URI[] metadataRepositoryLocations;
 
+	private URI[] metadataReposForRemoval;
+	private URI[] artifactReposForRemoval;
+	private IArtifactRepositoryManager artifactManager;
+	private IMetadataRepositoryManager metadataManager;
+
 	private String root;
 	private Version version = null;
 	private String flavor;
@@ -168,15 +165,20 @@
 			if (throwException)
 				missingArgument("artifactRepository"); //$NON-NLS-1$
 		} else {
-			IArtifactRepositoryManager manager = (IArtifactRepositoryManager) ServiceHelper.getService(Activator.getContext(), IArtifactRepositoryManager.class.getName());
-			if (manager == null) {
+			artifactManager = (IArtifactRepositoryManager) ServiceHelper.getService(Activator.getContext(), IArtifactRepositoryManager.class.getName());
+			if (artifactManager == null) {
 				if (throwException)
 					throw new ProvisionException(Messages.Application_NoManager);
 			} else {
+				int removalIdx = 0;
 				boolean anyValid = false; // do we have any valid repos or did they all fail to load?
+				artifactReposForRemoval = new URI[artifactRepositoryLocations.length];
 				for (int i = 0; i < artifactRepositoryLocations.length; i++) {
 					try {
-						manager.loadRepository(artifactRepositoryLocations[i], null);
+						if (!artifactManager.contains(artifactRepositoryLocations[i])) {
+							artifactManager.loadRepository(artifactRepositoryLocations[i], null);
+							artifactReposForRemoval[removalIdx++] = artifactRepositoryLocations[i];
+						}
 						anyValid = true;
 					} catch (ProvisionException e) {
 						//one of the repositories did not load
@@ -193,15 +195,20 @@
 			if (throwException)
 				missingArgument("metadataRepository"); //$NON-NLS-1$
 		} else {
-			IMetadataRepositoryManager manager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.getContext(), IMetadataRepositoryManager.class.getName());
-			if (manager == null) {
+			metadataManager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.getContext(), IMetadataRepositoryManager.class.getName());
+			if (metadataManager == null) {
 				if (throwException)
 					throw new ProvisionException(Messages.Application_NoManager);
 			} else {
+				int removalIdx = 0;
 				boolean anyValid = false; // do we have any valid repos or did they all fail to load?
+				metadataReposForRemoval = new URI[metadataRepositoryLocations.length];
 				for (int i = 0; i < metadataRepositoryLocations.length; i++) {
 					try {
-						manager.loadRepository(metadataRepositoryLocations[i], null);
+						if (!metadataManager.contains(metadataRepositoryLocations[i])) {
+							metadataManager.loadRepository(metadataRepositoryLocations[i], null);
+							metadataReposForRemoval[removalIdx++] = metadataRepositoryLocations[i];
+						}
 						anyValid = true;
 					} catch (ProvisionException e) {
 						//one of the repositories did not load
@@ -375,46 +382,48 @@
 		IStatus operationStatus = Status.OK_STATUS;
 		InstallableUnitQuery query;
 		Collector roots;
-		switch (command) {
-			case COMMAND_INSTALL :
-			case COMMAND_UNINSTALL :
-				initializeRepositories(command == COMMAND_INSTALL);
+		try {
+			initializeRepositories(command == COMMAND_INSTALL);
+			switch (command) {
+				case COMMAND_INSTALL :
+				case COMMAND_UNINSTALL :
 
-				IProfile profile = initializeProfile();
-				query = new InstallableUnitQuery(root, version == null ? VersionRange.emptyRange : new VersionRange(version, true, version, true));
-				roots = ProvisioningHelper.getInstallableUnits(null, query, new LatestIUVersionCollector(), new NullProgressMonitor());
-				if (roots.size() <= 0)
-					roots = profile.query(query, roots, new NullProgressMonitor());
-				if (roots.size() <= 0) {
-					LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.Missing_IU, root)));
-					System.out.println(NLS.bind(Messages.Missing_IU, root));
-					return EXIT_ERROR;
-				}
-				if (!updateRoamingProperties(profile).isOK()) {
-					LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.Cant_change_roaming, profile.getProfileId())));
-					System.out.println(NLS.bind(Messages.Cant_change_roaming, profile.getProfileId()));
-					return EXIT_ERROR;
-				}
-				ProvisioningContext context = new ProvisioningContext();
-				ProfileChangeRequest request = buildProvisioningRequest(profile, roots, command == COMMAND_INSTALL);
-				printRequest(request);
-				operationStatus = planAndExecute(profile, context, request);
-				break;
-			case COMMAND_LIST :
-				query = new InstallableUnitQuery(null, VersionRange.emptyRange);
-				if (metadataRepositoryLocations == null)
-					missingArgument("metadataRepository"); //$NON-NLS-1$
+					IProfile profile = initializeProfile();
+					query = new InstallableUnitQuery(root, version == null ? VersionRange.emptyRange : new VersionRange(version, true, version, true));
+					roots = collectRootIUs(metadataRepositoryLocations, query, new LatestIUVersionCollector());
+					if (roots.size() <= 0)
+						roots = profile.query(query, roots, new NullProgressMonitor());
+					if (roots.size() <= 0) {
+						LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.Missing_IU, root)));
+						System.out.println(NLS.bind(Messages.Missing_IU, root));
+						return EXIT_ERROR;
+					}
+					if (!updateRoamingProperties(profile).isOK()) {
+						LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.Cant_change_roaming, profile.getProfileId())));
+						System.out.println(NLS.bind(Messages.Cant_change_roaming, profile.getProfileId()));
+						return EXIT_ERROR;
+					}
+					ProvisioningContext context = new ProvisioningContext(metadataRepositoryLocations);
+					context.setArtifactRepositories(artifactRepositoryLocations);
+					ProfileChangeRequest request = buildProvisioningRequest(profile, roots, command == COMMAND_INSTALL);
+					printRequest(request);
+					operationStatus = planAndExecute(profile, context, request);
+					break;
+				case COMMAND_LIST :
+					query = new InstallableUnitQuery(null, VersionRange.emptyRange);
+					if (metadataRepositoryLocations == null)
+						missingArgument("metadataRepository"); //$NON-NLS-1$
 
-				for (int i = 0; i < metadataRepositoryLocations.length; i++) {
-					roots = ProvisioningHelper.getInstallableUnits(metadataRepositoryLocations[i], query, new NullProgressMonitor());
-
+					roots = collectRootIUs(metadataRepositoryLocations, query, null);
 					Iterator unitIterator = roots.iterator();
 					while (unitIterator.hasNext()) {
 						IInstallableUnit iu = (IInstallableUnit) unitIterator.next();
 						System.out.println(iu.getId());
 					}
-				}
-				break;
+					break;
+			}
+		} finally {
+			cleanupRepositories();
 		}
 
 		time += System.currentTimeMillis();
@@ -428,6 +437,32 @@
 		return IApplication.EXIT_OK;
 	}
 
+	private void cleanupRepositories() {
+		if (artifactReposForRemoval != null && artifactManager != null) {
+			for (int i = 0; i < artifactReposForRemoval.length && artifactReposForRemoval[i] != null; i++) {
+				artifactManager.removeRepository(artifactReposForRemoval[i]);
+			}
+		}
+		if (metadataReposForRemoval != null && metadataManager != null) {
+			for (int i = 0; i < metadataReposForRemoval.length && metadataReposForRemoval[i] != null; i++) {
+				metadataManager.removeRepository(metadataReposForRemoval[i]);
+			}
+		}
+	}
+
+	private Collector collectRootIUs(URI[] locations, InstallableUnitQuery query, Collector collector) {
+		IProgressMonitor nullMonitor = new NullProgressMonitor();
+
+		if (locations == null || locations.length == 0)
+			return ProvisioningHelper.getInstallableUnits(null, query, collector, nullMonitor);
+
+		Collector result = collector != null ? collector : new Collector();
+		for (int i = 0; i < locations.length; i++) {
+			result = ProvisioningHelper.getInstallableUnits(locations[i], query, result, nullMonitor);
+		}
+		return result;
+	}
+
 	private synchronized void setPackageAdmin(PackageAdmin service) {
 		packageAdmin = service;
 	}
@@ -510,6 +545,8 @@
 				LogHelper.log(new Status(IStatus.WARNING, Activator.ID, NLS.bind(Messages.Ignored_repo, urlSpecs[i])));
 			}
 		}
+		if (result.size() == 0)
+			return null;
 		return (URI[]) result.toArray(new URI[result.size()]);
 	}
 
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/DirectorAppTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/DirectorAppTest.java
index 4323235..c93ee6e 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/DirectorAppTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/DirectorAppTest.java
@@ -8,13 +8,19 @@
  ******************************************************************************/
 package org.eclipse.equinox.p2.tests.director;
 
-import java.io.File;
+import java.io.*;
 import java.net.MalformedURLException;
 import java.util.HashMap;
 import java.util.Map;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.p2.director.app.Activator;
 import org.eclipse.equinox.internal.p2.director.app.Application;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
 import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepositoryManager;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
 import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
 import org.osgi.framework.Bundle;
 
@@ -31,6 +37,7 @@
 		application.start(new IApplicationContext() {
 
 			public void applicationRunning() {
+				//empty
 			}
 
 			public Map getArguments() {
@@ -527,4 +534,92 @@
 		//Cleanup: delete the folders
 		delete(destinationRepo);
 	}
+
+	/** 
+	 * Test that the application only considers repositories that are pass in and not those that are previously known
+	 * by the managers
+	 */
+	public void testOnlyUsePassedInRepos() throws Exception {
+		File artifactRepo1 = getTestData("12.0", "/testData/mirror/mirrorSourceRepo3");
+		File metadataRepo1 = getTestData("12.1", "/testData/mirror/mirrorSourceRepo3");
+
+		IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) ServiceHelper.getService(Activator.getContext(), IArtifactRepositoryManager.class.getName());
+		IMetadataRepositoryManager metadataManager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.getContext(), IMetadataRepositoryManager.class.getName());
+		assertNotNull(artifactManager);
+		assertNotNull(metadataManager);
+
+		//make repo3 known to the managers
+		artifactManager.loadRepository(artifactRepo1.toURI(), new NullProgressMonitor());
+		metadataManager.loadRepository(metadataRepo1.toURI(), new NullProgressMonitor());
+
+		int numKnownRepos = artifactManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length;
+		numKnownRepos += metadataManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length;
+
+		File artifactRepo2 = getTestData("12.2", "/testData/mirror/mirrorSourceRepo4");
+		File metadataRepo2 = getTestData("12.3", "/testData/mirror/mirrorSourceRepo4");
+		File destinationRepo = new File(getTempFolder(), "DirectorApp Destination");
+		String[] args = getSingleRepoArgs("12.4", metadataRepo2, artifactRepo2, destinationRepo, "yetanotherplugin");
+
+		destinationRepo.mkdirs();
+		PrintStream oldOut = System.out;
+		PrintStream newOut = new PrintStream(new FileOutputStream(destinationRepo + "/out.out"));
+		System.setOut(newOut);
+
+		try {
+			runDirectorApp("12.5", args);
+		} finally {
+			System.setOut(oldOut);
+			newOut.close();
+		}
+
+		assertLogContainsLine(new File(destinationRepo, "out.out"), "The installable unit yetanotherplugin has not been found.");
+
+		assertEquals(numKnownRepos, artifactManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length + metadataManager.getKnownRepositories(IRepositoryManager.REPOSITORIES_ALL).length);
+
+		artifactManager.removeRepository(artifactRepo1.toURI());
+		metadataManager.removeRepository(metadataRepo1.toURI());
+		delete(destinationRepo);
+	}
+
+	/**
+	 * Test the ProvisioningContext only uses the passed in repos and not all known repos.
+	 * Expect to install helloworld_1.0.0 not helloworld_1.0.1
+	 * @throws Exception
+	 */
+	public void testPassedInRepos_ProvisioningContext() throws Exception {
+		File artifactRepo1 = getTestData("13.0", "/testData/mirror/mirrorSourceRepo4");
+		File metadataRepo1 = getTestData("13.1", "/testData/mirror/mirrorSourceRepo4");
+
+		IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) ServiceHelper.getService(Activator.getContext(), IArtifactRepositoryManager.class.getName());
+		IMetadataRepositoryManager metadataManager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.getContext(), IMetadataRepositoryManager.class.getName());
+		assertNotNull(artifactManager);
+		assertNotNull(metadataManager);
+
+		//make repo4 known to the managers
+		artifactManager.loadRepository(artifactRepo1.toURI(), new NullProgressMonitor());
+		metadataManager.loadRepository(metadataRepo1.toURI(), new NullProgressMonitor());
+
+		File artifactRepo2 = getTestData("13.2", "/testData/mirror/mirrorSourceRepo3");
+		File metadataRepo2 = getTestData("13.3", "/testData/mirror/mirrorSourceRepo3");
+		File destinationRepo = new File(getTempFolder(), "DirectorApp Destination");
+		String[] args = getSingleRepoArgs("13.4", metadataRepo2, artifactRepo2, destinationRepo, "helloworld");
+
+		destinationRepo.mkdirs();
+		PrintStream oldOut = System.out;
+		PrintStream newOut = new PrintStream(new FileOutputStream(destinationRepo + "/out.out"));
+		System.setOut(newOut);
+
+		try {
+			runDirectorApp("13.5", args);
+		} finally {
+			System.setOut(oldOut);
+			newOut.close();
+		}
+
+		assertLogContainsLine(new File(destinationRepo, "out.out"), "Installing helloworld 1.0.0.");
+
+		artifactManager.removeRepository(artifactRepo1.toURI());
+		metadataManager.removeRepository(metadataRepo1.toURI());
+		delete(destinationRepo);
+	}
 }