diff --git a/sftp-connector-demo/src/com/axonivy/connector/sftp/demo/Constants.java b/sftp-connector-demo/src/com/axonivy/connector/sftp/demo/Constants.java
new file mode 100644
index 0000000..5f9d079
--- /dev/null
+++ b/sftp-connector-demo/src/com/axonivy/connector/sftp/demo/Constants.java
@@ -0,0 +1,6 @@
+package com.axonivy.connector.sftp.demo;
+
+public class Constants {
+ public static final String DUMMY = "dummy";
+
+}
diff --git a/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemo.xhtml b/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemo.xhtml
index fbb94ab..95e2089 100644
--- a/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemo.xhtml
+++ b/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemo.xhtml
@@ -31,7 +31,7 @@
+ listener="#{logic.handleFileUpload}" />
diff --git a/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemoData.ivyClass b/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemoData.ivyClass
index 7936602..84c9ef1 100644
--- a/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemoData.ivyClass
+++ b/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemoData.ivyClass
@@ -1,5 +1,7 @@
SftpClientDemoData #class
com.axonivy.connector.sftp.demo.SftpClientDemo #namespace
+sftpName String #field
+sftpName PERSISTENT #fieldModifier
clientHost String #field
clientHost PERSISTENT #fieldModifier
clientPort Number #field
diff --git a/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemoProcess.p.json b/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemoProcess.p.json
index 945e2ed..9c63e5e 100644
--- a/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemoProcess.p.json
+++ b/sftp-connector-demo/src_hd/com/axonivy/connector/sftp/demo/SftpClientDemo/SftpClientDemoProcess.p.json
@@ -31,10 +31,13 @@
"config" : {
"output" : {
"code" : [
- "String prefix = \"com_axonivy_connector_sftp_server_\";",
- "in.clientHost = ivy.var.variable(prefix+\"host\").value();",
- "in.clientPort = Integer.parseInt(ivy.var.variable(prefix+\"port\").value());",
- "in.clientUsername = ivy.var.variable(prefix+\"username\").value();"
+ "import com.axonivy.connector.sftp.service.SftpClientService;",
+ "import com.axonivy.connector.sftp.demo.Constants;",
+ "",
+ "in.sftpName = new String(Constants.DUMMY);",
+ "in.clientHost = SftpClientService.getClientHost(in.sftpName);",
+ "in.clientPort = Integer.parseInt(SftpClientService.getPort(in.sftpName));",
+ "in.clientUsername = SftpClientService.getUsername(in.sftpName);"
]
}
},
@@ -77,19 +80,22 @@
"type" : "SubProcessCall",
"name" : "Sftp/SftpUploadFile",
"config" : {
- "processCall" : "Sftp/SftpUploadFile:uploadFile(java.io.InputStream,String)",
+ "processCall" : "Sftp/SftpUploadFile:uploadFile(String,java.io.InputStream,String)",
"output" : {
"map" : {
"out" : "in",
- "out.isFileUploaded" : "result.isSuccess"
+ "out.isFileUploaded" : "result.isSuccess",
+ "out.sftpName" : "in.sftpName"
}
},
"call" : {
"params" : [
+ { "name" : "sftpName", "type" : "String" },
{ "name" : "fileToBeUploaded", "type" : "java.io.InputStream" },
{ "name" : "fileName", "type" : "String" }
],
"map" : {
+ "param.sftpName" : "in.sftpName",
"param.fileToBeUploaded" : "in.uploadedFile.getInputStream()",
"param.fileName" : "in.uploadedFile.getFileName()"
}
@@ -111,7 +117,7 @@
"type" : "SubProcessCall",
"name" : "Sftp/SftpDownloadFile",
"config" : {
- "processCall" : "Sftp/SftpDownloadFile:downloadFile(String)",
+ "processCall" : "Sftp/SftpDownloadFile:downloadFile(String,String)",
"output" : {
"map" : {
"out" : "in",
@@ -120,9 +126,11 @@
},
"call" : {
"params" : [
+ { "name" : "sftpName", "type" : "String" },
{ "name" : "remoteFileName", "type" : "String" }
],
"map" : {
+ "param.sftpName" : "in.sftpName",
"param.remoteFileName" : "in.fileToDownload.name"
}
}
@@ -191,7 +199,7 @@
"type" : "SubProcessCall",
"name" : "call list All Files",
"config" : {
- "processCall" : "Sftp/SftpDownloadFile:listAllFiles(String)",
+ "processCall" : "Sftp/SftpDownloadFile:listAllFiles(String,String)",
"output" : {
"map" : {
"out" : "in",
@@ -200,9 +208,11 @@
},
"call" : {
"params" : [
+ { "name" : "sftpName", "type" : "String" },
{ "name" : "remoteDirectory", "type" : "String" }
],
"map" : {
+ "param.sftpName" : "in.sftpName",
"param.remoteDirectory" : "\".\""
}
}
diff --git a/sftp-connector-test/src_test/com/axonivy/connector/sftp/test/SftpProcessSSHTest.java b/sftp-connector-test/src_test/com/axonivy/connector/sftp/test/SftpProcessSSHTest.java
index 698bda2..3620703 100644
--- a/sftp-connector-test/src_test/com/axonivy/connector/sftp/test/SftpProcessSSHTest.java
+++ b/sftp-connector-test/src_test/com/axonivy/connector/sftp/test/SftpProcessSSHTest.java
@@ -45,29 +45,32 @@ public class SftpProcessSSHTest {
private static final BpmProcess TEST_UPLOAD_FILE_PROCESS = BpmProcess.path("Sftp/SftpUploadFile");
private static final BpmProcess TEST_DOWNLOAD_FILE_PROCESS = BpmProcess.path("Sftp/SftpDownloadFile");
+ private static final String TEST_SFTP_NAME = "dummy";
+ private static final String TEST_SFTP_NAME_VAR = TEST_SFTP_NAME + ".";
private static final String TEST_FILE_NAME = "market_market_connector_sftp.pdf";
private static final long TEST_FILE_SIZE = 207569L;
-
+ private static final String PREFIX = "com.axonivy.connector.sftp.server.";
+
@BeforeAll
public static void init() throws Exception {
- String prefix = "com_axonivy_connector_sftp_server_";
- Ivy.var().set(prefix+"auth", "ssh");
- Ivy.var().set(prefix+"password", "");
+
+ Ivy.var().set(PREFIX+TEST_SFTP_NAME_VAR+"auth", "ssh");
+ Ivy.var().set(PREFIX+TEST_SFTP_NAME_VAR+"password", "");
String keyString = Files.readString(Paths.get(SftpProcessSSHTest.class.getResource("sftptest").toURI()));
- Ivy.var().set(prefix+"secret_sshkey", keyString);
- Ivy.var().set(prefix+"secret_sshpassphrase", "123456");
+ Ivy.var().set(PREFIX+TEST_SFTP_NAME_VAR+"secret.sshkey", keyString);
+ Ivy.var().set(PREFIX+TEST_SFTP_NAME_VAR+"secret.sshpassphrase", "123456");
}
@Test
@Order(1)
public void callOpenConnection(BpmClient bpmClient) throws Exception {
- BpmElement startable = TEST_HELPER_PROCESS.elementName("openConnection()");
+ BpmElement startable = TEST_HELPER_PROCESS.elementName("openConnection(String)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute() // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME) // Callable sub process input arguments
.subResult();
SftpClientService sftpClient = result.param("sftpClient", SftpClientService.class);
@@ -82,11 +85,11 @@ public void callOpenConnection(BpmClient bpmClient) throws Exception {
public void callUploadFile(BpmClient bpmClient) {
InputStream fileToBeUploaded = getClass().getResourceAsStream(TEST_FILE_NAME);
- BpmElement startable = TEST_UPLOAD_FILE_PROCESS.elementName("uploadFile(InputStream,String)");
+ BpmElement startable = TEST_UPLOAD_FILE_PROCESS.elementName("uploadFile(String,InputStream,String)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute(fileToBeUploaded, TEST_FILE_NAME) // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME,fileToBeUploaded, TEST_FILE_NAME) // Callable sub process input arguments
.subResult();
Boolean isSuccess = result.param("isSuccess", Boolean.class);
@@ -103,11 +106,11 @@ public void callUploadIvyFile(BpmClient bpmClient) throws IOException {
File ivyFile = new File(TEST_FILE_NAME, true);
FileUtils.moveFile(javaFile, ivyFile.getJavaFile());
- BpmElement startable = TEST_UPLOAD_FILE_PROCESS.elementName("uploadFile(File)");
+ BpmElement startable = TEST_UPLOAD_FILE_PROCESS.elementName("uploadFile(String,File)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute(ivyFile) // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME, ivyFile) // Callable sub process input arguments
.subResult();
Boolean isSuccess = result.param("isSuccess", Boolean.class);
@@ -117,11 +120,11 @@ public void callUploadIvyFile(BpmClient bpmClient) throws IOException {
@Test
@Order(4)
public void callListAllFiles(BpmClient bpmClient) {
- BpmElement startable = TEST_DOWNLOAD_FILE_PROCESS.elementName("listAllFiles(String)");
+ BpmElement startable = TEST_DOWNLOAD_FILE_PROCESS.elementName("listAllFiles(String,String)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute(".") // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME, ".") // Callable sub process input arguments
.subResult();
List listFiles = result.param("listFiles", List.class);
assertThat(listFiles.size()).isGreaterThanOrEqualTo(1);
@@ -131,11 +134,11 @@ public void callListAllFiles(BpmClient bpmClient) {
@Test
@Order(5)
public void callDownloadFile(BpmClient bpmClient) {
- BpmElement startable = TEST_DOWNLOAD_FILE_PROCESS.elementName("downloadFile(String)");
+ BpmElement startable = TEST_DOWNLOAD_FILE_PROCESS.elementName("downloadFile(String,String)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute(TEST_FILE_NAME) // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME, TEST_FILE_NAME) // Callable sub process input arguments
.subResult();
java.io.File downloadedFile = result.param("toFile", java.io.File.class);
assertThat(downloadedFile.length()).isEqualTo(TEST_FILE_SIZE);
diff --git a/sftp-connector-test/src_test/com/axonivy/connector/sftp/test/SftpProcessTest.java b/sftp-connector-test/src_test/com/axonivy/connector/sftp/test/SftpProcessTest.java
index fc93b9b..e82be13 100644
--- a/sftp-connector-test/src_test/com/axonivy/connector/sftp/test/SftpProcessTest.java
+++ b/sftp-connector-test/src_test/com/axonivy/connector/sftp/test/SftpProcessTest.java
@@ -43,6 +43,7 @@ public class SftpProcessTest {
private static final BpmProcess TEST_UPLOAD_FILE_PROCESS = BpmProcess.path("Sftp/SftpUploadFile");
private static final BpmProcess TEST_DOWNLOAD_FILE_PROCESS = BpmProcess.path("Sftp/SftpDownloadFile");
+ private static final String TEST_SFTP_NAME = "dummy";
private static final String TEST_FILE_NAME = "market_market_connector_sftp.pdf";
private static final long TEST_FILE_SIZE = 207569L;
@@ -50,11 +51,11 @@ public class SftpProcessTest {
@Test
@Order(1)
public void callOpenConnection(BpmClient bpmClient) {
- BpmElement startable = TEST_HELPER_PROCESS.elementName("openConnection()");
+ BpmElement startable = TEST_HELPER_PROCESS.elementName("openConnection(String)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute() // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME) // Callable sub process input arguments
.subResult();
SftpClientService sftpClient = result.param("sftpClient", SftpClientService.class);
@@ -67,11 +68,11 @@ public void callOpenConnection(BpmClient bpmClient) {
public void callUploadFile(BpmClient bpmClient) {
InputStream fileToBeUploaded = getClass().getResourceAsStream(TEST_FILE_NAME);
- BpmElement startable = TEST_UPLOAD_FILE_PROCESS.elementName("uploadFile(InputStream,String)");
+ BpmElement startable = TEST_UPLOAD_FILE_PROCESS.elementName("uploadFile(String,InputStream,String)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute(fileToBeUploaded, TEST_FILE_NAME) // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME, fileToBeUploaded, TEST_FILE_NAME) // Callable sub process input arguments
.subResult();
Boolean isSuccess = result.param("isSuccess", Boolean.class);
@@ -88,11 +89,11 @@ public void callUploadIvyFile(BpmClient bpmClient) throws IOException {
File ivyFile = new File(TEST_FILE_NAME, true);
FileUtils.moveFile(javaFile, ivyFile.getJavaFile());
- BpmElement startable = TEST_UPLOAD_FILE_PROCESS.elementName("uploadFile(File)");
+ BpmElement startable = TEST_UPLOAD_FILE_PROCESS.elementName("uploadFile(String,File)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute(ivyFile) // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME, ivyFile) // Callable sub process input arguments
.subResult();
Boolean isSuccess = result.param("isSuccess", Boolean.class);
@@ -102,11 +103,11 @@ public void callUploadIvyFile(BpmClient bpmClient) throws IOException {
@Test
@Order(4)
public void callListAllFiles(BpmClient bpmClient) {
- BpmElement startable = TEST_DOWNLOAD_FILE_PROCESS.elementName("listAllFiles(String)");
+ BpmElement startable = TEST_DOWNLOAD_FILE_PROCESS.elementName("listAllFiles(String,String)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute(".") // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME, ".") // Callable sub process input arguments
.subResult();
List listFiles = result.param("listFiles", List.class);
assertThat(listFiles.size()).isGreaterThanOrEqualTo(1);
@@ -116,11 +117,11 @@ public void callListAllFiles(BpmClient bpmClient) {
@Test
@Order(5)
public void callDownloadFile(BpmClient bpmClient) {
- BpmElement startable = TEST_DOWNLOAD_FILE_PROCESS.elementName("downloadFile(String)");
+ BpmElement startable = TEST_DOWNLOAD_FILE_PROCESS.elementName("downloadFile(String,String)");
SubProcessCallResult result = bpmClient.start()
.subProcess(startable)
- .execute(TEST_FILE_NAME) // Callable sub process input arguments
+ .execute(TEST_SFTP_NAME, TEST_FILE_NAME) // Callable sub process input arguments
.subResult();
java.io.File downloadedFile = result.param("toFile", java.io.File.class);
assertThat(downloadedFile.length()).isEqualTo(TEST_FILE_SIZE);
diff --git a/sftp-connector/config/variables.yaml b/sftp-connector/config/variables.yaml
index afe98cb..eeb2d96 100644
--- a/sftp-connector/config/variables.yaml
+++ b/sftp-connector/config/variables.yaml
@@ -1,24 +1,26 @@
Variables:
com.axonivy.connector.sftp.server:
- # The host name to the SFTP server
- host: 'localhost'
-
- # The port number to the SFTP server
- port: 22
-
- # The username to the SFTP server
- username: 'usr'
-
- # Auth type to the SFPT server: password OR ssh
- auth: 'ssh'
-
- # The password to the SFTP server
- # [password]
- password: ''
-
- # The ssh key string to SFTP server
- # [secret private key]
- secret.sshkey: ''
- # The ssh key passphrase
- secret.sshpassphrase: ''
+ dummy:
+ # The host name to the SFTP server
+ host: 'localhost'
+
+ # The port number to the SFTP server
+ port: 22
+
+ # The username to the SFTP server
+ username: 'usr'
+
+ # Auth type to the SFPT server: password OR ssh
+ auth: 'password'
+
+ # The password to the SFTP server
+ # [password]
+ password: pwd
+
+ # The ssh key string to SFTP server
+ # [secret private key]
+ secret.sshkey: ''
+
+ # The ssh key passphrase
+ secret.sshpassphrase: ''
diff --git a/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpDownloadFileData.ivyClass b/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpDownloadFileData.ivyClass
index 21e7bfc..1dc25d7 100644
--- a/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpDownloadFileData.ivyClass
+++ b/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpDownloadFileData.ivyClass
@@ -5,3 +5,4 @@ toFile File #field
remoteDirectory String #field
listFiles java.util.List #field
sftpClient com.axonivy.connector.sftp.service.SftpClientService #field
+sftpName String #field
diff --git a/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpHelperData.ivyClass b/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpHelperData.ivyClass
index 8454560..c05f242 100644
--- a/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpHelperData.ivyClass
+++ b/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpHelperData.ivyClass
@@ -1,3 +1,4 @@
SftpHelperData #class
com.axonivy.connector.sftp #namespace
+sftpName String #field
sftpClient com.axonivy.connector.sftp.service.SftpClientService #field
diff --git a/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpUploadFileData.ivyClass b/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpUploadFileData.ivyClass
index 30d6f6c..c8db165 100644
--- a/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpUploadFileData.ivyClass
+++ b/sftp-connector/dataclasses/com/axonivy/connector/sftp/SftpUploadFileData.ivyClass
@@ -5,3 +5,4 @@ fileName String #field
sftpClient com.axonivy.connector.sftp.service.SftpClientService #field
isSuccess Boolean #field
ivyFile File #field
+sftpName String #field
diff --git a/sftp-connector/processes/Sftp/SftpDownloadFile.p.json b/sftp-connector/processes/Sftp/SftpDownloadFile.p.json
index 148fc98..6de6090 100644
--- a/sftp-connector/processes/Sftp/SftpDownloadFile.p.json
+++ b/sftp-connector/processes/Sftp/SftpDownloadFile.p.json
@@ -8,15 +8,17 @@
"elements" : [ {
"id" : "f0",
"type" : "CallSubStart",
- "name" : "downloadFile(String)",
+ "name" : "downloadFile(String,String)",
"config" : {
"callSignature" : "downloadFile",
"input" : {
"params" : [
+ { "name" : "sftpName", "type" : "String" },
{ "name" : "remoteFileName", "type" : "String" }
],
"map" : {
- "out.remoteFileName" : "param.remoteFileName"
+ "out.remoteFileName" : "param.remoteFileName",
+ "out.sftpName" : "param.sftpName"
}
},
"result" : {
@@ -99,14 +101,16 @@
}, {
"id" : "f7",
"type" : "CallSubStart",
- "name" : "listAllFiles(String)",
+ "name" : "listAllFiles(String,String)",
"config" : {
"callSignature" : "listAllFiles",
"input" : {
"params" : [
+ { "name" : "sftpName", "type" : "String" },
{ "name" : "remoteDirectory", "type" : "String" }
],
"map" : {
+ "out.sftpName" : "param.sftpName",
"out.remoteDirectory" : "param.remoteDirectory"
}
},
@@ -172,12 +176,20 @@
"type" : "SubProcessCall",
"name" : "Connect",
"config" : {
- "processCall" : "Sftp/SftpHelper:openConnection()",
+ "processCall" : "Sftp/SftpHelper:openConnection(String)",
"output" : {
"map" : {
"out" : "in",
"out.sftpClient" : "result.#sftpClient"
}
+ },
+ "call" : {
+ "params" : [
+ { "name" : "sftpName", "type" : "String" }
+ ],
+ "map" : {
+ "param.sftpName" : "in.sftpName"
+ }
}
},
"visual" : {
@@ -200,12 +212,20 @@
"type" : "SubProcessCall",
"name" : "Connect",
"config" : {
- "processCall" : "Sftp/SftpHelper:openConnection()",
+ "processCall" : "Sftp/SftpHelper:openConnection(String)",
"output" : {
"map" : {
"out" : "in",
"out.sftpClient" : "result.#sftpClient"
}
+ },
+ "call" : {
+ "params" : [
+ { "name" : "sftpName", "type" : "String" }
+ ],
+ "map" : {
+ "param.sftpName" : "in.sftpName"
+ }
}
},
"visual" : {
diff --git a/sftp-connector/processes/Sftp/SftpHelper.p.json b/sftp-connector/processes/Sftp/SftpHelper.p.json
index 3e064b1..994043a 100644
--- a/sftp-connector/processes/Sftp/SftpHelper.p.json
+++ b/sftp-connector/processes/Sftp/SftpHelper.p.json
@@ -8,9 +8,17 @@
"elements" : [ {
"id" : "f0",
"type" : "CallSubStart",
- "name" : "openConnection()",
+ "name" : "openConnection(String)",
"config" : {
"callSignature" : "openConnection",
+ "input" : {
+ "params" : [
+ { "name" : "sftpName", "type" : "String", "desc" : "Name of SFtp as configured in global variables" }
+ ],
+ "map" : {
+ "out.sftpName" : "param.sftpName"
+ }
+ },
"result" : {
"params" : [
{ "name" : "sftpClient", "type" : "com.axonivy.connector.sftp.service.SftpClientService" }
@@ -41,32 +49,8 @@
"output" : {
"code" : [
"import com.axonivy.connector.sftp.service.SftpClientService;",
- "import java.lang.NumberFormatException;",
- "",
- "",
- "String prefix = \"com_axonivy_connector_sftp_server_\";",
- "",
- "String host = ivy.var.variable(prefix+\"host\").value();",
- "Integer port = 22;",
- "String portRaw = ivy.var.variable(prefix+\"port\").value();",
- "try {",
- " port = Integer.parseInt(portRaw);",
- "}",
- "catch(NumberFormatException nfe) {",
- " ivy.log.error(\"The Global Variable: com.axonivy.connector.sftp.server.port = {0} does not contain a number. The default port number: {1} will be used instead.\", ",
- " nfe, portRaw);",
- "}",
- "String username = ivy.var.variable(prefix+\"username\").value();",
- "String password = ivy.var.variable(prefix+\"password\").value();",
- "String auth = ivy.var.get(prefix+\"auth\");",
- "String ssh = ivy.var.get(prefix+\"secret_sshkey\");",
- "String sshpassphrase = ivy.var.get(prefix+\"secret_sshpassphrase\");",
- "",
- "ivy.log.debug(\"The following settings will be used to connect to the SFTP server: hostname: {0}, port: {1}, username: {2}. Connection in progress...\", ",
- " host, port, username);",
- "in.sftpClient = new SftpClientService(host, port, username, auth, password, ssh, sshpassphrase);",
"",
- "ivy.log.debug(\"Connection established.\");"
+ "in.sftpClient = new SftpClientService(in.sftpName);"
]
}
},
diff --git a/sftp-connector/processes/Sftp/SftpUploadFile.p.json b/sftp-connector/processes/Sftp/SftpUploadFile.p.json
index 5f8b618..1c63546 100644
--- a/sftp-connector/processes/Sftp/SftpUploadFile.p.json
+++ b/sftp-connector/processes/Sftp/SftpUploadFile.p.json
@@ -8,15 +8,17 @@
"elements" : [ {
"id" : "f0",
"type" : "CallSubStart",
- "name" : "uploadFile(InputStream,String)",
+ "name" : "uploadFile(String,InputStream,String)",
"config" : {
"callSignature" : "uploadFile",
"input" : {
"params" : [
+ { "name" : "sftpName", "type" : "String" },
{ "name" : "fileToBeUploaded", "type" : "java.io.InputStream" },
{ "name" : "fileName", "type" : "String" }
],
"map" : {
+ "out.sftpName" : "param.sftpName",
"out.fileName" : "param.fileName",
"out.fileToBeUploaded" : "param.fileToBeUploaded"
}
@@ -85,12 +87,20 @@
"type" : "SubProcessCall",
"name" : "Connect",
"config" : {
- "processCall" : "Sftp/SftpHelper:openConnection()",
+ "processCall" : "Sftp/SftpHelper:openConnection(String)",
"output" : {
"map" : {
"out" : "in",
"out.sftpClient" : "result.#sftpClient"
}
+ },
+ "call" : {
+ "params" : [
+ { "name" : "sftpName", "type" : "String" }
+ ],
+ "map" : {
+ "param.sftpName" : "in.sftpName"
+ }
}
},
"visual" : {
@@ -111,14 +121,16 @@
}, {
"id" : "f12",
"type" : "CallSubStart",
- "name" : "uploadFile(File)",
+ "name" : "uploadFile(String,File)",
"config" : {
"callSignature" : "uploadFile",
"input" : {
"params" : [
+ { "name" : "sftpName", "type" : "String" },
{ "name" : "file", "type" : "File" }
],
"map" : {
+ "out.sftpName" : "param.sftpName",
"out.ivyFile" : "param.file"
}
},
@@ -149,12 +161,20 @@
"type" : "SubProcessCall",
"name" : "Connect",
"config" : {
- "processCall" : "Sftp/SftpHelper:openConnection()",
+ "processCall" : "Sftp/SftpHelper:openConnection(String)",
"output" : {
"map" : {
"out" : "in",
"out.sftpClient" : "result.#sftpClient"
}
+ },
+ "call" : {
+ "params" : [
+ { "name" : "sftpName", "type" : "String" }
+ ],
+ "map" : {
+ "param.sftpName" : "in.sftpName"
+ }
}
},
"visual" : {
diff --git a/sftp-connector/src/com/axonivy/connector/sftp/service/SftpClientService.java b/sftp-connector/src/com/axonivy/connector/sftp/service/SftpClientService.java
index 21c04a5..e69d123 100644
--- a/sftp-connector/src/com/axonivy/connector/sftp/service/SftpClientService.java
+++ b/sftp-connector/src/com/axonivy/connector/sftp/service/SftpClientService.java
@@ -11,7 +11,7 @@
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
-import org.apache.log4j.Logger;
+import ch.ivyteam.log.Logger;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
@@ -20,19 +20,29 @@
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
+import ch.ivyteam.ivy.environment.Ivy;
/**
- * Service class for file transfer to/from the SFTP server.
- * The service class is used to decouple the SFTP implementation.
+ * Service class for file transfer to/from the SFTP server. The service class is
+ * used to decouple the SFTP implementation.
*/
public class SftpClientService implements AutoCloseable {
- private static final Logger LOG = Logger.getLogger(SftpClientService.class);
+ private static final Logger LOG = Ivy.log();
+
private static final String PATHSEPARATOR = "/";
private static final int SESSION_TIMEOUT = 10000;
private static final int CHANNEL_TIMEOUT = 5000;
+
+ private static final String SFTP_VAR = "com.axonivy.connector.sftp.server";
+ private static final String HOST_VAR = "host";
+ private static final String PORT_VAR = "port";
+ private static final String SECRET_SSHPASSPHRASE_VAR = "secret.sshpassphrase";
+ private static final String SECRET_SSHKEY_VAR = "secret.sshkey";
+ private static final String AUTH_VAR = "auth";
+ private static final String PASSWORD_VAR = "password";
+ private static final String USERNAME_VAR = "username";
private static final String PASSWORD = "password";
-
-
+
/**
* A Session represents a connection to an SSH server.
*/
@@ -41,51 +51,60 @@ public class SftpClientService implements AutoCloseable {
* A Channel connected to an SFTP server (as a subsystem of the ssh server).
*/
private ChannelSftp channel;
-
-
- /**
- * Instantiates the SftpClientService object with given the host, port, username and password.
+
+ /***
*
- * @param host the host name
- * @param authType authentication type: password, ssh
- * @param port the port number
- * @param username the user name
- * @param password the password
- * @param keyString the ssh key string
- * @param passphrase the ssh passphrase
- * @throws IOException
+ * @param sftpName
+ * @throws IOException
*/
- public SftpClientService(String host, int port, String username, String authType, String password, String keyString, String passphrase) throws IOException {
+ public SftpClientService(String sftpName) throws IOException {
+ String host = getClientHost(sftpName);
+ String portRaw = getPort(sftpName);
+ String username = getUsername(sftpName);
+ String password = getVar(sftpName, PASSWORD_VAR);
+ String auth = getVar(sftpName, AUTH_VAR);
+ String secretSSHkey = getVar(sftpName, SECRET_SSHKEY_VAR);
+ String secretSSHpassphrase = getVar(sftpName, SECRET_SSHPASSPHRASE_VAR);
+
+ int port = 22;
+ try {
+ port = Integer.parseInt(portRaw);
+ } catch (NumberFormatException nfe) {
+ LOG.error("The Global Variable: com.axonivy.connector.sftp.server.port = {0} does not contain a number. The default port number: {1} will be used instead.",
+ portRaw, port, nfe);
+ }
+ LOG.debug("The following settings will be used to connect to the SFTP server: hostname: {0}, port: {1}, username: {2}. Connection in progress...",
+ host, port, username);
try {
JSch jsch = new JSch();
-
+
session = jsch.getSession(username, host, port);
- if (StringUtils.isEmpty(authType) || PASSWORD.equalsIgnoreCase(authType)) {
+ if (StringUtils.isEmpty(auth) || PASSWORD.equalsIgnoreCase(auth)) {
session.setPassword(password);
} else {
session.setConfig("PreferredAuthentications", "publickey");
- jsch.addIdentity(null, keyString.getBytes(), null, passphrase.getBytes());
+ jsch.addIdentity(null, secretSSHkey.getBytes(), null, secretSSHpassphrase.getBytes());
}
-
session.setConfig("StrictHostKeyChecking", "no");
// 10 seconds session timeout
session.connect(SESSION_TIMEOUT);
channel = (ChannelSftp) session.openChannel("sftp");
-
if (channel == null) {
close();
- throw new IOException("Error while opening the channel to SFTP session '" + host +
- "' with username '" + username + "'!");
+ throw new IOException("Error while opening the channel to SFTP session '" + host + "' with username '"
+ + username + "'!");
}
// 5 seconds timeout
channel.connect(CHANNEL_TIMEOUT);
} catch (JSchException ex) {
- throw new IOException("Error while trying to connect to SFTP server '" + host +
- "' with username '" + username + "': ", ex);
+ throw new IOException(
+ "Error while trying to connect to SFTP server '" + host + "' with username '" + username + "': ",
+ ex);
}
+ LOG.debug("Connection established.");
}
-
+
/**
* Closes the current channel and the connection to the server.
*/
@@ -96,15 +115,14 @@ public void close() {
channel.disconnect();
channel = null;
}
- }
- finally {
+ } finally {
if (session != null) {
session.disconnect();
session = null;
}
}
}
-
+
/**
* Returns the current local directory in absolute form.
*
@@ -113,7 +131,7 @@ public void close() {
public String getLocalCurrentDir() {
return channel.lpwd();
}
-
+
/**
* Creates a new remote directory.
*
@@ -123,12 +141,11 @@ public String getLocalCurrentDir() {
public void makeRemoteDir(String name) throws IOException {
try {
channel.mkdir(name);
- }
- catch (SftpException ex) {
+ } catch (SftpException ex) {
throw new IOException(ex);
}
}
-
+
/**
* Returns the current remote directory in absolute form.
*
@@ -138,12 +155,11 @@ public void makeRemoteDir(String name) throws IOException {
public String getRemoteCurrentDir() throws IOException {
try {
return channel.pwd();
- }
- catch (SftpException ex) {
+ } catch (SftpException ex) {
throw new IOException(ex);
}
}
-
+
/**
* Returns the File information of a single file.
*
@@ -157,7 +173,7 @@ public FileData getFileData(String remoteFilePath) {
List lsEntryList = channel.ls(remoteFilePath);
if (lsEntryList != null && !lsEntryList.isEmpty()) {
LsEntry lsEntry = lsEntryList.get(0);
-
+
fd = new FileData();
int i = remoteFilePath.lastIndexOf('/');
fd.parentPath = (i < 0) ? "" : remoteFilePath.substring(0, i);
@@ -167,14 +183,13 @@ public FileData getFileData(String remoteFilePath) {
fd.size = lsEntry.getAttrs().getSize();
fd.modificationDate = new Date(1000L * lsEntry.getAttrs().getMTime());
}
- }
- catch (SftpException ex) { // If an error occurs, null will be returned
+ } catch (SftpException ex) { // If an error occurs, null will be returned
LOG.warn("If an error occurs, null will be returned", ex);
}
-
+
return fd;
}
-
+
/**
* Returns the list of all File information of all the files in a directory.
*
@@ -196,80 +211,82 @@ public List getFileDataList(String remoteDir) {
fd.modificationDate = new Date(1000L * lsEntry.getAttrs().getMTime());
fileDataList.add(fd);
}
- }
- catch (SftpException ex) { // If an error occurs, empty list will be returned
+ } catch (SftpException ex) { // If an error occurs, empty list will be returned
LOG.warn("If an error occurs, empty list will be returned", ex);
}
return fileDataList;
}
-
+
/**
- * Uploads a file from an input stream.
- * If the file is already existing in the remote directory, it will be overwritten.
+ * Uploads a file from an input stream. If the file is already existing in the
+ * remote directory, it will be overwritten.
*
- * @param is the source file, in form of an input stream.
- * @param remoteDstFilePath the remote destination file name, relative to the current remote directory.
+ * @param is the source file, in form of an input stream.
+ * @param remoteDstFilePath the remote destination file name, relative to the
+ * current remote directory.
* @throws IOException
*/
public void uploadFile(InputStream is, String remoteDstFilePath) throws IOException {
try {
channel.put(is, remoteDstFilePath);
- }
- catch (SftpException ex) {
+ } catch (SftpException ex) {
throw new IOException(ex);
}
}
-
+
/**
- * Uploads a file.
- * If the file is already existing in the remote directory, it will be overwritten.
+ * Uploads a file. If the file is already existing in the remote directory, it
+ * will be overwritten.
*
- * @param localSrcFilePath the local source file name, absolute or relative to the current local directory.
- * @param remoteDstFilePath the remote destination file name, absolute or relative to the current remote directory.
+ * @param localSrcFilePath the local source file name, absolute or relative to
+ * the current local directory.
+ * @param remoteDstFilePath the remote destination file name, absolute or
+ * relative to the current remote directory.
* @throws IOException
*/
public void uploadFile(String localSrcFilePath, String remoteDstFilePath) throws IOException {
try {
channel.put(localSrcFilePath, remoteDstFilePath);
- }
- catch (SftpException ex) {
+ } catch (SftpException ex) {
throw new IOException(ex);
}
}
-
+
/**
- * Downloads a file to an OutputStream. This uses OVERWRITE mode and no progress monitor.
+ * Downloads a file to an OutputStream. This uses OVERWRITE mode and no progress
+ * monitor.
*
- * @param remoteSrcFilePath the source file name, relative to the current remote directory
- * @param oStream the Output Stream
+ * @param remoteSrcFilePath the source file name, relative to the current remote
+ * directory
+ * @param oStream the Output Stream
* @throws IOException
*/
public void downloadFile(String remoteSrcFilePath, OutputStream oStream) throws IOException {
try {
channel.get(remoteSrcFilePath, oStream);
- }
- catch (SftpException ex) {
+ } catch (SftpException ex) {
throw new IOException(ex);
}
}
-
+
/**
- * Downloads a file.
- * If the file is already existing in the local directory, it will be overwritten.
+ * Downloads a file. If the file is already existing in the local directory, it
+ * will be overwritten.
*
- * @param remoteSrcFilePath the source file name, relative to the current remote directory.
- * @param localDstFilePath the destination file name, relative to the current local directory.
+ * @param remoteSrcFilePath the source file name, relative to the current remote
+ * directory.
+ * @param localDstFilePath the destination file name, relative to the current
+ * local directory.
* @throws IOException
*/
public void downloadFile(String remoteSrcFilePath, String localDstFilePath) throws IOException {
try {
channel.get(remoteSrcFilePath, localDstFilePath);
- }
- catch (SftpException ex) {
+ } catch (SftpException ex) {
throw new IOException(ex);
}
}
-
+
/**
* Removes one remote file or one remote directory and its content.
*
@@ -278,17 +295,16 @@ public void downloadFile(String remoteSrcFilePath, String localDstFilePath) thro
*/
public void deleteRemoteFileOrDir(String path) throws IOException {
FileData fd = getFileData(path);
- if(fd != null) {
- if(fd.isFile) {
+ if (fd != null) {
+ if (fd.isFile) {
try {
channel.rm(path); // Remove file
} catch (SftpException ex) {
throw new IOException(ex);
}
- }
- else if(fd.isDirectory) {
+ } else if (fd.isDirectory) {
List fileAndFolderList = getFileDataList(path); // List source directory structure
-
+
for (FileData item : fileAndFolderList) { // Iterate objects in the list to get file/folder names
if (item.isFile) { // If it is a file (not a directory)
try {
@@ -296,15 +312,16 @@ else if(fd.isDirectory) {
} catch (SftpException ex) {
throw new IOException(ex);
}
- }
- else if (!(".".equals(item.name) || "..".equals(item.name))) { // If it is a subdir
+ } else if (!(".".equals(item.name) || "..".equals(item.name))) { // If it is a subdir
try {
// removing sub directory.
channel.rmdir(path + "/" + item.name);
- } catch (Exception ex) { // If subdir is not empty and error occurs,
+ } catch (Exception ex) { // If subdir is not empty and error occurs,
// Do deleteRemoteFileOrDir on this subdir to enter it and clear its contents
deleteRemoteFileOrDir(path + "/" + item.name);
- LOG.warn("If subdir is not empty and error occurs, Do deleteRemoteFileOrDir on this subdir to enter it and clear its contents", ex);
+ LOG.warn(
+ "If subdir is not empty and error occurs, Do deleteRemoteFileOrDir on this subdir to enter it and clear its contents",
+ ex);
}
}
}
@@ -316,12 +333,14 @@ else if (!(".".equals(item.name) || "..".equals(item.name))) { // If it is a sub
}
}
}
-
+
/**
- * Changes the current remote directory.
- * This checks the existence and accessibility of the indicated directory, and changes the current remote directory setting.
+ * Changes the current remote directory. This checks the existence and
+ * accessibility of the indicated directory, and changes the current remote
+ * directory setting.
*
- * @param path a directory path, absolute or relative to the current remote path.
+ * @param path a directory path, absolute or relative to the current remote
+ * path.
* @throws IOException
*/
public void changeDir(String path) throws IOException {
@@ -331,31 +350,29 @@ public void changeDir(String path) throws IOException {
throw new IOException(ex);
}
}
-
+
/**
- * This method is called recursively to Upload the local folder content
- * to the SFTP server remote directory.
+ * This method is called recursively to Upload the local folder content to the
+ * SFTP server remote directory.
*
* @param sourcePath
*/
public void uploadAllFiles(String sourcePath) {
File sourceFile = new File(sourcePath);
File[] files = sourceFile.listFiles();
- for(File f : files) {
- if(f.isFile() && !f.getName().startsWith(".")) { // Copy if it is a file
+ for (File f : files) {
+ if (f.isFile() && !f.getName().startsWith(".")) { // Copy if it is a file
try {
uploadFile(new FileInputStream(f), f.getName());
} catch (IOException e) {
LOG.error("Error occured while uploading", e);
}
- }
- else {
+ } else {
// Check if the directory is already existing
FileData fileData = getFileData(f.getName());
if (fileData != null) {
LOG.debug("Directory exists IsDir=" + fileData.isDirectory);
- }
- else { // else create a directory
+ } else { // else create a directory
LOG.debug("Creating dir " + f.getName());
try {
makeRemoteDir(f.getName());
@@ -368,9 +385,9 @@ public void uploadAllFiles(String sourcePath) {
} catch (IOException e1) {
LOG.error("Error occured", e1);
}
-
+
uploadAllFiles(f.getAbsolutePath());
-
+
try {
changeDir("..");
} catch (IOException e1) {
@@ -381,8 +398,8 @@ public void uploadAllFiles(String sourcePath) {
}
/**
- * This method is called recursively to download the remote folder content
- * of the SFTP server.
+ * This method is called recursively to download the remote folder content of
+ * the SFTP server.
*
* @param sourcePath
* @param destinationPath
@@ -405,12 +422,14 @@ public void downloadAllFiles(String sourcePath, String destinationPath) {
}
}
}
-
+
/**
* Renames a file or directory.
*
- * @param oldpath the old name of the file, relative to the current remote directory.
- * @param newpath the new name of the file, relative to the current remote directory.
+ * @param oldpath the old name of the file, relative to the current remote
+ * directory.
+ * @param newpath the new name of the file, relative to the current remote
+ * directory.
* @throws IOException
*/
public void rename(String oldpath, String newpath) throws IOException {
@@ -420,8 +439,23 @@ public void rename(String oldpath, String newpath) throws IOException {
throw new IOException(ex);
}
}
+
+ private static String getVar(String store, String var) {
+ return Ivy.var().get(String.format("%s.%s.%s", SFTP_VAR, store, var));
+ }
+ public static String getClientHost(String store) {
+ return getVar(store, HOST_VAR);
+ }
+ public static String getPort(String store) {
+ return getVar(store, PORT_VAR);
+ }
+
+ public static String getUsername(String store) {
+ return getVar(store, USERNAME_VAR);
+ }
+
/**
* File information class
*
@@ -436,73 +470,84 @@ public static class FileData {
* The last modification date.
*/
Date modificationDate;
-
+
/**
* @return the isFile
*/
public boolean isFile() {
return isFile;
}
+
/**
* @param isFile the isFile to set
*/
public void setFile(boolean isFile) {
this.isFile = isFile;
}
+
/**
* @return the isDirectory
*/
public boolean isDirectory() {
return isDirectory;
}
+
/**
* @param isDirectory the isDirectory to set
*/
public void setDirectory(boolean isDirectory) {
this.isDirectory = isDirectory;
}
+
/**
* @return the parentPath
*/
public String getParentPath() {
return parentPath;
}
+
/**
* @param parentPath the parentPath to set
*/
public void setParentPath(String parentPath) {
this.parentPath = parentPath;
}
+
/**
* @return the name
*/
public String getName() {
return name;
}
+
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
+
/**
* @return the size
*/
public long getSize() {
return size;
}
+
/**
* @param size the size to set
*/
public void setSize(long size) {
this.size = size;
}
+
/**
* @return the modificationDate
*/
public Date getModificationDate() {
return modificationDate;
}
+
/**
* @param modificationDate the modificationDate to set
*/
@@ -511,4 +556,3 @@ public void setModificationDate(Date modificationDate) {
}
}
}
-