Bug 229069 [ui] Two of every category or repository visible in available software tab
diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.metadata.repository/META-INF/MANIFEST.MF
index 69198e4..fea541e 100644
--- a/bundles/org.eclipse.equinox.p2.metadata.repository/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.metadata.repository/META-INF/MANIFEST.MF
@@ -5,7 +5,7 @@
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Bundle-Version: 1.0.0.qualifier
-Export-Package: org.eclipse.equinox.internal.p2.metadata.repository;x-friends:="org.eclipse.equinox.p2.engine,org.eclipse.equinox.p2.metadata.generator,org.eclipse.equinox.p2.reconciler.dropins",
+Export-Package: org.eclipse.equinox.internal.p2.metadata.repository;x-friends:="org.eclipse.equinox.p2.engine,org.eclipse.equinox.p2.metadata.generator,org.eclipse.equinox.p2.reconciler.dropins, org.eclipse.equinox.p2.ui",
  org.eclipse.equinox.internal.p2.metadata.repository.io;x-friends:="org.eclipse.equinox.p2.engine",
  org.eclipse.equinox.internal.provisional.p2.metadata.repository;
   x-friends:="org.eclipse.equinox.p2.ui,
diff --git a/bundles/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF
index 5eb998e..7fb8e14 100644
--- a/bundles/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF
@@ -8,6 +8,7 @@
 Bundle-Activator: org.eclipse.equinox.internal.p2.ui.ProvUIActivator
 Import-Package: org.eclipse.equinox.internal.p2.core.helpers,
  org.eclipse.equinox.internal.p2.metadata,
+ org.eclipse.equinox.internal.p2.metadata.repository,
  org.eclipse.equinox.internal.p2.rollback,
  org.eclipse.equinox.internal.provisional.configurator,
  org.eclipse.equinox.internal.provisional.p2.artifact.repository,
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/MetadataRepositories.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/MetadataRepositories.java
index 9cbafbf..3d32654 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/MetadataRepositories.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/MetadataRepositories.java
@@ -16,6 +16,7 @@
 import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
 import org.eclipse.equinox.internal.provisional.p2.ui.policy.IQueryProvider;
 import org.eclipse.equinox.internal.provisional.p2.ui.query.ElementQueryDescriptor;
+import org.eclipse.equinox.internal.provisional.p2.ui.query.QueryableMetadataRepositoryManager;
 
 /**
  * Element class that represents some collection of metadata repositories.
@@ -133,4 +134,24 @@
 	protected boolean isSufficientForQuery(ElementQueryDescriptor queryDescriptor) {
 		return queryDescriptor.collector != null && queryDescriptor.queryable != null;
 	}
+
+	/*
+	 * Overridden to check whether the queryable repository manager
+	 * has loaded all repositories or not.
+	 * This is necessary to prevent background loading of already loaded repositories
+	 * by the DeferredTreeContentManager, which will add redundant children to the
+	 * viewer.  
+	 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=229069
+	 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=226343
+	 * (non-Javadoc)
+	 * @see org.eclipse.equinox.internal.provisional.p2.ui.query.QueriedElement#hasQueryable()
+	 */
+	public boolean hasQueryable() {
+		// We use the superclass implementation if we don't have a queryable or
+		// don't recognize it.  Also, if we are merely iterating sites rather
+		// than loading them to obtain further results, use the superclass
+		if (queryable == null || !(queryable instanceof QueryableMetadataRepositoryManager) || getQueryType() == IQueryProvider.METADATA_REPOS)
+			return super.hasQueryable();
+		return ((QueryableMetadataRepositoryManager) queryable).areRepositoriesLoaded();
+	}
 }
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/MetadataRepositoryElement.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/MetadataRepositoryElement.java
index 0cee548..b219b22 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/MetadataRepositoryElement.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/model/MetadataRepositoryElement.java
@@ -12,11 +12,15 @@
 
 import java.net.URL;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager;
+import org.eclipse.equinox.internal.p2.ui.ProvUIActivator;
 import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
 import org.eclipse.equinox.internal.p2.ui.model.RemoteQueriedElement;
 import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
 import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
 import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
 import org.eclipse.equinox.internal.provisional.p2.query.IQueryable;
 import org.eclipse.equinox.internal.provisional.p2.ui.ProvUI;
 import org.eclipse.equinox.internal.provisional.p2.ui.ProvUIImages;
@@ -170,4 +174,29 @@
 	public void setEnabled(boolean enabled) {
 		isEnabled = enabled;
 	}
+
+	/*
+	 * Overridden to check whether a repository instance has already been loaded.
+	 * This is necessary to prevent background loading of an already loaded repository
+	 * by the DeferredTreeContentManager, which will add redundant children to the
+	 * viewer.  
+	 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=229069
+	 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=226343
+	 * (non-Javadoc)
+	 * @see org.eclipse.equinox.internal.provisional.p2.ui.query.QueriedElement#hasQueryable()
+	 */
+	public boolean hasQueryable() {
+		if (queryable != null)
+			return true;
+		if (url == null)
+			return false;
+		IMetadataRepositoryManager manager = (IMetadataRepositoryManager) ServiceHelper.getService(ProvUIActivator.getContext(), IMetadataRepositoryManager.class.getName());
+		if (manager == null || !(manager instanceof MetadataRepositoryManager))
+			return false;
+		IMetadataRepository repo = ((MetadataRepositoryManager) manager).getRepository(url);
+		if (repo == null)
+			return false;
+		queryable = repo;
+		return true;
+	}
 }
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/query/QueryableMetadataRepositoryManager.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/query/QueryableMetadataRepositoryManager.java
index 2d172dd..16dcc4f 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/query/QueryableMetadataRepositoryManager.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/query/QueryableMetadataRepositoryManager.java
@@ -14,6 +14,7 @@
 import java.util.*;
 import org.eclipse.core.runtime.*;
 import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager;
 import org.eclipse.equinox.internal.p2.ui.ProvUIActivator;
 import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
 import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
@@ -166,4 +167,33 @@
 		// Reset the accumulated status so that next time we only report the newly not found repos.
 		accumulatedNotFound = null;
 	}
+
+	/**
+	 * Return a boolean indicating whether the repositories to be queried
+	 * are already loaded.
+	 * 
+	 * @return <code>true</code> if all repositories to be queried by the
+	 * receiver are loaded, <code>false</code> if they
+	 * are not.
+	 * 
+	 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=229069
+	 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=226343
+	 */
+	public boolean areRepositoriesLoaded() {
+		IMetadataRepositoryManager manager = (IMetadataRepositoryManager) ServiceHelper.getService(ProvUIActivator.getContext(), IMetadataRepositoryManager.class.getName());
+		if (manager == null || !(manager instanceof MetadataRepositoryManager)) {
+			return false;
+		}
+		MetadataRepositoryManager mgr = (MetadataRepositoryManager) manager;
+		List repoURLs = getRepoLocations(mgr);
+		for (int i = 0; i < repoURLs.size(); i++) {
+			if (repoURLs.get(i) instanceof URL) {
+				IMetadataRepository repo = mgr.getRepository((URL) repoURLs.get(i));
+				if (repo == null)
+					return false;
+			}
+		}
+		return true;
+
+	}
 }