/*******************************************************************************
* Copyright (c) 2011, 2013 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 java.io.File;
import java.io.IOException;
import java.util.List;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.orion.internal.server.servlets.Activator;
import org.eclipse.orion.server.core.tasks.ITaskService;
import org.eclipse.orion.server.core.tasks.TaskInfo;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
* Common base class for import/export over SFTP
*/
public abstract class SFTPTransferJob extends Job {
protected final String host;
protected final File localRoot;
private final List<String> options;
protected final String passphrase;
protected final int port;
protected final IPath remoteRoot;
protected TaskInfo task;
private ITaskService taskService;
private ServiceReference<ITaskService> taskServiceRef;
protected final String user;
public SFTPTransferJob(String userRunningTask, File localFile, String host, int port, IPath remotePath, String user, String passphrase, List<String> options) {
super("Transfer over SFTP"); //$NON-NLS-1$
this.localRoot = localFile;
this.host = host;
this.port = port;
this.remoteRoot = remotePath;
this.user = user;
this.passphrase = passphrase;
this.options = options;
this.task = createTask(userRunningTask, false);
task.setLengthComputable(true);
}
private void cleanUp() {
taskService = null;
if (taskServiceRef != null) {
Activator.getDefault().getContext().ungetService(taskServiceRef);
taskServiceRef = null;
}
}
protected TaskInfo createTask(String userId, boolean keep) {
TaskInfo info = getTaskService().createTask(userId, keep);
getTaskService().updateTask(info);
return info;
}
protected List<String> getOptions() {
return options;
}
public TaskInfo getTask() {
return task;
}
protected ITaskService getTaskService() {
if (taskService == null) {
BundleContext context = Activator.getDefault().getContext();
if (taskServiceRef == null) {
taskServiceRef = context.getServiceReference(ITaskService.class);
if (taskServiceRef == null)
throw new IllegalStateException("Task service not available"); //$NON-NLS-1$
}
taskService = context.getService(taskServiceRef);
if (taskService == null)
throw new IllegalStateException("Task service not available"); //$NON-NLS-1$
}
return taskService;
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
JSch jsch = new JSch();
IStatus result = null;
try {
Session session = jsch.getSession(user, host, port);
session.setPassword(passphrase);
//don't require host key to be in orion server's known hosts file
session.setConfig("StrictHostKeyChecking", "no"); //$NON-NLS-1$ //$NON-NLS-2$
session.connect();
try {
ChannelSftp channel = (ChannelSftp) session.openChannel("sftp"); //$NON-NLS-1$
try {
channel.connect();
transferDirectory(channel, remoteRoot, localRoot);
} finally {
channel.disconnect();
}
} finally {
session.disconnect();
}
} catch (Exception e) {
String msg = NLS.bind("Transfer from {0} failed: {1}", host + remoteRoot, e.getMessage());
result = new Status(IStatus.ERROR, Activator.PI_SERVER_SERVLETS, msg, e);
}
if (result == null) {
//fill in message to client for successful result
String msg = NLS.bind("Transfer complete: {0}", host + remoteRoot);
result = new Status(IStatus.OK, Activator.PI_SERVER_SERVLETS, msg);
}
//update task for both good or bad result cases
task.done(result);
getTaskService().updateTask(task);
return result;
} finally {
cleanUp();
}
}
protected void taskItemLoaded() {
task.setLoaded(task.getLoaded() + 1);
getTaskService().updateTask(task);
}
protected void addTaskTotal(int total) {
task.setTotal(task.getTotal() + total);
getTaskService().updateTask(task);
}
/**
* Returns whether the given file name should be ignored during transfer.
*/
protected boolean shouldSkip(String fileName) {
//skip parent and self references
if (".".equals(fileName) || "..".equals(fileName))//$NON-NLS-1$ //$NON-NLS-2$
return true;
//skip git metadata
return ".git".equals(fileName); //$NON-NLS-1$
}
/**
* Method overwritten by subclass to implement import/export
*/
protected abstract void transferDirectory(ChannelSftp channel, IPath remotePath, File localFile) throws SftpException, IOException;
}