blob: 152a3d09e9bc863847b43ccfefcfc0be86ba79dd [file] [log] [blame]
/*******************************************************************************
* 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 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);
}