Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 8fd617c2f9832e032eb29c2ead86e2a6c11ee04e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*******************************************************************************
 * Copyright (c) 2007, 2018 IBM Corporation and others.
 * 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:
 *     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;
	}

}

Back to the top