diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RepositoryTracker.java')
-rw-r--r-- | bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RepositoryTracker.java | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RepositoryTracker.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RepositoryTracker.java new file mode 100644 index 000000000..8ef818e3c --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RepositoryTracker.java @@ -0,0 +1,275 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 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 org.eclipse.equinox.p2.core.ProvisionException; + +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.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 { + + // 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; + + // Syntax was ok, now look for duplicates + URI[] knownRepositories = getKnownRepositories(session); + for (int i = 0; i < knownRepositories.length; i++) { + if (URIUtil.sameURI(knownRepositories[i], location)) { + localValidationStatus = new Status(IStatus.ERROR, Activator.ID, IStatusCodes.INVALID_REPOSITORY_LOCATION, Messages.RepositoryTracker_DuplicateLocation, null); + break; + } + } + + if (!localValidationStatus.isOK()) + return localValidationStatus; + + if (contactRepositories) + return validateRepositoryLocationWithManager(session, location, monitor); + + return localValidationStatus; + } + + /** + * Validate the specified repository location using the appropriate repository manager. + * + * @param session the provisioning session providing the repository services + * @param location the location in question + * @param monitor the progress monitor + * @return a status indicating the current status of the repository + */ + protected abstract IStatus validateRepositoryLocationWithManager(ProvisioningSession session, URI location, IProgressMonitor monitor); + + /** + * 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); +} |