Skip to content
Snippets Groups Projects
Commit 92d5e48f authored by Jan Kožusznik's avatar Jan Kožusznik
Browse files

move java-scpclient to own project

parent f24a5277
Branches
No related tags found
1 merge request!38Cut to more projects
Showing
with 6 additions and 1248 deletions
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
<scm> <scm>
<url>https://code.it4i.cz/fiji/haas-java-client.git</url> <url>https://code.it4i.cz/fiji/haas-java-client.git</url>
<connection>scm:git:https://code.it4i.cz/fiji/haas-java-client.git</connection> <connection>scm:git:https://code.it4i.cz/fiji/haas-java-client.git</connection>
</scm> </scm>
<build> <build>
<plugins> <plugins>
...@@ -145,6 +144,12 @@ ...@@ -145,6 +144,12 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<repositories>
<repository>
<id>it4i</id>
<url>https://artifactory.cs.vsb.cz/it4i/</url>
</repository>
</repositories>
<distributionManagement> <distributionManagement>
<repository> <repository>
<id>it4i</id> <id>it4i</id>
......
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
/target/
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>java-scpclient</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cz.it4i.fiji</groupId>
<artifactId>java-scpclient</artifactId>
<version>1.0.0</version>
<name>Scp client library for Java</name>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<scm>
<url>https://code.it4i.cz/fiji/haas-java-client.git</url>
<connection>scm:git:https://code.it4i.cz/fiji/haas-java-client.git</connection>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Implementation-Build>${buildNumber}</Implementation-Build>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.25</version>
<optional>true</optional>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>it4i</id>
<url>https://artifactory.cs.vsb.cz/it4i/</url>
</repository>
<snapshotRepository>
<id>it4i</id>
<url>https://artifactory.cs.vsb.cz/it4i/</url>
</snapshotRepository>
</distributionManagement>
</project>
package cz.it4i.fiji.commons;
import java.io.Closeable;
import java.util.Timer;
import java.util.TimerTask;
public class DoActionEventualy implements Closeable {
private final Timer timer;
public DoActionEventualy(final long timeout, final Runnable runnable) {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
runnable.run();
}
}, timeout);
}
@Override
public void close() {
timer.cancel();
}
}
package cz.it4i.fiji.scpclient;
import com.jcraft.jsch.Identity;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
import java.io.Closeable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cz.it4i.fiji.commons.DoActionEventualy;
public class AbstractBaseSshClient implements Closeable {
protected static final int MAX_NUMBER_OF_CONNECTION_ATTEMPTS = 5;
protected static final long TIMEOUT_BETWEEN_CONNECTION_ATTEMPTS = 500;
private final static Logger log = LoggerFactory.getLogger(
AbstractBaseSshClient.class);
private String hostName;
private String username;
private final JSch jsch = new JSch();
private Session session;
private int port = 22;
public AbstractBaseSshClient(String hostName, String username,
byte[] privateKeyFile) throws JSchException
{
init(hostName, username, new ByteIdentity(jsch, privateKeyFile));
}
public AbstractBaseSshClient(String hostName, String username,
Identity privateKeyFile) throws JSchException
{
init(hostName, username, privateKeyFile);
}
public AbstractBaseSshClient(String hostName, String userName, String keyFile,
String pass) throws JSchException
{
Identity id = IdentityFile.newInstance(keyFile, null, jsch);
try {
if (pass != null) {
id.setPassphrase(pass.getBytes("UTF-8"));
}
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
init(hostName, userName, id);
}
public void setPort(int port) {
this.port = port;
}
@Override
public void close() {
if (session != null && session.isConnected()) {
// log.info("disconnect");
try (DoActionEventualy actionEventualy = new DoActionEventualy(
TIMEOUT_BETWEEN_CONNECTION_ATTEMPTS, this::interruptSessionThread))
{
session.disconnect();
}
}
session = null;
}
protected Session getConnectedSession() throws JSchException {
if (session == null) {
session = jsch.getSession(username, hostName, port);
UserInfo ui = new P_UserInfo();
session.setUserInfo(ui);
}
int connectRetry = 0;
long timoutBetweenRetry = TIMEOUT_BETWEEN_CONNECTION_ATTEMPTS;
while (!session.isConnected()) {
try {
session.connect();
}
catch (JSchException e) {
if (e.getMessage().contains("Auth fail") || e.getMessage().contains(
"Packet corrupt"))
{
if (connectRetry < MAX_NUMBER_OF_CONNECTION_ATTEMPTS) {
connectRetry++;
try {
Thread.sleep(timoutBetweenRetry);
timoutBetweenRetry *= 2;
}
catch (InterruptedException exc) {
log.info("Interruption detected");
throw new JSchException(exc.getMessage(), exc);
}
continue;
}
e = new AuthFailException(e.getMessage(), e);
}
throw e;
}
}
return session;
}
private void interruptSessionThread() {
try {
Field f = session.getClass().getDeclaredField("connectThread");
if (!f.isAccessible()) {
f.setAccessible(true);
Thread thread = (Thread) f.get(session);
thread.interrupt();
}
}
catch (NoSuchFieldException | SecurityException | IllegalArgumentException
| IllegalAccessException exc)
{
log.error(exc.getMessage(), exc);
}
}
private void init(String initHostName, String initUsername,
Identity privateKeyFile) throws JSchException
{
this.hostName = initHostName;
this.username = initUsername;
jsch.addIdentity(privateKeyFile, null);
}
private class P_UserInfo implements UserInfo {
@Override
public String getPassphrase() {
return null;
}
@Override
public String getPassword() {
return null;
}
@Override
public boolean promptPassword(String message) {
return false;
}
@Override
public boolean promptPassphrase(String message) {
return false;
}
@Override
public boolean promptYesNo(String message) {
return true;
}
@Override
public void showMessage(String message) {}
}
}
package cz.it4i.fiji.scpclient;
import java.io.IOException;
import java.io.InputStream;
public class AckowledgementChecker {
private int lastStatus;
private StringBuilder lastMessage;
public boolean checkAck(InputStream in) throws IOException {
lastMessage = new StringBuilder();
return checkAck(in, lastMessage);
}
public String getLastMessage() {
return lastMessage.toString();
}
public int getLastStatus() {
return lastStatus;
}
private boolean checkAck(InputStream in, StringBuilder sb) throws IOException {
lastStatus = in.read();
// b may be 0 for success,
// 1 for error,
// 2 for fatal error,
// -1
if (lastStatus == 0) return true;
if (lastStatus == -1) return false;
if (lastStatus == 1 || lastStatus == 2) {
int c;
do {
c = in.read();
sb.append((char) c);
}
while (c != '\n');
}
return lastStatus == 0;
}
}
package cz.it4i.fiji.scpclient;
import com.jcraft.jsch.JSchException;
public class AuthFailException extends JSchException {
public AuthFailException() {
}
public AuthFailException(String s) {
super(s);
}
public AuthFailException(String s, Throwable e) {
super(s, e);
}
}
package cz.it4i.fiji.scpclient;
import com.jcraft.jsch.Identity;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.KeyPair;
class ByteIdentity implements Identity{
private KeyPair keyPair;
public ByteIdentity(JSch jsch,byte []prvKey) throws JSchException {
this.keyPair = KeyPair.load(jsch, prvKey, null);
}
@Override
public boolean setPassphrase(byte[] passphrase) throws JSchException {
return keyPair.decrypt(passphrase);
}
@Override
public byte[] getPublicKeyBlob() {
return keyPair.getPublicKeyBlob();
}
@Override
public byte[] getSignature(byte[] data) {
return keyPair.getSignature(data);
}
@Override
public boolean decrypt() {
return false;
}
@Override
public String getAlgName() {
if(keyPair.getKeyType() == KeyPair.RSA) {
return "ssh-rsa";
} else if(keyPair.getKeyType() == KeyPair.DSA) {
return "ssh-dsa";
}
throw new UnsupportedOperationException("Key type:" + keyPair.getKeyType() + " not supported.");
}
@Override
public String getName() {
return keyPair.getPublicKeyComment();
}
@Override
public boolean isEncrypted() {
return keyPair.isEncrypted();
}
@Override
public void clear() {
keyPair.dispose();
keyPair = null;
}
}
package cz.it4i.fiji.scpclient;
import com.jcraft.jsch.Identity;
import com.jcraft.jsch.IdentityRepository;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.KeyPair;
class IdentityFile implements Identity {
private KeyPair kpair;
private String identity;
static IdentityFile newInstance(String prvfile, String pubfile, JSch jsch) throws JSchException {
KeyPair kpair = KeyPair.load(jsch, prvfile, pubfile);
return new IdentityFile(prvfile, kpair);
}
static IdentityFile newInstance(String name, byte[] prvkey, byte[] pubkey, JSch jsch) throws JSchException {
KeyPair kpair = KeyPair.load(jsch, prvkey, pubkey);
return new IdentityFile(name, kpair);
}
private IdentityFile(String name, KeyPair kpair) {
this.identity = name;
this.kpair = kpair;
}
/**
* Decrypts this identity with the specified pass-phrase.
*
* @param passphrase
* the pass-phrase for this identity.
* @return <tt>true</tt> if the decryption is succeeded or this identity is not
* cyphered.
*/
@Override
public boolean setPassphrase(byte[] passphrase) throws JSchException {
return kpair.decrypt(passphrase);
}
/**
* Returns the public-key blob.
*
* @return the public-key blob
*/
@Override
public byte[] getPublicKeyBlob() {
return kpair.getPublicKeyBlob();
}
/**
* Signs on data with this identity, and returns the result.
*
* @param data
* data to be signed
* @return the signature
*/
@Override
public byte[] getSignature(byte[] data) {
return kpair.getSignature(data);
}
/**
* @deprecated This method should not be invoked.
* @see #setPassphrase(byte[] passphrase)
*/
@Deprecated
@Override
public boolean decrypt() {
throw new RuntimeException("not implemented");
}
/**
* Returns the name of the key algorithm.
*
* @return "ssh-rsa" or "ssh-dss"
*/
@Override
public String getAlgName() {
if (kpair.getKeyType() == KeyPair.RSA) {
return "ssh-rsa";
} else if (kpair.getKeyType() == KeyPair.DSA) {
return "ssh-dsa";
}
throw new UnsupportedOperationException("Key type:" + kpair.getKeyType() + " not supported.");
}
/**
* Returns the name of this identity. It will be useful to identify this object
* in the {@link IdentityRepository}.
*/
@Override
public String getName() {
return identity;
}
/**
* Returns <tt>true</tt> if this identity is cyphered.
*
* @return <tt>true</tt> if this identity is cyphered.
*/
@Override
public boolean isEncrypted() {
return kpair.isEncrypted();
}
/**
* Disposes internally allocated data, like byte array for the private key.
*/
@Override
public void clear() {
kpair.dispose();
kpair = null;
}
/**
* Returns an instance of {@link KeyPair} used in this {@link Identity}.
*
* @return an instance of {@link KeyPair} used in this {@link Identity}.
*/
public KeyPair getKeyPair() {
return kpair;
}
}
package cz.it4i.fiji.scpclient;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.Identity;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.nio.channels.ClosedByInterruptException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ScpClient extends AbstractBaseSshClient {
public static final Logger log = LoggerFactory.getLogger(ScpClient.class);
private static final String NO_SUCH_FILE_OR_DIRECTORY_ERROR_TEXT =
"No such file or directory";
private static String constructExceptionText(AckowledgementChecker ack) {
return "Check acknowledgement failed with status: " + ack.getLastStatus() +
" and message: " + ack.getLastMessage();
}
private static final int BUFFER_SIZE = 4 * 1024 * 1024; // 4 MB
private final TransferFileProgress dummyProgress =
new TransferFileProgress()
{
@Override
public void dataTransfered(long bytesTransfered) {
}
};
public ScpClient(String hostName, String username, byte[] privateKeyFile)
throws JSchException
{
super(hostName, username, privateKeyFile);
}
public ScpClient(String hostName, String username, Identity privateKeyFile)
throws JSchException
{
super(hostName, username, privateKeyFile);
}
public ScpClient(String hostName, String userName, String keyFile,
String pass) throws JSchException
{
super(hostName, userName, keyFile, pass);
}
public void download(String lfile, Path rFile) throws JSchException,
IOException
{
download(lfile, rFile, dummyProgress);
}
public void download(String lfile, Path rfile, TransferFileProgress progress)
throws JSchException, IOException
{
if (!Files.exists(rfile.getParent())) {
Files.createDirectories(rfile.getParent());
}
try (OutputStream os = Files.newOutputStream(rfile)) {
download(lfile, os, progress);
}
}
public void download(String lfile, OutputStream os,
TransferFileProgress progress) throws JSchException, IOException
{
AckowledgementChecker ack = new AckowledgementChecker();
// exec 'scp -f rfile' remotely
lfile = sanityFileName(lfile);
String command = "scp -f " + lfile;
Channel channel = getConnectedSession().openChannel("exec");
try {
((ChannelExec) channel).setCommand(command);
// get I/O streams for remote scp
try (OutputStream out = channel.getOutputStream();
InputStream in = channel.getInputStream())
{
channel.connect();
byte[] buf = new byte[getBufferSize()];
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
while (true) {
ack.checkAck(in);
if (ack.getLastStatus() != 'C') {
break;
}
// read '0644 '
in.read(buf, 0, 5);
long filesize = 0L;
while (true) {
if (in.read(buf, 0, 1) < 0) {
// error
break;
}
if (buf[0] == ' ') break;
filesize = filesize * 10L + buf[0] - '0';
}
@SuppressWarnings("unused")
String file = null;
for (int i = 0;; i++) {
in.read(buf, i, 1);
if (buf[i] == (byte) 0x0a) {
file = new String(buf, 0, i);
break;
}
}
// System.out.println("filesize="+filesize+", file="+file);
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
// read a content of lfile
int foo;
while (true) {
if (buf.length < filesize) foo = buf.length;
else foo = (int) filesize;
foo = in.read(buf, 0, foo);
if (foo < 0) {
// error
break;
}
os.write(buf, 0, foo);
progress.dataTransfered(foo);
filesize -= foo;
if (filesize == 0L) break;
}
if (!ack.checkAck(in)) {
throw new JSchException(constructExceptionText(ack));
}
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
}
}
}
catch (ClosedByInterruptException e) {
throw new InterruptedIOException();
}
finally {
channel.disconnect();
}
}
public void upload(Path file, String rfile) throws JSchException,
IOException
{
upload(file, rfile, dummyProgress);
}
public void upload(Path file, String rfile, TransferFileProgress progress)
throws JSchException, IOException
{
try (InputStream is = Files.newInputStream(file)) {
upload(is, rfile, file.toFile().length(), file.toFile().lastModified(),
progress);
}
}
public void upload(InputStream is, String fileName, long length,
long lastModified, TransferFileProgress progress) throws JSchException,
IOException
{
int noSuchFileExceptionThrown = 0;
do {
try {
scp2Server(is, fileName, length, lastModified, progress);
break;
}
catch (NoSuchFileException e) {
if (noSuchFileExceptionThrown > MAX_NUMBER_OF_CONNECTION_ATTEMPTS) {
throw new JSchException(e.getReason());
}
if (noSuchFileExceptionThrown > 0) {
try {
Thread.sleep(TIMEOUT_BETWEEN_CONNECTION_ATTEMPTS);
}
catch (InterruptedException exc) {}
}
mkdir(e.getFile());
noSuchFileExceptionThrown++;
continue;
}
}
while (true);
}
public long size(String lfile) throws JSchException, IOException {
AckowledgementChecker ack = new AckowledgementChecker();
// exec 'scp -f rfile' remotely
lfile = sanityFileName(lfile);
String command = "scp -f " + lfile;
Channel channel = getConnectedSession().openChannel("exec");
try {
((ChannelExec) channel).setCommand(command);
// get I/O streams for remote scp
try (OutputStream out = channel.getOutputStream();
InputStream in = channel.getInputStream())
{
channel.connect();
byte[] buf = new byte[getBufferSize()];
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
while (true) {
ack.checkAck(in);
if (ack.getLastStatus() != 'C') {
break;
}
// read '0644 '
in.read(buf, 0, 5);
long filesize = 0L;
while (true) {
if (in.read(buf, 0, 1) < 0) {
// error
break;
}
if (buf[0] == ' ') break;
filesize = filesize * 10L + buf[0] - '0';
}
return filesize;
}
}
}
finally {
channel.disconnect();
}
return -1;
}
@SuppressWarnings("unchecked")
public List<Long> sizeByLs(String lfile) throws JSchException {
// exec 'scp -f rfile' remotely
Channel channel = getConnectedSession().openChannel("sftp");
lfile = sanityFileName(lfile);
try {
channel.connect();
return ((List<LsEntry>) ((ChannelSftp) channel).ls(lfile)).stream().map(
atr -> atr.getAttrs().getSize()).collect(Collectors.toList());
}
catch (SftpException e) {
e.printStackTrace();
}
finally {
channel.disconnect();
}
return null;
}
private int getBufferSize() {
return BUFFER_SIZE;
}
private void scp2Server(InputStream is, String fileName, long length,
long lastModified, TransferFileProgress progress) throws JSchException,
IOException, InterruptedIOException
{
AckowledgementChecker ack = new AckowledgementChecker();
boolean ptimestamp = false;
// exec 'scp -t rfile' remotely
fileName = sanityFileName(fileName);
String command = "scp " + (ptimestamp ? "-p" : "") + " -t " + fileName;
Channel channel = getConnectedSession().openChannel("exec");
((ChannelExec) channel).setCommand(command);
// get I/O streams for remote scp
try (OutputStream out = channel.getOutputStream();
InputStream in = channel.getInputStream())
{
channel.connect();
if (!ack.checkAck(in)) {
throw new JSchException(constructExceptionText(ack));
}
if (ptimestamp) {
command = "T " + (lastModified / 1000) + " 0";
// The access time should be sent here,
// but it is not accessible with JavaAPI ;-<
command += (" " + (lastModified / 1000) + " 0\n");
out.write(command.getBytes());
out.flush();
if (!ack.checkAck(in)) {
throw new JSchException(constructExceptionText(ack));
}
}
// send "C0644 filesize filename", where filename should not include '/'
long filesize = length;
command = "C0644 " + filesize + " ";
command += Paths.get(fileName).getFileName().toString();
command += "\n";
out.write(command.getBytes());
out.flush();
if (!ack.checkAck(in)) {
if (ack.getLastStatus() == 1 && ack.getLastMessage().contains(
NO_SUCH_FILE_OR_DIRECTORY_ERROR_TEXT))
{
throw new NoSuchFileException(getParent(fileName), null,
constructExceptionText(ack));
}
throw new JSchException(constructExceptionText(ack));
}
byte[] buf = new byte[getBufferSize()];
// send a content of lfile
while (true) {
int len = is.read(buf, 0, buf.length);
if (len <= 0) break;
out.write(buf, 0, len); // out.flush();
progress.dataTransfered(len);
}
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
if (!ack.checkAck(in)) {
throw new JSchException(constructExceptionText(ack));
}
out.close();
}
catch (ClosedByInterruptException e) {
Thread.interrupted();
throw new InterruptedIOException();
}
finally {
channel.disconnect();
}
}
private String sanityFileName(String fileName) {
fileName = fileName.replace("\"", "\\\\\\\"");
fileName = fileName.replace("'", "\\\\\\'");
fileName = "'" + fileName + "'";
return fileName;
}
private int mkdir(String file) throws JSchException {
ChannelExec channel = (ChannelExec) getConnectedSession().openChannel(
"exec");
file = sanityFileName(file);
channel.setCommand("mkdir -p '" + file + "'");
try {
channel.connect();
return channel.getExitStatus();
}
finally {
channel.disconnect();
}
}
private String getParent(String fileName) {
int index = fileName.lastIndexOf('/');
if (index == -1) {
return null;
}
return fileName.substring(0, index);
}
}
package cz.it4i.fiji.scpclient;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.Identity;
import com.jcraft.jsch.JSchException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SshCommandClient extends AbstractBaseSshClient {
private final static Logger log = LoggerFactory.getLogger(
SshCommandClient.class);
public SshCommandClient(String hostName, String username,
byte[] privateKeyFile) throws JSchException
{
super(hostName, username, privateKeyFile);
}
public SshCommandClient(String hostName, String username,
Identity privateKeyFile) throws JSchException
{
super(hostName, username, privateKeyFile);
}
public SshCommandClient(String hostName, String userName, String keyFile,
String pass) throws JSchException
{
super(hostName, userName, keyFile, pass);
}
public SshExecutionSession openSshExecutionSession(String command) {
try {
ChannelExec channelExec = (ChannelExec) getConnectedSession().openChannel(
"exec");
channelExec.setCommand(command);
channelExec.connect();
return new P_SshExecutionSession(channelExec);
}
catch (Exception e) {
log.error("Error: ", e);
throw new RuntimeException(e);
}
}
public List<String> executeCommand(String command) {
List<String> result = new LinkedList<>();
try (SshExecutionSession session = openSshExecutionSession(command)) {
BufferedReader reader = new BufferedReader(new InputStreamReader(session
.getStdout()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(
session.getStderr()));
String line;
while ((line = reader.readLine()) != null) {
result.add(line);
}
List<String> errors = new LinkedList<>();
while ((line = errReader.readLine()) != null) {
errors.add(line);
}
int exitStatus = session.getExitStatus();
if (exitStatus < 0) {
log.debug("Done, but exit status not set!");
}
else if (exitStatus > 0) {
log.debug("Done, but with error! ");
throw new SshExecuteCommandException(exitStatus, result, errors);
}
else {
log.debug("Done!");
}
}
catch (Exception e) {
log.error("Error: ", e);
throw new RuntimeException(e);
}
return result;
}
public boolean setPortForwarding(int lport, String rhost, int rport) {
try {
getConnectedSession().setPortForwardingL(lport, rhost, rport);
}
catch (JSchException exc) {
log.error("forward", exc);
return false;
}
return true;
}
private class P_SshExecutionSession implements SshExecutionSession {
private ChannelExec channel;
public P_SshExecutionSession(ChannelExec channel) {
this.channel = channel;
}
@Override
public InputStream getStdout() throws IOException {
return channel.getInputStream();
}
@Override
public InputStream getStderr() throws IOException {
return channel.getErrStream();
}
@Override
public int getExitStatus() {
return channel.getExitStatus();
}
@Override
public void close() {
channel.disconnect();
}
}
}
package cz.it4i.fiji.scpclient;
import com.jcraft.jsch.JSchException;
import java.util.List;
public class SshExecuteCommandException extends JSchException {
private int exitStatus;
private List<String> stdout;
private List<String> stderr;
public SshExecuteCommandException(int exitStatus, List<String> stdout,
List<String> stderr)
{
super("exitStatus: " + exitStatus + ", error output: " + String.join("\n",
stderr));
this.exitStatus = exitStatus;
this.stdout = stdout;
this.stderr = stderr;
}
public int getExitStatus() {
return exitStatus;
}
public List<String> getStdout() {
return stdout;
}
public List<String> getStderr() {
return stderr;
}
}
package cz.it4i.fiji.scpclient;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
public interface SshExecutionSession extends Closeable {
InputStream getStdout() throws IOException;
InputStream getStderr() throws IOException;
int getExitStatus();
@Override
void close();
}
package cz.it4i.fiji.scpclient;
public interface TransferFileProgress {
void dataTransfered(long bytesTransfered);
}
import java.io.IOException;
import com.jcraft.jsch.JSchException;
import cz.it4i.fiji.scpclient.ScpClient;
public class TestSCP {
public TestSCP() {
}
public static void main(String[] args) throws JSchException, IOException {
try(ScpClient scp = new ScpClient("salomon.it4i.cz", "koz01", "/home/koz01/.ssh/it4i_rsa-np", null)) {
// System.out.println( scp.upload(
// Paths.get("/home/koz01/Work/vyzkumnik/fiji/work/aaa/spim-data/exampleSingleChannel(9).czi"), "'/home/koz01/exampleSingleChannel(9).czi'"));
System.out.println( scp.size("'/home/koz01/exampleSingleChannel(9).czi'"));
}
}
}
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
<maven.deploy.skip>true</maven.deploy.skip> <maven.deploy.skip>true</maven.deploy.skip>
</properties> </properties>
<modules> <modules>
<module>java-scpclient</module>
<module>haas-java-client</module> <module>haas-java-client</module>
<module>haas-spim-benchmark</module> <module>haas-spim-benchmark</module>
<module>haas-imagej-client</module> <module>haas-imagej-client</module>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment