├── .gitignore
├── LICENSE
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── github
│ └── sparsick
│ └── ssh4j
│ ├── JSchClient.java
│ ├── SshClient.java
│ ├── SshJClient.java
│ └── VfsSftpClient.java
└── test
├── java
└── com
│ └── github
│ └── sparsick
│ └── ssh4j
│ ├── JSchClientIT.java
│ ├── SshClientIT.java
│ ├── SshJClientIT.java
│ └── VfsSftpClientIT.java
└── resources
├── id_rsa
├── id_rsa.pub
├── known_hosts
└── test.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 | /target/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Sandra Parsick
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | 4.0.0
6 |
7 | com.github.sparsick.ssh4j
8 | comparison-ssh-java
9 | 1.0.0-SNAPSHOT
10 |
11 | SSH libraries for Java in Comparison
12 |
13 |
14 | 1.8
15 | UTF-8
16 |
17 |
18 |
19 |
20 | com.hierynomus
21 | sshj
22 | 0.12.0
23 |
24 |
25 | org.apache.commons
26 | commons-vfs2
27 | 2.0
28 |
29 |
30 | com.jcraft
31 | jsch
32 | 0.1.53
33 |
34 |
35 | junit
36 | junit
37 | 4.12
38 | test
39 |
40 |
41 | org.assertj
42 | assertj-core
43 | 3.0.0
44 | test
45 |
46 |
47 |
48 |
49 |
50 |
51 | maven-compiler-plugin
52 | 2.3.2
53 |
54 | ${java.version}
55 | ${java.version}
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sparsick/ssh4j/JSchClient.java:
--------------------------------------------------------------------------------
1 | package com.github.sparsick.ssh4j;
2 |
3 | import com.jcraft.jsch.ChannelExec;
4 | import com.jcraft.jsch.ChannelSftp;
5 | import com.jcraft.jsch.JSch;
6 | import com.jcraft.jsch.JSchException;
7 | import com.jcraft.jsch.Session;
8 | import com.jcraft.jsch.SftpException;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.io.OutputStream;
12 | import java.nio.file.Files;
13 | import java.nio.file.Path;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | public class JSchClient implements SshClient {
18 |
19 | private String password;
20 | private String user;
21 | private Path privateKey;
22 | private Session session;
23 | private Path knownHosts;
24 |
25 | @Override
26 | public void authUserPassword(String user, String password) {
27 | this.user = user;
28 | this.password = password;
29 | }
30 |
31 | @Override
32 | public void authUserPublicKey(String user, Path privateKey) {
33 | this.user = user;
34 | this.privateKey = privateKey;
35 | }
36 |
37 | @Override
38 | public void setKnownHosts(Path knownHosts) {
39 | this.knownHosts = knownHosts;
40 | }
41 |
42 | @Override
43 | public void connect(String host) throws IOException {
44 | if (session == null) {
45 | try {
46 | JSch sshClient = new JSch();
47 | if (privateKey != null) {
48 | sshClient.addIdentity(privateKey.toString());
49 | }
50 | if (knownHosts != null) {
51 | sshClient.setKnownHosts(knownHosts.toString());
52 | } else {
53 | sshClient.setKnownHosts("~/.ssh/known_hosts");
54 | }
55 |
56 | session = sshClient.getSession(user, host);
57 | if (password != null) {
58 | session.setPassword(password);
59 | } else if (privateKey == null){
60 | throw new IOException("Either privateKey nor password is set. Please call one of the authentication method.");
61 | }
62 | session.connect();
63 | } catch (JSchException ex) {
64 | throw new IOException(ex);
65 | }
66 | }
67 |
68 | }
69 |
70 | @Override
71 | public void disconnect() {
72 | if (session != null) {
73 | session.disconnect();
74 | session = null;
75 | }
76 | }
77 |
78 | @Override
79 | public void download(String remotePath, Path local) throws IOException {
80 | ChannelSftp sftpChannel = null;
81 | try {
82 | sftpChannel = (ChannelSftp) session.openChannel("sftp");
83 | sftpChannel.connect();
84 | InputStream inputStream = sftpChannel.get(remotePath);
85 | Files.copy(inputStream, local);
86 | } catch (SftpException | JSchException ex) {
87 | throw new IOException(ex);
88 | } finally {
89 | if (sftpChannel != null) {
90 | sftpChannel.disconnect();
91 |
92 | }
93 | }
94 | }
95 |
96 | @Override
97 | public void upload(Path local, String remotePath) throws IOException {
98 | ChannelSftp sftpChannel = null;
99 | try {
100 | sftpChannel = (ChannelSftp) session.openChannel("sftp");
101 | sftpChannel.connect();
102 | OutputStream outputStream = sftpChannel.put(remotePath);
103 | Files.copy(local, outputStream);
104 | } catch (SftpException | JSchException ex) {
105 | throw new IOException(ex);
106 | } finally {
107 | if (sftpChannel != null) {
108 | sftpChannel.disconnect();
109 |
110 | }
111 | }
112 | }
113 |
114 | @Override
115 | public void move(String oldRemotePath, String newRemotePath) throws IOException {
116 | ChannelSftp sftpChannel = null;
117 | try {
118 | sftpChannel = (ChannelSftp) session.openChannel("sftp");
119 | sftpChannel.connect();
120 | sftpChannel.rename(oldRemotePath, newRemotePath);
121 | } catch (SftpException | JSchException ex) {
122 | throw new IOException(ex);
123 | } finally {
124 | if (sftpChannel != null) {
125 | sftpChannel.disconnect();
126 |
127 | }
128 | }
129 | }
130 |
131 | @Override
132 | public void copy(String oldRemotePath, String newRemotePath) throws IOException {
133 | executeCommand("cp " + oldRemotePath + " " + newRemotePath);
134 | }
135 |
136 | private void executeCommand(String command) throws IOException {
137 | ChannelExec execChannel = null;
138 | try {
139 | execChannel = (ChannelExec) session.openChannel("exec");
140 | execChannel.connect();
141 | execChannel.setCommand(command);
142 | execChannel.start();
143 | } catch (JSchException ex) {
144 | throw new IOException(ex);
145 | } finally {
146 | if (execChannel != null) {
147 | execChannel.disconnect();
148 |
149 | }
150 | }
151 | }
152 |
153 | @Override
154 | public void delete(String remotePath) throws IOException {
155 | ChannelSftp sftpChannel = null;
156 | try {
157 | sftpChannel = (ChannelSftp) session.openChannel("sftp");
158 | sftpChannel.connect();
159 | sftpChannel.rm(remotePath);
160 | } catch (SftpException | JSchException ex) {
161 | throw new IOException(ex);
162 | } finally {
163 | if (sftpChannel != null) {
164 | sftpChannel.disconnect();
165 |
166 | }
167 | }
168 | }
169 |
170 | @Override
171 | public boolean fileExists(String remotePath) throws IOException {
172 | ChannelSftp sftpChannel = null;
173 | try {
174 | sftpChannel = (ChannelSftp) session.openChannel("sftp");
175 | sftpChannel.connect();
176 | sftpChannel.ls(remotePath);
177 | return true;
178 | } catch (JSchException ex) {
179 | throw new IOException(ex);
180 | } catch (SftpException ex) {
181 | return false;
182 | } finally {
183 | if (sftpChannel != null) {
184 | sftpChannel.disconnect();
185 |
186 | }
187 | }
188 | }
189 |
190 | @Override
191 | public List listChildrenNames(String remotePath) throws IOException {
192 | ChannelSftp sftpChannel = null;
193 | try {
194 | sftpChannel = (ChannelSftp) session.openChannel("sftp");
195 | sftpChannel.connect();
196 | return sftpChannel.ls(remotePath);
197 | } catch (SftpException | JSchException ex) {
198 | throw new IOException(ex);
199 | } finally {
200 | if (sftpChannel != null) {
201 | sftpChannel.disconnect();
202 |
203 | }
204 | }
205 | }
206 |
207 | @Override
208 | public List listChildrenFolderNames(String remotePath) throws IOException {
209 | ChannelSftp sftpChannel = null;
210 | List folderChildren = new ArrayList<>();
211 | try {
212 | sftpChannel = (ChannelSftp) session.openChannel("sftp");
213 | sftpChannel.connect();
214 | sftpChannel.ls(remotePath, (ChannelSftp.LsEntry entry) -> {
215 | if (entry.getAttrs().isDir()) {
216 | folderChildren.add(entry.getFilename());
217 | }
218 | return ChannelSftp.LsEntrySelector.CONTINUE;
219 | });
220 | return folderChildren;
221 | } catch (SftpException | JSchException ex) {
222 | throw new IOException(ex);
223 | } finally {
224 | if (sftpChannel != null) {
225 | sftpChannel.disconnect();
226 |
227 | }
228 | }
229 | }
230 |
231 | @Override
232 | public List listChildrenFileNames(String remotePath) throws IOException {
233 | ChannelSftp sftpChannel = null;
234 | List folderChildren = new ArrayList<>();
235 | try {
236 | sftpChannel = (ChannelSftp) session.openChannel("sftp");
237 | sftpChannel.connect();
238 | sftpChannel.ls(remotePath, (ChannelSftp.LsEntry entry) -> {
239 | if (entry.getAttrs().isReg()) {
240 | folderChildren.add(entry.getFilename());
241 | }
242 | return ChannelSftp.LsEntrySelector.CONTINUE;
243 | });
244 | return folderChildren;
245 | } catch (SftpException | JSchException ex) {
246 | throw new IOException(ex);
247 | } finally {
248 | if (sftpChannel != null) {
249 | sftpChannel.disconnect();
250 |
251 | }
252 | }
253 | }
254 |
255 | @Override
256 | public void execute(String command) throws IOException {
257 | executeCommand(command);
258 | }
259 |
260 | @Override
261 | public void close() throws Exception {
262 | disconnect();
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sparsick/ssh4j/SshClient.java:
--------------------------------------------------------------------------------
1 | package com.github.sparsick.ssh4j;
2 |
3 | import java.io.IOException;
4 | import java.nio.file.Path;
5 | import java.util.List;
6 |
7 |
8 | public interface SshClient extends AutoCloseable {
9 |
10 | void authUserPassword(String user, String password);
11 |
12 | void authUserPublicKey(String user, Path privateKey);
13 |
14 | void setKnownHosts(Path knownHosts);
15 |
16 | void connect(String host) throws IOException;
17 |
18 | void disconnect();
19 |
20 | void download(String remotePath, Path local) throws IOException;
21 |
22 | void upload(Path local, String remotePath) throws IOException;
23 |
24 | void move(String oldRemotePath, String newRemotePath) throws IOException;
25 |
26 | void copy(String oldRemotePath, String newRemotePath) throws IOException;
27 |
28 | void delete(String remotePath) throws IOException;
29 |
30 | boolean fileExists(String remotePath) throws IOException ;
31 |
32 | List listChildrenNames(String remotePath) throws IOException;
33 |
34 | List listChildrenFolderNames(String remotePath) throws IOException;
35 |
36 | List listChildrenFileNames(String remotePath) throws IOException;
37 |
38 | void execute(String command) throws IOException;
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sparsick/ssh4j/SshJClient.java:
--------------------------------------------------------------------------------
1 | package com.github.sparsick.ssh4j;
2 |
3 | import java.io.IOException;
4 | import java.nio.file.Path;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 | import net.schmizz.sshj.SSHClient;
8 | import net.schmizz.sshj.connection.channel.direct.Session;
9 | import net.schmizz.sshj.sftp.RemoteResourceFilter;
10 | import net.schmizz.sshj.sftp.RemoteResourceInfo;
11 | import net.schmizz.sshj.sftp.SFTPClient;
12 | import net.schmizz.sshj.xfer.FileSystemFile;
13 |
14 | public class SshJClient implements SshClient {
15 |
16 | private String user;
17 | private String password;
18 | private Path privateKey;
19 | private Path knownHosts;
20 | private SSHClient sshClient;
21 |
22 | @Override
23 | public void authUserPassword(String user, String password) {
24 | this.user = user;
25 | this.password = password;
26 | }
27 |
28 | @Override
29 | public void authUserPublicKey(String user, Path privateKey) {
30 | this.user = user;
31 | this.privateKey = privateKey;
32 | }
33 |
34 | @Override
35 | public void setKnownHosts(Path knownHosts) {
36 | this.knownHosts = knownHosts;
37 | }
38 |
39 | @Override
40 | public void connect(String host) throws IOException {
41 | sshClient = new SSHClient();
42 | if (knownHosts == null) {
43 | sshClient.loadKnownHosts();
44 | } else {
45 | sshClient.loadKnownHosts(knownHosts.toFile());
46 | }
47 |
48 | sshClient.connect(host);
49 |
50 | if (privateKey != null) {
51 | sshClient.authPublickey(user, privateKey.toString());
52 | } else if (password != null) {
53 | sshClient.authPassword(user, password);
54 | } else {
55 | throw new RuntimeException("Either privateKey nor password is set. Please call one of the auth method.");
56 | }
57 | }
58 |
59 | @Override
60 | public void disconnect() {
61 | try {
62 | close();
63 | } catch (Exception ex) {
64 | // Ignore because disconnection is quietly
65 | }
66 | }
67 |
68 | @Override
69 | public void download(String remotePath, Path local) throws IOException {
70 | try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
71 | sftpClient.get(remotePath, new FileSystemFile(local.toFile()));
72 | }
73 | }
74 |
75 | @Override
76 | public void upload(Path local, String remotePath) throws IOException {
77 | try (SFTPClient sFTPClient = sshClient.newSFTPClient()) {
78 | sFTPClient.put(new FileSystemFile(local.toFile()), remotePath);
79 | }
80 | }
81 |
82 | @Override
83 | public void move(String oldRemotePath, String newRemotePath) throws IOException {
84 | try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
85 | sftpClient.rename(oldRemotePath, newRemotePath);
86 | }
87 | }
88 |
89 | @Override
90 | public void copy(String oldRemotePath, String newRemotePath) throws IOException {
91 | try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
92 | sftpClient.put(oldRemotePath, newRemotePath);
93 | }
94 | }
95 |
96 | @Override
97 | public void delete(String remotePath) throws IOException {
98 | try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
99 | sftpClient.rm(remotePath);
100 | }
101 | }
102 |
103 | @Override
104 | public boolean fileExists(String remotePath) throws IOException {
105 | try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
106 | return sftpClient.statExistence(remotePath) != null;
107 | }
108 | }
109 |
110 | @Override
111 | public List listChildrenNames(String remotePath) throws IOException {
112 | return listChildrenNamesByFilter(remotePath, null);
113 | }
114 |
115 | @Override
116 | public List listChildrenFolderNames(String remotePath) throws IOException {
117 | return listChildrenNamesByFilter(remotePath, RemoteResourceInfo::isDirectory);
118 | }
119 |
120 | @Override
121 | public List listChildrenFileNames(String remotePath) throws IOException {
122 | return listChildrenNamesByFilter(remotePath, RemoteResourceInfo::isRegularFile);
123 | }
124 |
125 | private List listChildrenNamesByFilter(String remotePath, RemoteResourceFilter remoteFolderResourceFilter) throws IOException {
126 | try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
127 | List children = new ArrayList<>();
128 | List childrenInfos = sftpClient.ls(remotePath, remoteFolderResourceFilter);
129 | childrenInfos.stream().forEach((childInfo) -> {
130 | children.add(childInfo.getName());
131 | });
132 | return children;
133 | }
134 | }
135 |
136 | @Override
137 | public void execute(String command) throws IOException {
138 | try (Session session = sshClient.startSession()) {
139 | session.exec(command);
140 | }
141 | }
142 |
143 | @Override
144 | public void close() throws Exception {
145 | sshClient.close();
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/com/github/sparsick/ssh4j/VfsSftpClient.java:
--------------------------------------------------------------------------------
1 | package com.github.sparsick.ssh4j;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.nio.file.Path;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import org.apache.commons.vfs2.AllFileSelector;
9 | import org.apache.commons.vfs2.FileObject;
10 | import org.apache.commons.vfs2.FileSystemException;
11 | import org.apache.commons.vfs2.FileSystemOptions;
12 | import org.apache.commons.vfs2.FileType;
13 | import org.apache.commons.vfs2.impl.StandardFileSystemManager;
14 | import org.apache.commons.vfs2.provider.local.LocalFile;
15 | import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
16 |
17 | public class VfsSftpClient implements SshClient {
18 |
19 | private String password;
20 | private String user;
21 | private Path privateKey;
22 | private Path knownHosts;
23 | private StandardFileSystemManager fileSystemManager;
24 | private FileObject remoteRootDirectory;
25 |
26 | @Override
27 | public void authUserPassword(String user, String password) {
28 | this.user = user;
29 | this.password = password;
30 | }
31 |
32 | @Override
33 | public void authUserPublicKey(String user, Path privateKey) {
34 | this.user = user;
35 | this.privateKey = privateKey;
36 | }
37 |
38 | @Override
39 | public void setKnownHosts(Path knownHosts) {
40 | this.knownHosts = knownHosts;
41 | }
42 |
43 | @Override
44 | public void connect(String host) throws IOException {
45 | initFileSystemManager();
46 | FileSystemOptions connectionOptions = buildConnectionOptions();
47 | String connectionUrl = buildConnectionUrl(host);
48 | remoteRootDirectory = fileSystemManager.resolveFile(connectionUrl, connectionOptions);
49 | }
50 |
51 | private void initFileSystemManager() throws FileSystemException {
52 | if (fileSystemManager == null) {
53 | fileSystemManager = new StandardFileSystemManager();
54 | fileSystemManager.init();
55 | }
56 | }
57 |
58 | private FileSystemOptions buildConnectionOptions() throws FileSystemException {
59 | SftpFileSystemConfigBuilder sftpConfigBuilder = SftpFileSystemConfigBuilder.getInstance();
60 | FileSystemOptions opts = new FileSystemOptions();
61 | sftpConfigBuilder.setUserDirIsRoot(opts, false);
62 | sftpConfigBuilder.setStrictHostKeyChecking(opts, "yes");
63 | if (knownHosts != null) {
64 | sftpConfigBuilder.setKnownHosts(opts, knownHosts.toFile());
65 | } else {
66 | sftpConfigBuilder.setKnownHosts(opts, new File("~/.ssh/known_hosts"));
67 | }
68 | if (privateKey != null) {
69 | sftpConfigBuilder.setIdentities(opts, new File[]{privateKey.toFile()});
70 | }
71 | return opts;
72 | }
73 |
74 | private String buildConnectionUrl(String host) {
75 | if (privateKey != null) {
76 | return String.format("sftp://%s@%s", user, host);
77 | } else if (password != null) {
78 | return String.format("sftp://%s:%s@%s", user, password, host);
79 | } else {
80 | throw new RuntimeException("Either privateKey nor password is set. Please call one of the auth methods.");
81 | }
82 | }
83 |
84 | @Override
85 | public void disconnect() {
86 | if (fileSystemManager != null) {
87 | fileSystemManager.close();
88 | fileSystemManager = null;
89 | }
90 | }
91 |
92 | @Override
93 | public void download(String remotePath, Path local) throws IOException {
94 | LocalFile localFileObject = (LocalFile) fileSystemManager.resolveFile(local.toUri().toString());
95 | FileObject remoteFileObject = remoteRootDirectory.resolveFile(remotePath);
96 | try {
97 | localFileObject.copyFrom(remoteFileObject, new AllFileSelector());
98 | } finally {
99 | localFileObject.close();
100 | remoteFileObject.close();
101 | }
102 |
103 | }
104 |
105 | @Override
106 | public void upload(Path local, String remotePath) throws IOException {
107 | LocalFile localFileObject = (LocalFile) fileSystemManager.resolveFile(local.toUri().toString());
108 | FileObject remoteFileObject = remoteRootDirectory.resolveFile(remotePath);
109 | try {
110 | remoteFileObject.copyFrom(localFileObject, new AllFileSelector());
111 | } finally {
112 | localFileObject.close();
113 | remoteFileObject.close();
114 | }
115 | }
116 |
117 | @Override
118 | public void move(String oldRemotePath, String newRemotePath) throws IOException {
119 | FileObject remoteOldFileObject = remoteRootDirectory.resolveFile(oldRemotePath);
120 | FileObject newRemoteFileObject = remoteRootDirectory.resolveFile(newRemotePath);
121 | try {
122 | remoteOldFileObject.moveTo(newRemoteFileObject);
123 | remoteOldFileObject.close();
124 | } finally {
125 | newRemoteFileObject.close();
126 | }
127 | }
128 |
129 | @Override
130 | public void copy(String oldRemotePath, String newRemotePath) throws IOException {
131 | FileObject newRemoteFileObject = remoteRootDirectory.resolveFile(newRemotePath);
132 | FileObject oldRemoteFileObject = remoteRootDirectory.resolveFile(oldRemotePath);
133 | try {
134 | newRemoteFileObject.copyFrom(oldRemoteFileObject, new AllFileSelector());
135 | } finally {
136 | oldRemoteFileObject.close();
137 | newRemoteFileObject.close();
138 | }
139 | }
140 |
141 | @Override
142 | public void delete(String remotePath) throws IOException {
143 | FileObject remoteFileObject = remoteRootDirectory.resolveFile(remotePath);
144 | try {
145 | remoteFileObject.delete();
146 | } finally {
147 | remoteFileObject.close();
148 | }
149 | }
150 |
151 | @Override
152 | public boolean fileExists(String remotePath) throws IOException {
153 | FileObject remoteFileObject = remoteRootDirectory.resolveFile(remotePath);
154 | try {
155 | return remoteFileObject.exists();
156 | } finally {
157 | remoteFileObject.close();
158 | }
159 | }
160 |
161 | @Override
162 | public List listChildrenNames(String remotePath) throws IOException {
163 | return listChildrenNamesByFileType(remotePath, null);
164 | }
165 |
166 | @Override
167 | public List listChildrenFolderNames(String remotePath) throws IOException {
168 | return listChildrenNamesByFileType(remotePath, FileType.FOLDER);
169 | }
170 |
171 | @Override
172 | public List listChildrenFileNames(String remotePath) throws IOException {
173 | return listChildrenNamesByFileType(remotePath, FileType.FILE);
174 | }
175 |
176 | private List listChildrenNamesByFileType(String remotePath, FileType fileType) throws FileSystemException {
177 | FileObject remoteFileObject = remoteRootDirectory.resolveFile(remotePath);
178 | try {
179 | FileObject[] fileObjectChildren = remoteFileObject.getChildren();
180 | List childrenNames = new ArrayList<>();
181 | for (FileObject child : fileObjectChildren) {
182 | if (fileType == null || child.getType() == fileType) {
183 | childrenNames.add(child.getName().getBaseName());
184 | }
185 | }
186 | return childrenNames;
187 | } finally {
188 | remoteFileObject.close();
189 | }
190 | }
191 |
192 | @Override
193 | public void execute(String command) throws IOException {
194 | throw new UnsupportedOperationException("Not supported yet.");
195 | }
196 |
197 | @Override
198 | public void close() throws Exception {
199 | disconnect();
200 | }
201 |
202 | }
203 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sparsick/ssh4j/JSchClientIT.java:
--------------------------------------------------------------------------------
1 | package com.github.sparsick.ssh4j;
2 |
3 |
4 | public class JSchClientIT extends SshClientIT {
5 |
6 | @Override
7 | public void setUp() {
8 | clientUnderTest = new JSchClient();
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sparsick/ssh4j/SshClientIT.java:
--------------------------------------------------------------------------------
1 | package com.github.sparsick.ssh4j;
2 |
3 | import java.io.IOException;
4 | import java.nio.file.FileSystems;
5 | import java.util.List;
6 | import org.junit.After;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | import static org.assertj.core.api.Assertions.assertThat;
11 |
12 | import java.nio.file.Path;
13 |
14 | public abstract class SshClientIT {
15 |
16 | private static final String SSH_USER = "vagrant";
17 | private static final String SSH_HOST = "192.168.33.10";
18 |
19 | protected SshClient clientUnderTest;
20 |
21 | @Before
22 | public abstract void setUp();
23 |
24 | @After
25 | public void tearDown() {
26 | clientUnderTest.disconnect();
27 | }
28 |
29 | @Test
30 | public void authUserPasswordAndConnect() throws IOException {
31 | clientUnderTest.authUserPassword(SSH_USER, "vagrant");
32 | clientUnderTest.setKnownHosts(FileSystems.getDefault().getPath("src/test/resources/known_hosts"));
33 | clientUnderTest.connect(SSH_HOST);
34 | }
35 |
36 | @Test
37 | public void authUserPublicKeyAndConnect() throws IOException {
38 | clientUnderTest.authUserPublicKey(SSH_USER, FileSystems.getDefault().getPath("src/test/resources/id_rsa"));
39 | clientUnderTest.setKnownHosts(FileSystems.getDefault().getPath("src/test/resources/known_hosts"));
40 | clientUnderTest.connect(SSH_HOST);
41 | }
42 |
43 | @Test
44 | public void listChildrenNames() throws IOException {
45 | authUserPasswordAndConnect();
46 |
47 | List children = clientUnderTest.listChildrenNames("/home");
48 | assertThat(children.size()).isGreaterThan(0);
49 | }
50 |
51 | @Test
52 | public void listChildrenFolderNames() throws IOException {
53 | authUserPasswordAndConnect();
54 |
55 | List children = clientUnderTest.listChildrenFolderNames("/home");
56 | assertThat(children.size()).isGreaterThan(0);
57 | }
58 |
59 | @Test
60 | public void listChildrenFileNames() throws IOException {
61 | authUserPasswordAndConnect();
62 |
63 | List children = clientUnderTest.listChildrenFileNames("/home");
64 | assertThat(children.size()).isEqualTo(0);
65 | }
66 |
67 | @Test
68 | public void uploadAndListFile() throws IOException {
69 | authUserPasswordAndConnect();
70 | String remoteDirPath = "/home/vagrant";
71 | String remoteFilePath = remoteDirPath + "/test.txt";
72 |
73 | clientUnderTest.upload(FileSystems.getDefault().getPath("src/test/resources/test.txt"), remoteFilePath);
74 | assertThat(clientUnderTest.listChildrenFileNames(remoteDirPath)).contains("test.txt");
75 | }
76 |
77 | @Test
78 | public void uploadAndDownloadFile() throws IOException {
79 | authUserPasswordAndConnect();
80 | String remotePath = "/home/vagrant/test1.txt";
81 | Path localPath = FileSystems.getDefault().getPath("target/test1.txt");
82 |
83 | clientUnderTest.upload(FileSystems.getDefault().getPath("src/test/resources/test.txt"), remotePath);
84 | clientUnderTest.download(remotePath, localPath);
85 | assertThat(localPath).exists();
86 | }
87 |
88 | @Test
89 | public void uploadMoveAndListFile() throws IOException {
90 | authUserPasswordAndConnect();
91 | String remotePath = "/home/vagrant/test2.txt";
92 | String remoteMovePath = "/home/vagrant/test3.txt";
93 |
94 | clientUnderTest.upload(FileSystems.getDefault().getPath("src/test/resources/test.txt"), remotePath);
95 | clientUnderTest.move(remotePath, remoteMovePath);
96 | List children = clientUnderTest.listChildrenFileNames("/home/vagrant");
97 | assertThat(children).contains("test3.txt");
98 | }
99 |
100 | @Test
101 | public void uploadAndDeleteFile() throws IOException {
102 | authUserPasswordAndConnect();
103 | String remotePath = "/home/vagrant/test4.txt";
104 |
105 | clientUnderTest.upload(FileSystems.getDefault().getPath("src/test/resources/test.txt"), remotePath);
106 | clientUnderTest.delete(remotePath);
107 | List children = clientUnderTest.listChildrenFileNames("/home/vagrant");
108 | assertThat(children).doesNotContain("test4.txt");
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sparsick/ssh4j/SshJClientIT.java:
--------------------------------------------------------------------------------
1 | package com.github.sparsick.ssh4j;
2 |
3 | public class SshJClientIT extends SshClientIT {
4 |
5 | @Override
6 | public void setUp() {
7 | clientUnderTest = new SshJClient();
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/test/java/com/github/sparsick/ssh4j/VfsSftpClientIT.java:
--------------------------------------------------------------------------------
1 | package com.github.sparsick.ssh4j;
2 |
3 | public class VfsSftpClientIT extends SshClientIT {
4 |
5 | @Override
6 | public void setUp() {
7 | clientUnderTest = new VfsSftpClient();
8 | }
9 |
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/resources/id_rsa:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEA6HPbAaDkgydBmSBhu1SfQfoDz8SbJ8EiWh8csVFTx0z4jyWu
3 | b4dKfAdS/DPOm8/tuWy5nGmX97iMaNtrkgqvUz8PfKZpQUTCyXZgguFNOI348sQV
4 | TSaVTcARYc3qnFCgE2h1PToR/Mj5zKobYvvBRRNP0xwlnVOi2WR8xBpptzLl6AkA
5 | gsEr6yMGjMND9sFHgStsUK6NMlcijJXVBSF8LLVJM/ADTAGCgj5d7oKxu7M6zCRV
6 | iM0SVNUVR0lkgw4CFYf2HGRelX/iApr9DqJ3ED7hE1fhlzpaS9eqDOY0P8GshRxi
7 | eLgPFJLZIm/yjOxNgpRONjwrvx5U5hnLtf9uGQIDAQABAoIBAQCdY8SH576RpwTd
8 | f3Vs97EVZQkrpn0/f5+Y0bQFw4EsUsuBcQwY68vdCsB/jzx3d2QIxrsuUrjYvBYl
9 | 8Vt2eNGZVftQdQSTctFIw2Q5ef9lKYvEJEwf/t3c1Q1v4ZLW4Chiu7mWCTmgpRuu
10 | HgeJD9kewiKsWESHr9d1xnpL9W5a4Us3YHkVTNIW91dX/IF87hqaEORLhIgE3Jyz
11 | Wmn8GRDXc7bpBvsl/gIzrpMK9Z64xEb5PuILhq218CTKlZ4KxWwa08ffNtW67U8F
12 | qGO4iZu5j7e0cVMpFBp9XBE+tal/fjuAqzveXEKSxn3i30di+LMdDztnr64eiDkh
13 | mYR+cBeZAoGBAPb36gX3UfB757gDzCiGJkirCv0Yj4YhIEKeIitndU1WCWevzcnb
14 | 6v9q+ozwei2lXZX7/f8JK8TDKrN/nQEwp2gVDkJgT5S9qiJSKuLI2mAqQ3KZwD5J
15 | UoZYzmuqx/HSNgAD6qA3MDUbkJbq6vtQEsj9dauHSiBa4SH+ke0pE8hjAoGBAPD0
16 | C7rsgbVfUtrJa0Qjf1dD0AWkOu4LUIzJaFANgdT/myX38bF89T7+YkX1aQwQUTzY
17 | JYjHsa4kE2NAr0HkqciyJILIlapqB9Y3yREAgnRRMAb8tR7anocVmgLXWn/rmls5
18 | SJQVA+TqozPSHTwtchCblS1bVTGyjCVQNsEvj5JTAoGBAJoXx1nfna2Z8dOb8vdZ
19 | 9Gsk5Z9TgsGiy5klR5ajX8pYI1ghlhob8H1bh2cG6ISwiDr71tgZJckIKQ2EUzcZ
20 | 32oOsS3zH9RjntL5R67muXKFDD5l9lAmuan/oRQGo+ibS3wo9Wzv4lFQmJ/Bhco2
21 | hPIJSzEyIascaRon128NUT2XAoGAYmDiITHLS8hdxeKTH0D3DyQq3QLO5L5N5w2c
22 | v4KkTdkG+ZugXP1ODKhEa5flif1njdYajRwrmZQ1LkMMy3SXNdA2RAetw+SCyp4A
23 | RCbXHLLBTzkColRUgYb6WMqgsrX5UeGzlnJ2IpMCi3fwY8+SUOGVKO2vfRkPS3TS
24 | xlGq5u0CgYBziv+nOvOAEKyqhvg/Yd1js28vdG9ZypCC6YQePLmd33tKEoqakpqI
25 | sylfKck7dnT6ChjqBbTNOpfATUC/OxjwHMLivynWaNTobz54to8pF8BU7AUA1vwL
26 | HLQzhDMCG2SXPgE06fYHCFlYMrbRDNBcXl7ubrqcT0xWtSXmsRUkqQ==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/src/test/resources/id_rsa.pub:
--------------------------------------------------------------------------------
1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDoc9sBoOSDJ0GZIGG7VJ9B+gPPxJsnwSJaHxyxUVPHTPiPJa5vh0p8B1L8M86bz+25bLmcaZf3uIxo22uSCq9TPw98pmlBRMLJdmCC4U04jfjyxBVNJpVNwBFhzeqcUKATaHU9OhH8yPnMqhti+8FFE0/THCWdU6LZZHzEGmm3MuXoCQCCwSvrIwaMw0P2wUeBK2xQro0yVyKMldUFIXwstUkz8ANMAYKCPl3ugrG7szrMJFWIzRJU1RVHSWSDDgIVh/YcZF6Vf+ICmv0OoncQPuETV+GXOlpL16oM5jQ/wayFHGJ4uA8Uktkib/KM7E2ClE42PCu/HlTmGcu1/24Z skosmalla@skosmalla-ThinkPad-T430s
2 |
--------------------------------------------------------------------------------
/src/test/resources/known_hosts:
--------------------------------------------------------------------------------
1 | |1|kvHaX2btU1VRjil0Cwk3fKIYLIc=|uJDM6vZWkLeZSwTci3pllUmN26Q= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAye/ADYofk2N4nHSpbNjssY7E9ovuO7FiIVc1zH2M64lcjPChoD2V/GyVrtLCcw8qw/l0M1kSd9WfaAT9oCe8CsQiLqQgfqt2ApaLreKWWIg2raB+PSbm/k4K+J681HkJ04dwImr4bAQS4PecaoDFvYpPf8ApDNrXFu8LqxtHVz5hfbi8iEY6Hd4+SMB+BcGRGLM6xlN6OwlAd4G1Ystwqr5BERmk6a5upF2bhRYt7aNk3Ur58XsLKsS99fnlZhEc4okfHOyEp1wMJMV1yXd2borzH/JOwbmlqenpkpYKH96EFMELur9ymv4AouH6DrswbMIr3LuHhYjiNrvjEjI51w==
2 |
--------------------------------------------------------------------------------
/src/test/resources/test.txt:
--------------------------------------------------------------------------------
1 | 99 bottles
--------------------------------------------------------------------------------