Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 4947597437f9c8e031e81114b582cac09a995e63 (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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/*******************************************************************************
 *  Copyright (c) 2007, 2010 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.p2.operations;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.operations.*;
import org.eclipse.equinox.internal.p2.repository.helpers.RepositoryHelper;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.repository.IRepositoryManager;
import org.eclipse.osgi.util.NLS;

/**
 * RepositoryTracker defines a service that retrieves repositories, tracks their status, and
 * reports errors.
 * 
 * @since 2.0
 */
public abstract class RepositoryTracker {

	/**
	 * A status code used to indicate that a repository location was not valid.
	 */
	public static final int STATUS_INVALID_REPOSITORY_LOCATION = IStatusCodes.INVALID_REPOSITORY_LOCATION;

	// What repositories to show
	private int artifactRepositoryFlags = IRepositoryManager.REPOSITORIES_NON_SYSTEM;
	private int metadataRepositoryFlags = IRepositoryManager.REPOSITORIES_NON_SYSTEM;
	/**
	 * List<URI> of repositories that have already been reported to the user as not found.
	 */
	private final List<URI> reposNotFound = Collections.synchronizedList(new ArrayList<URI>());

	/**
	 * Return an array of repository locations known for the specified provisioning session.
	 * 
	 * @param session the provisioning session providing the provisioning services
	 * @return an array of repository locations known by this tracker
	 */
	public abstract URI[] getKnownRepositories(ProvisioningSession session);

	/**
	 * Return a status appropriate for reporting an invalid repository location.
	 * @param locationText the text representation of the location
	 * @return a status that describes an invalid location
	 */
	public IStatus getInvalidLocationStatus(String locationText) {
		return new Status(IStatus.ERROR, Activator.ID, IStatusCodes.INVALID_REPOSITORY_LOCATION, NLS.bind(Messages.RepositoryTracker_InvalidLocation, locationText), null);
	}

	/**
	 * Return a repository location represented by the supplied string. The provided
	 * string should either be an unencoded string representation of a URI, or a
	 * local file system path. This method is generally suitable for converting a 
	 * location string entered by an end user into a suitable URI representation.
	 * 
	 * @param locationString a text representation of the location
	 * @return a repository location URI, or <code>null</code> if the
	 * text could not be interpreted.
	 */
	public URI locationFromString(String locationString) {
		URI userLocation;
		try {
			userLocation = URIUtil.fromString(locationString);
		} catch (URISyntaxException e) {
			return null;
		}
		// If a path separator char was used, interpret as a local file URI
		String uriString = URIUtil.toUnencodedString(userLocation);
		if (uriString.length() > 0 && (uriString.charAt(0) == '/' || uriString.charAt(0) == File.separatorChar))
			return RepositoryHelper.localRepoURIHelper(userLocation);
		return userLocation;
	}

	/**
	 * Validate the specified repository location.
	 * 
	 * @param session the provisioning session providing the repository services
	 * @param location the location in question
	 * @param contactRepositories <code>true</code> if the appropriate repository manager(s) should be
	 * consulted regarding the validity of the location, or <code>false</code> if the repository manager
	 * should not be consulted.
	 * @param monitor the progress monitor
	 * @return a status indicating the current status of the repository
	 */

	public IStatus validateRepositoryLocation(ProvisioningSession session, URI location, boolean contactRepositories, IProgressMonitor monitor) {
		// First validate syntax issues
		IStatus localValidationStatus = RepositoryHelper.checkRepositoryLocationSyntax(location);
		if (!localValidationStatus.isOK()) {
			// bad syntax, but it could just be non-absolute.
			// In this case, use the helper
			String locationString = URIUtil.toUnencodedString(location);
			if (locationString.length() > 0 && (locationString.charAt(0) == '/' || locationString.charAt(0) == File.separatorChar)) {
				location = RepositoryHelper.localRepoURIHelper(location);
				localValidationStatus = RepositoryHelper.checkRepositoryLocationSyntax(location);
			}
		}

		if (!localValidationStatus.isOK())
			return localValidationStatus;

		if (contains(location, session))
			return new Status(IStatus.ERROR, Activator.ID, IStatusCodes.INVALID_REPOSITORY_LOCATION, Messages.RepositoryTracker_DuplicateLocation, null);
		return Status.OK_STATUS;
	}

	/**
	 * Return a boolean indicating whether this tracker already contains the specified
	 * repository location.
	 * 
	 * @param location the location in question
	 * @param session the provisioning session providing the repository services
	 * @since 2.1
	 */
	protected boolean contains(URI location, ProvisioningSession session) {
		// This is a fallback implementation in the absence of a repository manager
		// that would know what to do.
		URI[] knownRepositories = getKnownRepositories(session);
		for (int i = 0; i < knownRepositories.length; i++) {
			if (URIUtil.sameURI(knownRepositories[i], location)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Add the specified location to the list of "not found" repositories.
	 * This list is used to ensure that errors are not reported multiple times
	 * for the same repository.
	 * 
	 * The caller is already assumed to have reported any errors if necessary.
	 * 
	 * @param location the location of the repository that cannot be found
	 */
	public void addNotFound(URI location) {
		reposNotFound.add(location);
	}

	/**
	 * Answer a boolean indicating whether not found status has already been
	 * reported for the specified location.
	 * 
	 * @param location the location in question
	 * @return <code>true</code> if the repository has already been reported as
	 * being not found, <code>false</code> if no status has been reported for this
	 * location.
	 */
	public boolean hasNotFoundStatusBeenReported(URI location) {
		// We don't check for things like case variants or end slash variants
		// because we know that the repository managers already did this.
		return reposNotFound.contains(location);
	}

	/**
	 * Clear the list of repositories that have already been reported as not found.
	 */
	public void clearRepositoriesNotFound() {
		reposNotFound.clear();
	}

	/**
	 * Remove the specified repository from the list of repositories that
	 * have already been reported as not found.  This method has no effect
	 * if the repository has never been reported as not found.
	 * 
	 * @param location the location in question
	 */
	public void clearRepositoryNotFound(URI location) {
		reposNotFound.remove(location);
	}

	/**
	 * Return the repository flags suitable for retrieving known repositories from 
	 * a repository manager
	 * 
	 * @return the repository flags
	 * 
	 */
	public int getArtifactRepositoryFlags() {
		return artifactRepositoryFlags;
	}

	/**
	 * Set the repository flags suitable for retrieving known repositories from 
	 * a repository manager
	 * 
	 * @param flags the repository flags
	 * 
	 */
	public void setArtifactRepositoryFlags(int flags) {
		artifactRepositoryFlags = flags;
	}

	/**
	 * Return the repository flags suitable for retrieving known repositories from 
	 * a repository manager
	 * 
	 * @return the repository flags
	 * 
	 */
	public int getMetadataRepositoryFlags() {
		return metadataRepositoryFlags;
	}

	/**
	 * Set the repository flags suitable for retrieving known repositories from 
	 * a repository manager
	 * 
	 * @param flags the repository flags
	 * 
	 */

	public void setMetadataRepositoryFlags(int flags) {
		metadataRepositoryFlags = flags;
	}

	/**
	 * Report a failure to load the specified repository.
	 * <p>
	 * This default implementation simply logs the failure. Subclasses may override
	 * to provide additional error reporting.
	 * </p>
	 * @param location the location of the failed repository
	 * @param exception the failure that occurred
	 */
	public void reportLoadFailure(final URI location, ProvisionException exception) {
		// special handling when the repo location is bad.  We don't want to continually report it
		int code = exception.getStatus().getCode();
		if (code == IStatusCodes.INVALID_REPOSITORY_LOCATION || code == ProvisionException.REPOSITORY_INVALID_LOCATION || code == ProvisionException.REPOSITORY_NOT_FOUND) {
			if (hasNotFoundStatusBeenReported(location))
				return;
			addNotFound(location);
		}

		LogHelper.log(exception.getStatus());
	}

	/**
	 * Add a repository at the specified location.
	 *
	 * @param location the location of the new repository
	 * @param nickname the nickname for the repository, or <code>null</code> if there is no nickname
	 * @param session the session to use for provisioning services
	 */
	public abstract void addRepository(URI location, String nickname, ProvisioningSession session);

	/**
	 * Remove the repositories at the specified locations
	 *
	 * @param locations the locations
	 * @param session the session to use for provisioning services
	 */
	public abstract void removeRepositories(URI[] locations, ProvisioningSession session);

	/**
	 * Refresh the repositories at the specified locations
	 * @param locations the locations
	 * @param session the session to use for provisioning services
	 * @param monitor the progress monitor to use
	 */
	public abstract void refreshRepositories(URI[] locations, ProvisioningSession session, IProgressMonitor monitor);
}

Back to the top