From 554c7ce50dc41e4887b5b61f419340f6f8933346 Mon Sep 17 00:00:00 2001 From: Nicholas Sushkin Date: Wed, 17 Nov 2021 13:41:32 -0500 Subject: [PATCH 1/6] Merge support for download requests with start/end date from styppo - Merged styppo's commit 014df1e36f5f935de6692a4440b1ff3b4358aaeb limited to only changes related to the support for start and end dates --- .../org/kopi/ebics/client/EbicsClient.java | 24 ++++++++++++++++++- .../DownloadInitializationRequestElement.java | 17 +++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kopi/ebics/client/EbicsClient.java b/src/main/java/org/kopi/ebics/client/EbicsClient.java index 48eb0332..11a0cfc2 100644 --- a/src/main/java/org/kopi/ebics/client/EbicsClient.java +++ b/src/main/java/org/kopi/ebics/client/EbicsClient.java @@ -26,6 +26,8 @@ import java.io.ObjectInputStream; import java.net.URL; import java.security.GeneralSecurityException; +import java.text.SimpleDateFormat; +import java.time.Instant; import java.util.Arrays; import java.util.Date; import java.util.HashMap; @@ -611,6 +613,8 @@ public static void main(String[] args) throws Exception { options.addOption("o", "output", true, "output file"); options.addOption("i", "input", true, "input file"); + options.addOption("s", "start", true, "Start date (yyyy-MM-dd)"); + options.addOption("e", "end", true, "End date (yyyy-MM-dd)"); CommandLine cmd = parseArguments(options, args); @@ -642,6 +646,24 @@ public static void main(String[] args) throws Exception { String outputFileValue = cmd.getOptionValue("o"); String inputFileValue = cmd.getOptionValue("i"); + // Process start and end dates. + // If the end date is specified, start date is required + // If the start date is specified, the end date defaults + // to the current date. + String start = cmd.getOptionValue("s"); + String end = cmd.getOptionValue("e"); + Date startDate = null; + Date endDate = null; + if (start != null) { + final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + startDate = format.parse(start); + endDate = end != null + ? format.parse(end) + : Date.from(Instant.now()); + } else if (end != null) { + throw new EbicsException("Start date required if end date is given"); + } + List fetchFileOrders = Arrays.asList(OrderType.STA, OrderType.VMK, OrderType.C52, OrderType.C53, OrderType.C54, OrderType.ZDF, OrderType.ZB6, OrderType.PTK, OrderType.HAC, OrderType.Z01); @@ -649,7 +671,7 @@ public static void main(String[] args) throws Exception { for (EbicsOrderType type : fetchFileOrders) { if (hasOption(cmd, type)) { client.fetchFile(getOutputFile(outputFileValue), client.defaultUser, - client.defaultProduct, type, false, null, null); + client.defaultProduct, type, false, startDate, endDate); break; } } diff --git a/src/main/java/org/kopi/ebics/xml/DownloadInitializationRequestElement.java b/src/main/java/org/kopi/ebics/xml/DownloadInitializationRequestElement.java index 4bc96c3e..73705d38 100644 --- a/src/main/java/org/kopi/ebics/xml/DownloadInitializationRequestElement.java +++ b/src/main/java/org/kopi/ebics/xml/DownloadInitializationRequestElement.java @@ -125,9 +125,22 @@ public void buildInitialization() throws EbicsException { orderType, fDLOrderParamsType); } else { - StandardOrderParamsType standardOrderParamsType; + StandardOrderParamsType standardOrderParamsType; + standardOrderParamsType = EbicsXmlFactory.createStandardOrderParamsType(); + + if (startRange != null && endRange != null) { + StandardOrderParamsType.DateRange range = StandardOrderParamsType.DateRange.Factory.newInstance(); + Calendar start = Calendar.getInstance(); + Calendar end = Calendar.getInstance(); + start.setTime(startRange); + end.setTime(endRange); + range.setStart(start); + range.setEnd(end); + + standardOrderParamsType.setDateRange(range); + } + - standardOrderParamsType = EbicsXmlFactory.createStandardOrderParamsType(); //FIXME Some banks cannot handle OrderID element in download process. Add parameter in configuration!!! orderDetails = EbicsXmlFactory.createStaticHeaderOrderDetailsType(null,//session.getUser().getPartner().nextOrderId(), OrderAttributeType.DZHNN, From 337d0633944fdb4e4fedf5124dec57a54d3de9e4 Mon Sep 17 00:00:00 2001 From: Nicholas Sushkin Date: Wed, 17 Nov 2021 17:01:22 -0500 Subject: [PATCH 2/6] Add support for any custom order type - Support any bank's custom order types via new options --download and --upload - Add logging of the order type --- .../org/kopi/ebics/client/EbicsClient.java | 60 ++++++++++++++----- .../kopi/ebics/session/CustomOrderType.java | 46 ++++++++++++++ .../kopi/ebics/client/messages_en.properties | 2 + .../kopi/ebics/client/messages_fr.properties | 44 +++++++------- 4 files changed, 115 insertions(+), 37 deletions(-) create mode 100644 src/main/java/org/kopi/ebics/session/CustomOrderType.java diff --git a/src/main/java/org/kopi/ebics/client/EbicsClient.java b/src/main/java/org/kopi/ebics/client/EbicsClient.java index 11a0cfc2..3020f86f 100644 --- a/src/main/java/org/kopi/ebics/client/EbicsClient.java +++ b/src/main/java/org/kopi/ebics/client/EbicsClient.java @@ -28,6 +28,7 @@ import java.security.GeneralSecurityException; import java.text.SimpleDateFormat; import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; @@ -55,6 +56,7 @@ import org.kopi.ebics.io.IOUtils; import org.kopi.ebics.messages.Messages; import org.kopi.ebics.schema.h003.OrderAttributeType; +import org.kopi.ebics.session.CustomOrderType; import org.kopi.ebics.session.DefaultConfiguration; import org.kopi.ebics.session.EbicsSession; import org.kopi.ebics.session.OrderType; @@ -392,6 +394,8 @@ public void sendFile(File file, User user, Product product, EbicsOrderType order configuration.getTransferTraceDirectory(user)); try { + configuration.getLogger().info(messages.getString("upload.request.send", + orderType.getCode())); transferManager.sendFile(IOUtils.getFileContent(file), orderType, orderAttribute); } catch (IOException | EbicsException e) { configuration.getLogger() @@ -418,6 +422,8 @@ public void fetchFile(File file, User user, Product product, EbicsOrderType orde configuration.getTransferTraceDirectory(user)); try { + configuration.getLogger().info(messages.getString("download.request.send", + orderType.getCode())); transferManager.fetchFile(orderType, start, end, file); } catch (NoDownloadDataAvailableException e) { // don't log this exception as an error, caller can decide how to handle @@ -616,6 +622,9 @@ public static void main(String[] args) throws Exception { options.addOption("s", "start", true, "Start date (yyyy-MM-dd)"); options.addOption("e", "end", true, "End date (yyyy-MM-dd)"); + options.addOption("d", "download", true, "download custom order type"); + options.addOption("u", "upload", true, "upload custom order type"); + CommandLine cmd = parseArguments(options, args); File defaultRootDir = new File(System.getProperty("user.home") + File.separator + "ebics" @@ -664,25 +673,44 @@ public static void main(String[] args) throws Exception { throw new EbicsException("Start date required if end date is given"); } - List fetchFileOrders = Arrays.asList(OrderType.STA, OrderType.VMK, - OrderType.C52, OrderType.C53, OrderType.C54, - OrderType.ZDF, OrderType.ZB6, OrderType.PTK, OrderType.HAC, OrderType.Z01); - - for (EbicsOrderType type : fetchFileOrders) { - if (hasOption(cmd, type)) { - client.fetchFile(getOutputFile(outputFileValue), client.defaultUser, - client.defaultProduct, type, false, startDate, endDate); - break; + if (cmd.hasOption("d")) + { + client.fetchFile(getOutputFile(outputFileValue), client.defaultUser, + client.defaultProduct, + new CustomOrderType(cmd.getOptionValue("d")), + false, startDate, endDate); + } + else + { + List fetchFileOrders = Arrays.asList(OrderType.STA, OrderType.VMK, + OrderType.C52, OrderType.C53, OrderType.C54, + OrderType.ZDF, OrderType.ZB6, OrderType.PTK, OrderType.HAC, OrderType.Z01); + + for (EbicsOrderType type : fetchFileOrders) { + if (hasOption(cmd, type)) { + client.fetchFile(getOutputFile(outputFileValue), client.defaultUser, + client.defaultProduct, type, false, startDate, endDate); + break; + } } } - List sendFileOrders = Arrays.asList(OrderType.XKD, OrderType.FUL, OrderType.XCT, - OrderType.XE2, OrderType.CCT); - for (EbicsOrderType type : sendFileOrders) { - if (hasOption(cmd, type)) { - client.sendFile(new File(inputFileValue), client.defaultUser, - client.defaultProduct, type); - break; + if (cmd.hasOption("u")) + { + client.sendFile(new File(inputFileValue), client.defaultUser, + client.defaultProduct, + new CustomOrderType(cmd.getOptionValue("u"))); + } + else + { + List sendFileOrders = Arrays.asList(OrderType.XKD, OrderType.FUL, OrderType.XCT, + OrderType.XE2, OrderType.CCT); + for (EbicsOrderType type : sendFileOrders) { + if (hasOption(cmd, type)) { + client.sendFile(new File(inputFileValue), client.defaultUser, + client.defaultProduct, type); + break; + } } } diff --git a/src/main/java/org/kopi/ebics/session/CustomOrderType.java b/src/main/java/org/kopi/ebics/session/CustomOrderType.java new file mode 100644 index 00000000..ce00ba0f --- /dev/null +++ b/src/main/java/org/kopi/ebics/session/CustomOrderType.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, Digital Financial, LLC. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.kopi.ebics.session; + +import java.util.Objects; +import org.kopi.ebics.interfaces.EbicsOrderType; + +/** + * + * @author nsushkin + */ +public class CustomOrderType implements EbicsOrderType { + + private final String code; + + public CustomOrderType(String code) { + Objects.requireNonNull(code, "CustomOrderType code must not be null"); + this.code = code.toUpperCase(); + } + + /** + * Get the value of code + * + * @return the value of code + */ + @Override + public String getCode() { + return code; + } + +} diff --git a/src/main/resources/org/kopi/ebics/client/messages_en.properties b/src/main/resources/org/kopi/ebics/client/messages_en.properties index 3f92d5b2..8666c83f 100644 --- a/src/main/resources/org/kopi/ebics/client/messages_en.properties +++ b/src/main/resources/org/kopi/ebics/client/messages_en.properties @@ -23,6 +23,7 @@ app.quit.error = Error while saving users information app.quit.partners = Saving {0} partner information app.quit.users = Saving {0} user information +download.request.send = Downloading file for order type {0} download.file.error = Cannot download the requested file hia.request.send = Sending authentication and encryption certificates for {0} user @@ -41,6 +42,7 @@ ini.send.success = The signature certificate has been sent correctly for the { init.configuration = Configuration initialization +upload.request.send = Uploading file for order type {0} upload.file.error = Cannot upload file {0} to the ebics server upload.segment = Uploading segment number {0} diff --git a/src/main/resources/org/kopi/ebics/client/messages_fr.properties b/src/main/resources/org/kopi/ebics/client/messages_fr.properties index 7af2ce38..e2667c53 100644 --- a/src/main/resources/org/kopi/ebics/client/messages_fr.properties +++ b/src/main/resources/org/kopi/ebics/client/messages_fr.properties @@ -23,37 +23,39 @@ app.quit.error = Erreur dans la sauvgarde des informations utilisateurs app.quit.partners = Sauvgarde des informations concernant le partenaire {0} app.quit.users = Sauvgarde des informations concernant l''utilisateur {0} -download.file.error = Erreur dans le t\u00E9l\u00E9chargement du fichier +download.request.send = R\u00e9cup\u00e9ration du fichier pour la commande de type {0} +download.file.error = Erreur dans le t\u00e9l\u00e9chargement du fichier hia.request.send = Envoi des certificats d''authentification et de cryptage pour l''utilisateur {0} -hia.send.error = Les certificats d''authentification et de cryptage n''ont pas \u00E9t\u00E9 envoy\u00E9s pour l''utilisateur {0} -hia.send.success = Les certificats d''authentification et de cryptage ont \u00E9t\u00E9 envoy\u00E9s avec succ\u00E8s pour l''utilisateur {0} +hia.send.error = Les certificats d''authentification et de cryptage n''ont pas \u00e9t\u00e9 envoy\u00e9s pour l''utilisateur {0} +hia.send.success = Les certificats d''authentification et de cryptage ont \u00e9t\u00e9 envoy\u00e9s avec succ\u00e8s pour l''utilisateur {0} -hpb.request.send = R\u00E9cup\u00E9ration des cl\u00E9s publiques de la banque pour l''utilisateur {0} -hpb.send.error = Les cl\u00E9s publiques de la banque ne peuvent pas \u00EAtre r\u00E9cup\u00E9r\u00E9es pour l''utilisateur {0} -hpb.send.success = Les cl\u00E9s publiques de la banque ont \u00E9t\u00E9 r\u00E9cup\u00E9r\u00E9es avec succ\u00E8s pour l''utilisateur {0} +hpb.request.send = R\u00e9cup\u00e9ration des cl\u00e9s publiques de la banque pour l''utilisateur {0} +hpb.send.error = Les cl\u00e9s publiques de la banque ne peuvent pas \u00eatre r\u00e9cup\u00e9r\u00e9es pour l''utilisateur {0} +hpb.send.success = Les cl\u00e9s publiques de la banque ont \u00e9t\u00e9 r\u00e9cup\u00e9r\u00e9es avec succ\u00e8s pour l''utilisateur {0} -http.code.error = Code de retour HTTP erron\u00E9: {0} +http.code.error = Code de retour HTTP erron\u00e9: {0} ini.request.send = Envoie du certificat de signature pour l''utilisateur {0} -ini.send.error = Le certificat de signature ne peut pas \u00EAtre envoy\u00E9 pour l''utilisateur {0} -ini.send.success = Le certificat de signature a \u00E9t\u00E9 envoy\u00E9 avec succ\u00E8s pour l''utilisateur {0} +ini.send.error = Le certificat de signature ne peut pas \u00eatre envoy\u00e9 pour l''utilisateur {0} +ini.send.success = Le certificat de signature a \u00e9t\u00e9 envoy\u00e9 avec succ\u00e8s pour l''utilisateur {0} init.configuration = Initialisation de la configuration -upload.file.error = Le fichier {0} ne peut pas \u00EAtre envoy\u00E9 au server ebics -upload.segment = Envoie du segment num\u00E9ro {0} - -user.already.hia.initialized = Les certificats d''autentification et de cryptage on \u00E9t\u00E9 d\u00E9j\u00E0 envoy\u00E9 pour l''utilisateur {0} -user.already.initialized = Le certificate de signature a \u00E9t\u00E9 d\u00E9j\u00E0 envoy\u00E9 pour l''utilisateur {0} -user.create.directories = Cr\u00E9ation des r\u00E9p\u00E9rtoires n\u00E9cessaires pour l''utilisateur {0} -user.create.error = L''utilisateur ne peut pas \u00EAtre cr\u00E9e -user.create.info = Cr\u00E9ation du nouvel utilisateur {0} -user.create.success = L''utilisateur {0} a \u00E9t\u00E9 cr\u00E9e avec succ\u00E8s -user.load.error = L''utilisateur ne peut pas \u00EAtre charg\u00E9 +upload.request.send = Envoi du fichier pour le type de commande {0} +upload.file.error = Le fichier {0} ne peut pas \u00eatre envoy\u00e9 au server ebics +upload.segment = Envoie du segment num\u00e9ro {0} + +user.already.hia.initialized = Les certificats d''autentification et de cryptage on \u00e9t\u00e9 d\u00e9j\u00e0 envoy\u00e9 pour l''utilisateur {0} +user.already.initialized = Le certificate de signature a \u00e9t\u00e9 d\u00e9j\u00e0 envoy\u00e9 pour l''utilisateur {0} +user.create.directories = Cr\u00e9ation des r\u00e9p\u00e9rtoires n\u00e9cessaires pour l''utilisateur {0} +user.create.error = L''utilisateur ne peut pas \u00eatre cr\u00e9e +user.create.info = Cr\u00e9ation du nouvel utilisateur {0} +user.create.success = L''utilisateur {0} a \u00e9t\u00e9 cr\u00e9e avec succ\u00e8s +user.load.error = L''utilisateur ne peut pas \u00eatre charg\u00e9 user.load.info = Chargement de l''utilisateur {0} -user.load.success = L''utilisateur {0} a \u00E9t\u00E9 charg\u00E9 avec succ\u00E8s +user.load.success = L''utilisateur {0} a \u00e9t\u00e9 charg\u00e9 avec succ\u00e8s spr.request.send = Blockage de l''utilisateur {0} spr.send.error = Erreur dans le bloquage de l''utilisateur {0} -spr.send.success = L''utilisateur {0} est bloqué. Vous devez effectuez les opérations d''initialisations à nouveau. \ No newline at end of file +spr.send.success = L''utilisateur {0} est bloqu\u00e9. Vous devez effectuez les op\u00e9rations d''initialisations \u00e0 nouveau. \ No newline at end of file From f5f440a080b7fa586b5a2ebfe95039a6f2d31e59 Mon Sep 17 00:00:00 2001 From: Nicholas Sushkin Date: Thu, 18 Nov 2021 13:16:49 -0500 Subject: [PATCH 3/6] Package Ebics Client as a single jar - Use executable-packer-maven-plugin to package the project in a single jar. This plugin uses a Jar-in-Jar approach which does not break digital signature of the Bouncy Castle JCE provider jar. Run "mvn package" to package and run "java -jar ebics*.jar" to execute EbicsClient main class. --- pom.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pom.xml b/pom.xml index 4958a27b..d7fd5be9 100644 --- a/pom.xml +++ b/pom.xml @@ -139,6 +139,21 @@ maven-surefire-plugin 2.22.1 + + de.ntcomputer + executable-packer-maven-plugin + 1.0.1 + + org.kopi.ebics.client.EbicsClient + + + + + pack-executable-jar + + + + From 1b03d39a549f41daaa830810f8083b2e049bee0c Mon Sep 17 00:00:00 2001 From: Nicholas Sushkin Date: Thu, 18 Nov 2021 13:25:06 -0500 Subject: [PATCH 4/6] When download request has no data, warn instead of crashing - When requesting order types that download data, NoDataException is a common occurrence. In this case, the client writes a warning to the log and exits with error code 2 (to distinguish the condition from other errors which return error code 1). - When a file download succeeds, the client logs the success. - Introduce new method EbicsClient.fetchFileIfAvailable which wraps fetchFile with warn and log. --- .../org/kopi/ebics/client/EbicsClient.java | 49 +++++++++++++++++-- .../kopi/ebics/client/messages_en.properties | 2 + .../kopi/ebics/client/messages_fr.properties | 4 +- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kopi/ebics/client/EbicsClient.java b/src/main/java/org/kopi/ebics/client/EbicsClient.java index 3020f86f..859fcf93 100644 --- a/src/main/java/org/kopi/ebics/client/EbicsClient.java +++ b/src/main/java/org/kopi/ebics/client/EbicsClient.java @@ -28,7 +28,6 @@ import java.security.GeneralSecurityException; import java.text.SimpleDateFormat; import java.time.Instant; -import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; @@ -48,6 +47,7 @@ import org.kopi.ebics.exception.NoDownloadDataAvailableException; import org.kopi.ebics.interfaces.Configuration; import org.kopi.ebics.interfaces.EbicsBank; +import org.kopi.ebics.interfaces.EbicsLogger; import org.kopi.ebics.interfaces.EbicsOrderType; import org.kopi.ebics.interfaces.EbicsUser; import org.kopi.ebics.interfaces.InitLetter; @@ -439,6 +439,35 @@ public void fetchFile(File file, EbicsOrderType orderType, Date start, Date end) fetchFile(file, defaultUser, defaultProduct, orderType, false, start, end); } + /** + * Downloads file for order type without throwing NoDataAvailableException. + * + * Downloads file for the order type and logs success or warns about no data. + * + * @param file output file + * @param user EBICS User + * @param product EBICS Product + * @param orderType EBICS Order Type + * @param start Optional Date Range Start Date + * @param end Optional Date Range End Date + * @return true if data was available, false if not + * @throws java.io.IOException + * @throws org.kopi.ebics.exception.EbicsException + */ + public boolean fetchFileIfAvailable(File file, User user, Product product, + EbicsOrderType orderType, Date start, Date end) throws IOException, + EbicsException { + + final EbicsLogger logger = configuration.getLogger(); + try { + fetchFile(file, user, product, orderType, false, start, end); + configuration.getLogger().info(messages.getString("download.file.success", orderType.getCode())); + return true; + } catch (NoDownloadDataAvailableException nodataException) { + configuration.getLogger().warn(messages.getString("download.file.nodata", orderType.getCode())); + return false; + } + } /** * Performs buffers save before quitting the client application. */ @@ -673,12 +702,15 @@ public static void main(String[] args) throws Exception { throw new EbicsException("Start date required if end date is given"); } + boolean allDataWasAvailable = true; + if (cmd.hasOption("d")) { - client.fetchFile(getOutputFile(outputFileValue), client.defaultUser, + allDataWasAvailable &= client.fetchFileIfAvailable(getOutputFile(outputFileValue), + client.defaultUser, client.defaultProduct, new CustomOrderType(cmd.getOptionValue("d")), - false, startDate, endDate); + startDate, endDate); } else { @@ -688,8 +720,11 @@ public static void main(String[] args) throws Exception { for (EbicsOrderType type : fetchFileOrders) { if (hasOption(cmd, type)) { - client.fetchFile(getOutputFile(outputFileValue), client.defaultUser, - client.defaultProduct, type, false, startDate, endDate); + allDataWasAvailable &= client.fetchFileIfAvailable(getOutputFile(outputFileValue), + client.defaultUser, + client.defaultProduct, + type, + startDate, endDate); break; } } @@ -721,6 +756,10 @@ public static void main(String[] args) throws Exception { } } client.quit(); + if (!allDataWasAvailable) + { + System.exit(2); + } } private static File getOutputFile(String outputFileName) { diff --git a/src/main/resources/org/kopi/ebics/client/messages_en.properties b/src/main/resources/org/kopi/ebics/client/messages_en.properties index 8666c83f..ecaf447f 100644 --- a/src/main/resources/org/kopi/ebics/client/messages_en.properties +++ b/src/main/resources/org/kopi/ebics/client/messages_en.properties @@ -25,6 +25,8 @@ app.quit.users = Saving {0} user information download.request.send = Downloading file for order type {0} download.file.error = Cannot download the requested file +download.file.success = Data has been retrieved correctly for order type {0} +download.file.nodata = No data available for order type {0} hia.request.send = Sending authentication and encryption certificates for {0} user hia.send.error = The authentication and encryption certificates has not been sent for the {0} user diff --git a/src/main/resources/org/kopi/ebics/client/messages_fr.properties b/src/main/resources/org/kopi/ebics/client/messages_fr.properties index e2667c53..132dec97 100644 --- a/src/main/resources/org/kopi/ebics/client/messages_fr.properties +++ b/src/main/resources/org/kopi/ebics/client/messages_fr.properties @@ -23,8 +23,10 @@ app.quit.error = Erreur dans la sauvgarde des informations utilisateurs app.quit.partners = Sauvgarde des informations concernant le partenaire {0} app.quit.users = Sauvgarde des informations concernant l''utilisateur {0} -download.request.send = R\u00e9cup\u00e9ration du fichier pour la commande de type {0} +download.request.send = R\u00e9cup\u00e9ration du fichier pour la type de commande {0} download.file.error = Erreur dans le t\u00e9l\u00e9chargement du fichier +download.file.success = Les donn\u00e9es ont \u00e9t\u00e9 r\u00e9cup\u00e9r\u00e9es avec succ\u00e8s pour le type de commande {0} +download.file.nodata = Pas de donn\u00e9es disponibles pour la type de commande {0} hia.request.send = Envoi des certificats d''authentification et de cryptage pour l''utilisateur {0} hia.send.error = Les certificats d''authentification et de cryptage n''ont pas \u00e9t\u00e9 envoy\u00e9s pour l''utilisateur {0} From 9540c0110afc1eedcd31d09cdd0c03a1363fae6b Mon Sep 17 00:00:00 2001 From: Nicholas Sushkin Date: Thu, 18 Nov 2021 17:37:12 -0500 Subject: [PATCH 5/6] Add options to specify configuration directory and print version - Add option --configuration-directory to override the default value of ${user.home}/ebics/client - Add option --version to print version information --- pom.xml | 6 +++++ .../org/kopi/ebics/client/EbicsClient.java | 24 ++++++++++++++++++- src/main/resources/build.properties | 2 ++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/build.properties diff --git a/pom.xml b/pom.xml index d7fd5be9..a26fe1e5 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,12 @@ + + + src/main/resources + true + + org.codehaus.mojo diff --git a/src/main/java/org/kopi/ebics/client/EbicsClient.java b/src/main/java/org/kopi/ebics/client/EbicsClient.java index 859fcf93..f5109905 100644 --- a/src/main/java/org/kopi/ebics/client/EbicsClient.java +++ b/src/main/java/org/kopi/ebics/client/EbicsClient.java @@ -23,6 +23,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.ObjectInputStream; import java.net.URL; import java.security.GeneralSecurityException; @@ -35,6 +36,8 @@ import java.util.Locale; import java.util.Map; import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; @@ -544,6 +547,7 @@ private User createUser(ConfigProperties properties, PasswordCallback pwdHandler private static CommandLine parseArguments(Options options, String[] args) throws ParseException { CommandLineParser parser = new DefaultParser(); options.addOption(null, "help", false, "Print this help text"); + options.addOption(null, "version", false, "Print the version information and exit"); CommandLine line = parser.parse(options, args); if (line.hasOption("help")) { HelpFormatter formatter = new HelpFormatter(); @@ -552,6 +556,20 @@ private static CommandLine parseArguments(Options options, String[] args) throws System.out.println(); System.exit(0); } + if (line.hasOption("version")) { + InputStream streamOrNull = EbicsClient.class.getClassLoader().getResourceAsStream( + "build.properties"); + if (streamOrNull != null) { + try { + Properties properties = new Properties(); + properties.load(streamOrNull); + System.out.println(properties.getProperty("build.name") + " " + + properties.getProperty("build.version")); + } catch (IOException ex) {} + + } + System.exit(0); + } return line; } @@ -654,10 +672,14 @@ public static void main(String[] args) throws Exception { options.addOption("d", "download", true, "download custom order type"); options.addOption("u", "upload", true, "upload custom order type"); + options.addOption("c", "configuration-directory", true, "Configuration directory"); + CommandLine cmd = parseArguments(options, args); - File defaultRootDir = new File(System.getProperty("user.home") + File.separator + "ebics" + String configurationDirectory = cmd.getOptionValue("configuration-directory", + System.getProperty("user.home") + File.separator + "ebics" + File.separator + "client"); + File defaultRootDir = new File(configurationDirectory); File ebicsClientProperties = new File(defaultRootDir, "ebics.txt"); EbicsClient client = createEbicsClient(defaultRootDir, ebicsClientProperties); diff --git a/src/main/resources/build.properties b/src/main/resources/build.properties new file mode 100644 index 00000000..9b161998 --- /dev/null +++ b/src/main/resources/build.properties @@ -0,0 +1,2 @@ +build.version=${pom.version} +build.name=${pom.name} \ No newline at end of file From e298c6771437f8eecdef58b95d2849c6bf1c42cd Mon Sep 17 00:00:00 2001 From: Nicholas Sushkin Date: Thu, 18 Nov 2021 21:13:11 -0500 Subject: [PATCH 6/6] Implement override of configuration properties with the system ones - In DefaultConfiguration.java, any configuration property that comes from a key in the configuration file can be overriden with a system property with the same key. For example, specify -Dlog.dir.name=/var/log to override the default ebics/client/log directory. - In DefaultConfiguration.java, if a property is a compound of a directory name and a file name, specifying an absolute file name overrides the directory name. For example, -Dtraces.dir.name=/var/local/traces overrides the default value of traces under ebics/client/users/USERNAME. --- .../ebics/session/DefaultConfiguration.java | 51 ++++++++++++++----- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/kopi/ebics/session/DefaultConfiguration.java b/src/main/java/org/kopi/ebics/session/DefaultConfiguration.java index 7e66fbcf..e1debf13 100644 --- a/src/main/java/org/kopi/ebics/session/DefaultConfiguration.java +++ b/src/main/java/org/kopi/ebics/session/DefaultConfiguration.java @@ -41,6 +41,9 @@ /** * A simple client application configuration. * + * Loads client configuration from a property file, but allows properties + * to be overridden from the System properties. + * * @author hachani * */ @@ -60,13 +63,17 @@ public DefaultConfiguration(String rootDir, Properties properties) { } /** - * Returns the corresponding property of the given key + * Returns the corresponding property of the given key. + * + * First, attempts to load property from system properties. If none found, + * loads the property from the bundle. + * * @param key the property key * @return the property value. */ private String getString(String key) { try { - return bundle.getString(key); + return System.getProperty(key, bundle.getString(key)); } catch(MissingResourceException e) { return "!!" + key + "!!"; } @@ -94,7 +101,7 @@ public void init() { //Create users directory IOUtils.createDirectories(getUsersDirectory()); - logger.setLogFile(getLogDirectory() + File.separator + getLogFileName()); + logger.setLogFile(resolveFile(getLogDirectory(), getLogFileName())); ((DefaultEbicsLogger)logger).setFileLoggingEnabled(true); ((DefaultEbicsLogger)logger).setLevel(DefaultEbicsLogger.ALL_LEVEL); serializationManager.setSerializationDirectory(getSerializationDirectory()); @@ -102,6 +109,24 @@ public void init() { letterManager = new DefaultLetterManager(getLocale()); } + /** + * Returns absolute file name or prepends directory name. + * + *

If fileName starts with path separator, just returns the fileName. + * Otherwise, prepends directory name and a path separator. + * + * @param directory directory name + * @param file file name + * @return + */ + public static String resolveFile(String directory, String file) { + if (file != null && file.startsWith(File.separator)) { + return file; + } else { + return directory + File.separator + file; + } + } + @Override public Locale getLocale() { return Locale.FRANCE; @@ -109,7 +134,7 @@ public Locale getLocale() { @Override public String getLogDirectory() { - return rootDir + File.separator + getString("log.dir.name"); + return resolveFile(rootDir, getString("log.dir.name")); } @Override @@ -119,7 +144,7 @@ public String getLogFileName() { @Override public String getConfigurationFile() { - return rootDir + File.separator + getString("conf.file.name"); + return resolveFile(rootDir, getString("conf.file.name")); } @Override @@ -129,22 +154,22 @@ public String getProperty(String key) { @Override public String getKeystoreDirectory(EbicsUser user) { - return getUserDirectory(user) + File.separator + getString("keystore.dir.name"); + return resolveFile(getUserDirectory(user), getString("keystore.dir.name")); } @Override public String getTransferTraceDirectory(EbicsUser user) { - return getUserDirectory(user) + File.separator + getString("traces.dir.name"); + return resolveFile(getUserDirectory(user), getString("traces.dir.name")); } @Override public String getSerializationDirectory() { - return rootDir + File.separator + getString("serialization.dir.name"); + return resolveFile(rootDir, getString("serialization.dir.name")); } @Override public String getSSLTrustedStoreDirectory() { - return rootDir + File.separator + getString("ssltruststore.dir.name"); + return resolveFile(rootDir, getString("ssltruststore.dir.name")); } @Override @@ -154,12 +179,12 @@ public String getSSLKeyStoreDirectory() { @Override public String getSSLBankCertificates() { - return rootDir + File.separator + getString("sslbankcert.dir.name"); + return resolveFile(rootDir, getString("sslbankcert.dir.name")); } @Override public String getUsersDirectory() { - return rootDir + File.separator + getString("users.dir.name"); + return resolveFile(rootDir, getString("users.dir.name")); } @Override @@ -179,12 +204,12 @@ public LetterManager getLetterManager() { @Override public String getLettersDirectory(EbicsUser user) { - return getUserDirectory(user) + File.separator + getString("letters.dir.name"); + return resolveFile(getUserDirectory(user), getString("letters.dir.name")); } @Override public String getUserDirectory(EbicsUser user) { - return getUsersDirectory() + File.separator + user.getUserId(); + return resolveFile(getUsersDirectory(), user.getUserId()); } @Override