/*******************************************************************************
* Copyright (c) 2009 Obeo.
* 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:
* Obeo - initial API and implementation
* CEA LIST - adaptation to Papyrus additional components
*******************************************************************************/
package org.eclipse.papyrus.infra.discovery.ui.viewer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.URIHandler;
import org.eclipse.emf.ecore.resource.impl.URIHandlerImpl;
import org.eclipse.papyrus.infra.discovery.DiscoveryDefinition;
import org.eclipse.papyrus.infra.discovery.InstallableComponent;
import org.eclipse.papyrus.infra.discovery.ui.Activator;
/**
* Updater that checks that features are available for installation
*/
public class AvailabilityUpdater {
private DiscoveryDefinitionBrowser discovery;
public AvailabilityUpdater(DiscoveryDefinition newdiscovery) {
this.discovery = new DiscoveryDefinitionBrowser(newdiscovery);
}
public void update(IProgressMonitor monitor) {
Collection<InstallableComponent> connectors = discovery
.getAllInstallableComponents();
Map<String, Collection<InstallableComponent>> urlToDescriptors = new HashMap<String, Collection<InstallableComponent>>();
for (InstallableComponent descriptor : connectors) {
for (String url : descriptor.getSitesURLS()) {
handleSiteURL(urlToDescriptors, descriptor, url);
}
}
final int totalTicks = urlToDescriptors.size();
monitor.beginTask("Checking update sites availability", 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<InstallableComponent> descriptors = urlToDescriptors
.get(job.url);
for (InstallableComponent 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;
}
IStatus status;
if (e.getCause() instanceof CoreException) {
status = ((CoreException) e.getCause())
.getStatus();
} else {
status = new Status(
IStatus.ERROR,
Activator.PLUGIN_ID,
"Error while checking update sites availability.",
e.getCause());
}
Activator.logHelper.error(status.getMessage(), status.getException());
}
monitor.worked(1);
}
} finally {
executorService.shutdownNow();
}
}
} finally {
monitor.done();
}
}
private void handleSiteURL(
Map<String, Collection<InstallableComponent>> urlToDescriptors,
InstallableComponent descriptor, String url) {
if (!url.endsWith("/")) { //$NON-NLS-1$
url += "/"; //$NON-NLS-1$
}
Collection<InstallableComponent> collection = urlToDescriptors.get(url);
if (collection == null) {
collection = new ArrayList<InstallableComponent>();
urlToDescriptors.put(url, collection);
}
collection.add(descriptor);
}
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 {
URI baseUrl = URI.createURI(removeTraillingSlash(url));
List<URI> locations = new ArrayList<URI>();
for (String location : new String[] {
"compositeContent.jar","content.jar", "content.xml", "site.xml" }) { //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
URI locationURI = baseUrl.appendSegment(location);
locations.add(locationURI);
}
URIHandler handler = new URIHandlerImpl();
Iterator<URI> it = locations.iterator();
while (it.hasNext() && !ok) {
URI uri = it.next();
if (handler.canHandle(uri)
&& handler.exists(uri, Collections.EMPTY_MAP))
ok = true;
}
return this;
}
private String removeTraillingSlash(String url2) {
if (url2.endsWith("/"))
return url2.substring(0, url2.length() - 1);
return url2;
}
}
}