| /******************************************************************************* |
| * Copyright (c) 2007, 2018 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.ui; |
| |
| import java.net.URI; |
| import java.util.*; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.equinox.p2.core.ProvisionException; |
| import org.eclipse.equinox.p2.operations.ProvisioningSession; |
| import org.eclipse.equinox.p2.operations.RepositoryTracker; |
| import org.eclipse.equinox.p2.query.*; |
| import org.eclipse.equinox.p2.repository.IRepository; |
| import org.eclipse.equinox.p2.repository.IRepositoryManager; |
| import org.eclipse.equinox.p2.ui.ProvisioningUI; |
| import org.eclipse.osgi.util.NLS; |
| |
| /** |
| * An object that provides query support for a specified |
| * set of repositories. The repository tracker flags determine which repositories |
| * are included in the query. Callers interested in only the resulting repository URIs |
| * should specify a {@link RepositoryLocationQuery}, in which case the |
| * query is performed over the URI's. Otherwise the repositories are loaded and |
| * the query is performed over the repositories themselves. |
| */ |
| public abstract class QueryableRepositoryManager<T> implements IQueryable<T> { |
| private ProvisioningSession session; |
| protected boolean includeDisabledRepos; |
| protected RepositoryTracker tracker; |
| protected int repositoryFlags; |
| protected ProvisioningUI ui; |
| |
| public QueryableRepositoryManager(ProvisioningUI ui, boolean includeDisabledRepos) { |
| this.includeDisabledRepos = includeDisabledRepos; |
| this.ui = ui; |
| this.tracker = ui.getRepositoryTracker(); |
| this.session = ui.getSession(); |
| repositoryFlags = getRepositoryFlags(tracker); |
| } |
| |
| protected ProvisioningSession getSession() { |
| return session; |
| } |
| |
| /** |
| * Iterates over the repositories configured in this queryable. |
| * For most queries, the query is run on each repository, passing any objects that satisfy the |
| * query. |
| * <p> |
| * This method is long-running; progress and cancellation are provided |
| * by the given progress monitor. |
| * </p> |
| * |
| * @param query The query to perform.. |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting is not desired |
| * @return The QueryResult argument |
| */ |
| @Override |
| public IQueryResult<T> query(IQuery<T> query, IProgressMonitor monitor) { |
| IRepositoryManager<T> manager = getRepositoryManager(); |
| if (monitor == null) |
| monitor = new NullProgressMonitor(); |
| return query(getRepoLocations(manager), query, monitor); |
| } |
| |
| public IQueryable<URI> locationsQueriable() { |
| return (query, monitor) -> query.perform(getRepoLocations(getRepositoryManager()).iterator()); |
| } |
| |
| protected Collection<URI> getRepoLocations(IRepositoryManager<T> manager) { |
| Set<URI> locations = new HashSet<>(); |
| locations.addAll(Arrays.asList(manager.getKnownRepositories(repositoryFlags))); |
| if (includeDisabledRepos) { |
| locations.addAll(Arrays.asList(manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_DISABLED | repositoryFlags))); |
| } |
| return locations; |
| } |
| |
| /** |
| * Return a boolean indicating whether all the repositories that |
| * can be queried by the receiver are already loaded. If a repository |
| * is not loaded because it was not found, this will not return false, |
| * because this repository cannot be queried. |
| * |
| * @return <code>true</code> if all repositories to be queried by the |
| * receiver are loaded, <code>false</code> if they |
| * are not. |
| */ |
| public boolean areRepositoriesLoaded() { |
| IRepositoryManager<T> mgr = getRepositoryManager(); |
| if (mgr == null) |
| return false; |
| for (URI repoURI : getRepoLocations(mgr)) { |
| IRepository<T> repo = getRepository(mgr, repoURI); |
| // A not-loaded repo doesn't count if it's considered missing (not found) |
| if (repo == null && !tracker.hasNotFoundStatusBeenReported(repoURI)) |
| return false; |
| } |
| return true; |
| } |
| |
| protected abstract IRepository<T> getRepository(IRepositoryManager<T> manager, URI location); |
| |
| protected IRepository<T> loadRepository(IRepositoryManager<T> manager, URI location, IProgressMonitor monitor) throws ProvisionException { |
| monitor.setTaskName(NLS.bind(ProvUIMessages.QueryableMetadataRepositoryManager_LoadRepositoryProgress, URIUtil.toUnencodedString(location))); |
| IRepository<T> repo = doLoadRepository(manager, location, monitor); |
| return repo; |
| } |
| |
| /** |
| * Return the appropriate repository manager, or <code>null</code> if none could be found. |
| * @return the repository manager |
| */ |
| protected abstract IRepositoryManager<T> getRepositoryManager(); |
| |
| /** |
| * Return the flags that should be used to access repositories given the |
| * manipulator. |
| */ |
| protected abstract int getRepositoryFlags(RepositoryTracker repositoryManipulator); |
| |
| /** |
| * Load the repository located at the specified location. |
| * |
| * @param manager the manager |
| * @param location the repository location |
| * @param monitor the progress monitor |
| * @return the repository that was loaded, or <code>null</code> if no repository could |
| * be found at that location. |
| */ |
| protected abstract IRepository<T> doLoadRepository(IRepositoryManager<T> manager, URI location, IProgressMonitor monitor) throws ProvisionException; |
| |
| @SuppressWarnings("unchecked") |
| protected IQueryResult<T> query(Collection<URI> uris, IQuery<T> query, IProgressMonitor monitor) { |
| if (query instanceof RepositoryLocationQuery) { |
| return (IQueryResult<T>) locationsQueriable().query((IQuery<URI>) query, monitor); |
| } |
| SubMonitor sub = SubMonitor.convert(monitor, (uris.size() + 1) * 100); |
| ArrayList<IRepository<T>> loadedRepos = new ArrayList<>(uris.size()); |
| for (URI uri : uris) { |
| IRepository<T> repo = null; |
| try { |
| repo = loadRepository(getRepositoryManager(), uri, sub.newChild(100)); |
| } catch (ProvisionException e) { |
| tracker.reportLoadFailure(uri, e); |
| } catch (OperationCanceledException e) { |
| // user has canceled |
| repo = null; |
| } |
| if (repo != null) |
| loadedRepos.add(repo); |
| } |
| if (loadedRepos.size() > 0) { |
| return QueryUtil.compoundQueryable(loadedRepos).query(query, sub.newChild(100)); |
| } |
| return Collector.emptyCollector(); |
| } |
| |
| public void setRespositoryFlags(int flags) { |
| this.repositoryFlags = flags; |
| } |
| |
| } |