blob: 94bfaf543d95dd8bd3bf92ef90cc344678c0ceec [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006-2009, IBM Corporation and other.
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the copyright holder
* listed above, as the Initial Contributor under such license. The text of
* such license is available at www.eclipse.org.
*
* Contributors
* IBM Corporation - Initial API and implementation.
* Cloudsmith Inc - Implementation
******************************************************************************/
package org.eclipse.equinox.internal.p2.repository;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.net.URI;
import org.eclipse.core.runtime.*;
import org.eclipse.ecf.core.security.ConnectContextFactory;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.filetransfer.UserCancelledException;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.core.IServiceUI.AuthenticationInfo;
import org.eclipse.equinox.internal.provisional.p2.repository.IStateful;
import org.eclipse.osgi.util.NLS;
/**
* RepositoryTransport adapts p2 to ECF file download and file browsing.
* Download is performed by {@link FileReader}, and file browsing is performed by
* {@link FileInfoReader}.
*
* @author henrik.lindberg@cloudsmith.com
*
*/
public class RepositoryTransport extends Transport {
private static RepositoryTransport instance;
/**
* Returns an shared instance of Generic Transport
*/
public static synchronized RepositoryTransport getInstance() {
if (instance == null) {
instance = new RepositoryTransport();
}
return instance;
}
/**
* Perform a download, writing into the target output stream. Progress is reported on the
* monitor. If the <code>target</code> is an instance of {@link IStateful} the resulting status
* is also set on the target.
*
* @returns IStatus, that is a {@link DownloadStatus} on success.
* @param toDownload URI of file to download
* @param target OutputStream where result is written
* @param monitor where progress should be reported
*/
public IStatus download(URI toDownload, OutputStream target, IProgressMonitor monitor) {
boolean promptUser = false;
AuthenticationInfo loginDetails = null;
for (int i = RepositoryPreferences.getLoginRetryCount(); i > 0; i++) {
try {
loginDetails = Credentials.forLocation(toDownload, promptUser, loginDetails);
IConnectContext context = (loginDetails == null) ? null : ConnectContextFactory.createUsernamePasswordConnectContext(loginDetails.getUserName(), loginDetails.getPassword());
// perform the download
FileReader reader = new FileReader(context);
reader.readInto(toDownload, target, monitor);
// Download status is expected on success
DownloadStatus status = new DownloadStatus(IStatus.OK, Activator.ID, Status.OK_STATUS.getMessage());
status.setTransferRate(reader.getLastFileInfo().getAverageSpeed());
return statusOn(target, status);
} catch (UserCancelledException e) {
statusOn(target, Status.CANCEL_STATUS);
throw new OperationCanceledException();
} catch (CoreException e) {
return statusOn(target, RepositoryStatus.forStatus(e.getStatus(), toDownload));
} catch (FileNotFoundException e) {
return statusOn(target, RepositoryStatus.forException(e, toDownload));
} catch (AuthenticationFailedException e) {
promptUser = true;
}
}
// reached maximum number of retries without success
IStatus status = new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_FAILED_AUTHENTICATION, //
NLS.bind(Messages.UnableToRead_0_TooManyAttempts, toDownload), null);
return statusOn(target, status);
}
private static IStatus statusOn(OutputStream target, IStatus status) {
if (target instanceof IStateful)
((IStateful) target).setStatus(status);
return status;
}
/**
* Returns the last modified date for a URI. A last modified of 0 typically indicates that
* the server response is wrong, but should not be interpreted as a file not found.
* @param toDownload
* @param monitor
* @return last modified date (possibly 0)
*/
public long getLastModified(URI toDownload, IProgressMonitor monitor) throws UserCancelledException, CoreException, FileNotFoundException, AuthenticationFailedException {
boolean promptUser = false;
AuthenticationInfo loginDetails = null;
for (int i = RepositoryPreferences.getLoginRetryCount(); i > 0; i++) {
try {
loginDetails = Credentials.forLocation(toDownload, promptUser, loginDetails);
IConnectContext context = (loginDetails == null) ? null : ConnectContextFactory.createUsernamePasswordConnectContext(loginDetails.getUserName(), loginDetails.getPassword());
// get the remote info
FileInfoReader reader = new FileInfoReader(context);
return reader.getLastModified(toDownload, monitor);
} catch (CoreException e) {
// must translate this core exception as it is most likely not informative to a user
throw new CoreException(RepositoryStatus.forStatus(e.getStatus(), toDownload));
} catch (AuthenticationFailedException e) {
promptUser = true;
}
}
// reached maximum number of authentication retries without success
throw new AuthenticationFailedException();
}
}