package deploy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.io.IOUtils;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class Scp {
private static final int FATAL_ERROR = 2;
private static final int ERROR = 1;
//private static final Logger log = Logger.getLogger(Scp.class);
public static void exec(final SecureContext pContext, String pLocalFile,
String pRemoteFile) throws JSchException, IOException {
if (pContext.getPassword() == null
&& pContext.getPrivateKeyFile() == null) {
throw new IllegalStateException(
"Must specifiy either a password or private key file");
}
FileInputStream fis = null;
OutputStream out = null;
InputStream in = null;
try {
Session session = pContext.createSession();
session.connect();
Channel channel = sendCommand(pRemoteFile, session);
out = channel.getOutputStream();
in = channel.getInputStream();
channel.connect();
if (checkAck(in) != 0) {
System.exit(0);
}
sendFileSize(pLocalFile, out, in);
fis = sendContent(pLocalFile, out, in);
out.close();
channel.disconnect();
session.disconnect();
} finally {
IOUtils.closeQuietly(fis);
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(in);
}
}
private static Channel sendCommand(String pRemoteFile, Session session)
throws JSchException {
// exec 'scp -t rfile' remotely
String command = "scp " + " -t " + pRemoteFile;
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
return channel;
}
private static FileInputStream sendContent(String pLocalFile,
OutputStream out, InputStream in) throws FileNotFoundException,
IOException {
FileInputStream fis;
// send a content of lfile
fis = new FileInputStream(pLocalFile);
byte[] buf = new byte[1024];
while (true) {
int len = fis.read(buf, 0, buf.length);
if (len <= 0)
break;
out.write(buf, 0, len); // out.flush();
}
fis.close();
fis = null;
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
if (checkAck(in) != 0) {
System.exit(0);
}
return fis;
}
private static void sendFileSize(String pLocalFile, OutputStream out,
InputStream in) throws IOException {
File _lfile = new File(pLocalFile);
// send "C0644 filesize filename", where filename should not include
// '/'
long filesize = _lfile.length();
String streamCommand = "C0644 " + filesize + " ";
if (pLocalFile.lastIndexOf('/') > 0) {
streamCommand += pLocalFile.substring(pLocalFile.lastIndexOf('/') + 1);
} else {
streamCommand += pLocalFile;
}
streamCommand += "\n";
out.write(streamCommand.getBytes());
out.flush();
if (checkAck(in) != 0) {
System.exit(0);
}
}
static int checkAck(InputStream in) throws IOException {
int b = in.read();
if (b == 0)
return b;
if (b == -1)
return b;
if (b == ERROR || b == FATAL_ERROR) {
StringBuffer sb = new StringBuffer();
int c;
do {
c = in.read();
sb.append((char) c);
} while (c != '\n');
if (b == ERROR) {
//log.error(sb.toString());
}
if (b == FATAL_ERROR) {
//log.error(sb.toString());
}
}
return b;
}
}