diff options
4 files changed, 141 insertions, 1 deletions
diff --git a/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/Messages.java b/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/Messages.java index 824601623..3e334b23c 100644 --- a/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/Messages.java +++ b/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/Messages.java @@ -68,12 +68,19 @@ class Messages extends NLS { public static String RemoteBundleDiscoveryStrategy_unrecognized_discovery_url; + public static String SiteVerifier_Error_with_cause; + + public static String SiteVerifier_Unexpected_Error; + + public static String SiteVerifier_Verify_Job_Label; + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); } private Messages() { + // constructor } } diff --git a/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/SiteVerifier.java b/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/SiteVerifier.java new file mode 100644 index 000000000..bceca3fbd --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/SiteVerifier.java @@ -0,0 +1,128 @@ +package org.eclipse.equinox.internal.p2.discovery.compatibility; + +import java.net.URI; +import java.net.URL; +import java.util.*; +import java.util.concurrent.*; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; +import org.eclipse.equinox.internal.p2.discovery.Catalog; +import org.eclipse.equinox.internal.p2.discovery.DiscoveryCore; +import org.eclipse.equinox.internal.p2.discovery.compatibility.util.TransportUtil; +import org.eclipse.equinox.internal.p2.discovery.model.CatalogItem; +import org.eclipse.osgi.util.NLS; + +/** + * Verifies if site URIs point to valid P2 repositories. + * + * @author David Green + * @author Steffen Pingel + */ +public class SiteVerifier { + + private final Catalog catalog; + + public SiteVerifier(Catalog catalog) { + this.catalog = catalog; + } + + /** + * Determine update site availability. This may be performed automatically as part of discovery when + * {@link #isVerifyUpdateSiteAvailability()} is true, or it may be invoked later by calling this method. + */ + public void verifySiteAvailability(IProgressMonitor monitor) { + // NOTE: we don't put java.net.URLs in the map since it involves DNS activity when + // computing the hash code. + Map<String, Collection<CatalogItem>> urlToDescriptors = new HashMap<String, Collection<CatalogItem>>(); + + for (CatalogItem descriptor : catalog.getItems()) { + String url = descriptor.getSiteUrl(); + if (!url.endsWith("/")) { //$NON-NLS-1$ + url += "/"; //$NON-NLS-1$ + } + Collection<CatalogItem> collection = urlToDescriptors.get(url); + if (collection == null) { + collection = new ArrayList<CatalogItem>(); + urlToDescriptors.put(url, collection); + } + collection.add(descriptor); + } + final int totalTicks = urlToDescriptors.size(); + monitor.beginTask(Messages.SiteVerifier_Verify_Job_Label, totalTicks); + try { + if (!urlToDescriptors.isEmpty()) { + ExecutorService executorService = Executors.newFixedThreadPool(Math.min(urlToDescriptors.size(), 4)); + try { + List<Future<VerifyUpdateSiteJob>> futures = new ArrayList<Future<VerifyUpdateSiteJob>>(urlToDescriptors.size()); + for (String url : urlToDescriptors.keySet()) { + futures.add(executorService.submit(new VerifyUpdateSiteJob(url))); + } + for (Future<VerifyUpdateSiteJob> jobFuture : futures) { + try { + for (;;) { + try { + VerifyUpdateSiteJob job = jobFuture.get(1L, TimeUnit.SECONDS); + + Collection<CatalogItem> descriptors = urlToDescriptors.get(job.url); + for (CatalogItem descriptor : descriptors) { + descriptor.setAvailable(job.ok); + } + break; + } catch (TimeoutException e) { + if (monitor.isCanceled()) { + return; + } + } + } + } catch (InterruptedException e) { + monitor.setCanceled(true); + return; + } catch (ExecutionException e) { + if (e.getCause() instanceof OperationCanceledException) { + monitor.setCanceled(true); + return; + } + LogHelper.log(computeStatus(e, Messages.SiteVerifier_Unexpected_Error)); + } + monitor.worked(1); + } + } finally { + executorService.shutdownNow(); + } + } + } finally { + monitor.done(); + } + } + + private IStatus computeStatus(ExecutionException e, String message) { + Throwable cause = e.getCause(); + if (cause.getMessage() != null) { + message = NLS.bind(Messages.SiteVerifier_Error_with_cause, message, cause.getMessage()); + } + return new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, message, e); + } + + private static class VerifyUpdateSiteJob implements Callable<VerifyUpdateSiteJob> { + + private final String url; + + private boolean ok = false; + + public VerifyUpdateSiteJob(String url) { + this.url = url; + } + + public VerifyUpdateSiteJob call() throws Exception { + URL baseUrl = new URL(url); + List<URI> locations = new ArrayList<URI>(); + for (String location : new String[] {"content.jar", "content.xml", "site.xml"}) { //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + locations.add(new URL(baseUrl, location).toURI()); + } + ok = TransportUtil.verifyAvailability(locations, true, new NullProgressMonitor()); + return this; + } + + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/messages.properties b/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/messages.properties index 9a10066b5..d4c1a86b4 100644 --- a/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/messages.properties +++ b/bundles/org.eclipse.equinox.p2.discovery.compatibility/src/org/eclipse/equinox/internal/p2/discovery/compatibility/messages.properties @@ -32,3 +32,6 @@ RemoteBundleDiscoveryStrategy_task_remote_discovery=remote discovery RemoteBundleDiscoveryStrategy_unexpectedError=Unexpected error RemoteBundleDiscoveryStrategy_unknown_host_discovery_directory=Cannot access {0}: unknown host: please check your Internet connection and try again. RemoteBundleDiscoveryStrategy_unrecognized_discovery_url=Unrecognized discovery bundle URL: {0} +SiteVerifier_Error_with_cause={0}: {1} +SiteVerifier_Unexpected_Error=Unexpected error while verifying site availability +SiteVerifier_Verify_Job_Label=Verifying availability diff --git a/bundles/org.eclipse.equinox.p2.ui.discovery/src/org/eclipse/equinox/internal/p2/ui/discovery/wizards/CatalogViewer.java b/bundles/org.eclipse.equinox.p2.ui.discovery/src/org/eclipse/equinox/internal/p2/ui/discovery/wizards/CatalogViewer.java index 21b0c22a1..6bf54ecf1 100644 --- a/bundles/org.eclipse.equinox.p2.ui.discovery/src/org/eclipse/equinox/internal/p2/ui/discovery/wizards/CatalogViewer.java +++ b/bundles/org.eclipse.equinox.p2.ui.discovery/src/org/eclipse/equinox/internal/p2/ui/discovery/wizards/CatalogViewer.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.regex.Pattern; import org.eclipse.core.runtime.*; import org.eclipse.equinox.internal.p2.discovery.Catalog; +import org.eclipse.equinox.internal.p2.discovery.compatibility.SiteVerifier; import org.eclipse.equinox.internal.p2.discovery.model.*; import org.eclipse.equinox.internal.p2.discovery.util.CatalogCategoryComparator; import org.eclipse.equinox.internal.p2.discovery.util.CatalogItemComparator; @@ -590,7 +591,8 @@ public class CatalogViewer extends FilteredViewer { try { context.run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { - //discovery.verifySiteAvailability(monitor); + SiteVerifier verifier = new SiteVerifier(catalog); + verifier.verifySiteAvailability(monitor); } }); } catch (InvocationTargetException e) { |