/*******************************************************************************
* Copyright (c) 2011, 2014 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.orion.internal.server.servlets.xfer;
import com.jcraft.jsch.*;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import java.io.*;
import java.util.List;
import java.util.Vector;
import org.eclipse.core.runtime.IPath;
import org.eclipse.orion.server.core.IOUtilities;
import org.eclipse.orion.server.core.ProtocolConstants;
import org.eclipse.osgi.util.NLS;
/**
* Implementation of background import into workspace over SFTP.
*/
public class SFTPImportJob extends SFTPTransferJob {
public SFTPImportJob(String userRunningTask, File destination, String host, int port, IPath sourcePath, String user, String passphrase, List<String> options) {
super(userRunningTask, destination, host, port, sourcePath, user, passphrase, options);
}
protected void doTransferDirectory(ChannelSftp channel, IPath remotePath, SftpATTRS remoteAttributes, File localFile) throws SftpException, IOException {
//create the local folder on import
localFile.mkdirs();
@SuppressWarnings("unchecked")
Vector<LsEntry> remoteChildren = channel.ls(remotePath.toString());
addTaskTotal(remoteChildren.size());
//visit remote children
for (LsEntry remoteChild : remoteChildren) {
String childName = remoteChild.getFilename();
if (shouldSkip(childName)) {
taskItemLoaded();
continue;
}
File localChild = new File(localFile, childName);
if (remoteChild.getAttrs().isDir()) {
doTransferDirectory(channel, remotePath.append(childName), remoteChild.getAttrs(), localChild);
} else {
doTransferFile(channel, remotePath.append(childName), remoteChild.getAttrs(), localChild);
}
taskItemLoaded();
}
synchronizeTimestamp(remoteAttributes, localFile);
}
protected void doTransferFile(ChannelSftp channel, IPath remotePath, SftpATTRS remoteAttributes, File localFile) throws IOException, SftpException {
if (shouldSkip(remotePath, remoteAttributes, localFile))
return;
//on import, copy the remote file to the local destination
IOUtilities.pipe(channel.get(remotePath.toString()), new FileOutputStream(localFile), true, true);
synchronizeTimestamp(remoteAttributes, localFile);
}
/**
* Check if we should skip writing this file due to timestamp checks and overwrite options.
* @throws IOException If the operation should abort completely
*/
private boolean shouldSkip(IPath remotePath, SftpATTRS remoteAttributes, File localFile) throws IOException {
//abort the entire import if we have a collision and no-overwrite is specified
if (getOptions().contains(ProtocolConstants.OPTION_NO_OVERWRITE) && localFile.exists()) {
IPath localPath = remotePath.removeFirstSegments(remoteRoot.segmentCount());
throw new IOException(NLS.bind("Local file exists: {0}", localPath.toString()));
}
//time is expressed as seconds since the epoch
int localMTime = (int) (localFile.lastModified() / 1000L);
int remoteMTime = remoteAttributes.getMTime();
//check if we should skip overwrite of newer files
if (getOptions().contains(ProtocolConstants.OPTION_OVERWRITE_OLDER) && localMTime > remoteMTime)
return true;
//skip file if unchanged
if (localMTime == remoteMTime && localFile.length() == remoteAttributes.getSize())
return true;
return false;
}
private void synchronizeTimestamp(SftpATTRS remoteAttributes, File localFile) {
localFile.setLastModified(remoteAttributes.getMTime() * 1000L);
}
@Override
protected void transferDirectory(ChannelSftp channel, IPath remotePath, File localFile) throws SftpException, IOException {
SftpATTRS attrs = channel.stat(remotePath.toString());
doTransferDirectory(channel, remotePath, attrs, localFile);
}
}