| /******************************************************************************* |
| * 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); |
| } |