Bug 220872 Many (many) attempts to read from the same invalid artifact repository
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/ArtifactRepositoryManager.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/ArtifactRepositoryManager.java
index b04440c..22cf4ac 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/ArtifactRepositoryManager.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/ArtifactRepositoryManager.java
@@ -60,6 +60,12 @@
 	//lock object to be held when referring to the repositories field
 	private final Object repositoryLock = new Object();
 
+	/**
+	 * Cache List of repositories that are not reachable. Maintain cache
+	 * for short duration because repository may become available at any time.
+	 */
+	private SoftReference unavailableRepositories;
+
 	public ArtifactRepositoryManager() {
 		//initialize repositories lazily
 	}
@@ -281,6 +287,8 @@
 		IArtifactRepository result = getRepository(location);
 		if (result != null)
 			return result;
+		if (checkNotFound(location))
+			fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
 		String[] suffixes = getAllSuffixes();
 		SubMonitor sub = SubMonitor.convert(monitor, suffixes.length * 100);
 		for (int i = 0; i < suffixes.length; i++) {
@@ -290,10 +298,42 @@
 				return result;
 			}
 		}
+		rememberNotFound(location);
 		fail(location, ProvisionException.REPOSITORY_NOT_FOUND);
 		return null;
 	}
 
+	/**
+	 * Check if we recently attempted to load the given location and failed
+	 * to find anything. Returns <code>true</code> if the repository was not
+	 * found, and <code>false</code> otherwise.
+	 */
+	private boolean checkNotFound(URL location) {
+		if (unavailableRepositories == null)
+			return false;
+		List badRepos = (List) unavailableRepositories.get();
+		if (badRepos == null)
+			return false;
+		return badRepos.contains(location);
+	}
+
+	/**
+	 * Cache the fact that we tried to load a repository at this location and did not find anything.
+	 */
+	private void rememberNotFound(URL location) {
+		List badRepos;
+		if (unavailableRepositories != null) {
+			badRepos = (List) unavailableRepositories.get();
+			if (badRepos != null) {
+				badRepos.add(location);
+				return;
+			}
+		}
+		badRepos = new ArrayList();
+		badRepos.add(location);
+		unavailableRepositories = new SoftReference(badRepos);
+	}
+
 	private IArtifactRepository loadRepository(URL location, String suffix, SubMonitor monitor) {
 		IExtension[] providers = findMatchingRepositoryExtensions(suffix);
 		// Loop over the candidates and return the first one that successfully loads
diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryManager.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryManager.java
index 691e9ac..fb48d95 100644
--- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryManager.java
+++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryManager.java
@@ -54,9 +54,16 @@
 	 * obtained vai getKey(URL).
 	 */
 	private Map repositories = null;
+
 	//lock object to be held when referring to the repositories field
 	private final Object repositoryLock = new Object();
 
+	/**
+	 * Cache List of repositories that are not reachable. Maintain cache
+	 * for short duration because repository may become available at any time.
+	 */
+	private SoftReference unavailableRepositories;
+
 	public MetadataRepositoryManager() {
 		//initialize repositories lazily
 	}
@@ -285,19 +292,55 @@
 		IMetadataRepository result = getRepository(location);
 		if (result != null)
 			return result;
+		MultiStatus notFoundStatus = new MultiStatus(Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, NLS.bind(Messages.repoMan_notExists, location.toExternalForm()), null);
+		if (checkNotFound(location))
+			throw new ProvisionException(notFoundStatus);
 		String[] suffixes = getAllSuffixes();
 		SubMonitor sub = SubMonitor.convert(monitor, Messages.REPOMGR_ADDING_REPO, suffixes.length * 100);
-		MultiStatus notFoundStatus = new MultiStatus(Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, NLS.bind(Messages.repoMan_notExists, location.toExternalForm()), null);
-		for (int i = 0; i < suffixes.length; i++) {
-			result = loadRepository(location, suffixes[i], sub.newChild(100), notFoundStatus);
-			if (result != null) {
-				addRepository(result);
-				sub.done();
-				return result;
+		try {
+			for (int i = 0; i < suffixes.length; i++) {
+				result = loadRepository(location, suffixes[i], sub.newChild(100), notFoundStatus);
+				if (result != null) {
+					addRepository(result);
+					return result;
+				}
+			}
+		} finally {
+			sub.done();
+		}
+		rememberNotFound(location);
+		throw new ProvisionException(notFoundStatus);
+	}
+
+	/**
+	 * Check if we recently attempted to load the given location and failed
+	 * to find anything. Returns <code>true</code> if the repository was not
+	 * found, and <code>false</code> otherwise.
+	 */
+	private boolean checkNotFound(URL location) {
+		if (unavailableRepositories == null)
+			return false;
+		List badRepos = (List) unavailableRepositories.get();
+		if (badRepos == null)
+			return false;
+		return badRepos.contains(location);
+	}
+
+	/**
+	 * Cache the fact that we tried to load a repository at this location and did not find anything.
+	 */
+	private void rememberNotFound(URL location) {
+		List badRepos;
+		if (unavailableRepositories != null) {
+			badRepos = (List) unavailableRepositories.get();
+			if (badRepos != null) {
+				badRepos.add(location);
+				return;
 			}
 		}
-		sub.done();
-		throw new ProvisionException(notFoundStatus);
+		badRepos = new ArrayList();
+		badRepos.add(location);
+		unavailableRepositories = new SoftReference(badRepos);
 	}
 
 	public IStatus validateRepositoryLocation(URL location, IProgressMonitor monitor) {