package bndtools.views.repository; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.SortedSet; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import aQute.bnd.service.RemoteRepositoryPlugin; import aQute.bnd.service.RepositoryPlugin; import aQute.bnd.service.ResourceHandle; import aQute.bnd.service.ResourceHandle.Location; import aQute.bnd.service.Strategy; import aQute.bnd.version.Version; import bndtools.Plugin; import bndtools.model.repo.RepositoryBundle; import bndtools.model.repo.RepositoryBundleVersion; public class RepoDownloadJob extends Job { private static final Lock LOCK = new ReentrantLock(true); private final Collection<RemoteRepositoryPlugin> repos; private final Collection<RepositoryBundle> bundles; private final Collection<RepositoryBundleVersion> bundleVersions; public RepoDownloadJob(Collection<RemoteRepositoryPlugin> repos, Collection<RepositoryBundle> bundles, Collection<RepositoryBundleVersion> bundleVersions) { super("Downloading Repository Contents"); this.repos = repos; this.bundles = bundles; this.bundleVersions = bundleVersions; } @Override protected IStatus run(IProgressMonitor progress) { SubMonitor monitor = SubMonitor.convert(progress); boolean locked = LOCK.tryLock(); try { while (!locked) { monitor.setBlocked(new Status(IStatus.INFO, Plugin.PLUGIN_ID, 0, "Waiting for other download jobs to complete.", null)); if (progress.isCanceled()) return Status.CANCEL_STATUS; try { locked = LOCK.tryLock(5, TimeUnit.SECONDS); } catch (InterruptedException e) {} } monitor.clearBlocked(); MultiStatus status = new MultiStatus(Plugin.PLUGIN_ID, 0, "One or more repository files failed to download.", null); monitor.setTaskName("Expanding repository contents"); List<RepositoryBundleVersion> rbvs = new LinkedList<RepositoryBundleVersion>(); try { for (RemoteRepositoryPlugin repo : repos) { expandContentsInto(repo, rbvs); } for (RepositoryBundle bundle : bundles) { expandContentsInto(bundle, rbvs); } rbvs.addAll(bundleVersions); } catch (Exception e) { return new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, "Error listing repository contents", e); } monitor.setWorkRemaining(rbvs.size()); for (RepositoryBundleVersion rbv : rbvs) { if (monitor.isCanceled()) return Status.CANCEL_STATUS; String resourceName = "<<unknown>>"; try { RemoteRepositoryPlugin repo = (RemoteRepositoryPlugin) rbv.getRepo(); ResourceHandle handle = repo.getHandle(rbv.getBsn(), rbv.getVersion().toString(), Strategy.EXACT, Collections.<String, String> emptyMap()); resourceName = handle.getName(); Location location = handle.getLocation(); if (location == Location.remote) { monitor.setTaskName("Downloading " + handle.getName()); handle.request(); } } catch (Exception e) { status.add(new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, String.format("Download of %s:%s with remote name %s failed", rbv.getBsn(), rbv.getVersion(), resourceName), e)); } finally { monitor.worked(1); } } return status; } finally { if (locked) LOCK.unlock(); } } private void expandContentsInto(RemoteRepositoryPlugin repo, List<RepositoryBundleVersion> rbvs) throws Exception { List<String> bsns = repo.list(null); if (bsns != null) { for (String bsn : bsns) { RepositoryBundle bundle = new RepositoryBundle(repo, bsn); expandContentsInto(bundle, rbvs); } } } private void expandContentsInto(RepositoryBundle bundle, List<RepositoryBundleVersion> rbvs) throws Exception { RepositoryPlugin repo = bundle.getRepo(); SortedSet<Version> versions = repo.versions(bundle.getBsn()); if (versions != null) { for (Version version : versions) { RepositoryBundleVersion rbv = new RepositoryBundleVersion(bundle, version); rbvs.add(rbv); } } } @Override protected void canceling() { Thread myThread = getThread(); if (myThread != null) myThread.interrupt(); } }