diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/CargosoftExportAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/CargosoftExportAdapter.java index 39fc1dd..2920a63 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/CargosoftExportAdapter.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/CargosoftExportAdapter.java @@ -3,12 +3,14 @@ package com.alexanderlogistics; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.logging.Logger; import javax.inject.Inject; import javax.xml.bind.JAXBException; import javax.xml.transform.TransformerException; +import org.eclipse.microprofile.config.inject.ConfigProperty; import org.imixs.workflow.FileData; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.SignalAdapter; @@ -47,11 +49,20 @@ public class CargosoftExportAdapter implements SignalAdapter { private static Logger logger = Logger.getLogger(CargosoftExportAdapter.class.getName()); + + @Inject + @ConfigProperty(name = FTPConnector.ENV_EXPORT_FTP_HOST) + Optional ftpServer; + + @Inject WorkflowService workflowService; @Inject ReportService reportService; + + @Inject + FTPConnector ftpConnector; /** * This method computes the cargosoft export data file @@ -85,6 +96,12 @@ public class CargosoftExportAdapter implements SignalAdapter { // attach result document.addFileData(exportFile); + // transfer file via FTP... + if (ftpServer.isPresent()) { + logger.info("ftp transfer..."); + ftpConnector.put(exportFile); + } + // finally append the success event id document.event(EVENT_SUCCESS); diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/FTPConnector.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/FTPConnector.java new file mode 100644 index 0000000..b5b39e4 --- /dev/null +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/FTPConnector.java @@ -0,0 +1,224 @@ +/******************************************************************************* + * Imixs Workflow Technology + * Copyright (C) 2001, 2008 Imixs Software Solutions GmbH, + * http://www.imixs.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You can receive a copy of the GNU General Public + * License at http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Imixs Software Solutions GmbH - initial API and implementation + * Ralph Soika + *******************************************************************************/ +package com.alexanderlogistics; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Optional; +import java.util.logging.Logger; + +import javax.ejb.Stateless; +import javax.inject.Inject; + +import org.apache.commons.net.ftp.FTP; +import org.apache.commons.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPSClient; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.imixs.workflow.FileData; +import org.imixs.workflow.exceptions.PluginException; + +/** + * The FTPConnector service provides methods to push a snapshot document into an + * FTP storage. The snapshot is stored in a directory based on the snapshot + * creation date. E.g. $created=2017-03-19 will put the data into the sub + * directory /2017/03/ + * + * @version 1.0 + * @author rsoika + */ + +@Stateless +public class FTPConnector { + + public static final String FTP_ERROR = "FTP_ERROR"; + public static final String ENV_EXPORT_FTP_HOST = "cargosoft.export.ftp.host"; + public static final String ENV_EXPORT_FTP_PATH = "cargosoft.export.ftp.path"; + public static final String ENV_EXPORT_FTP_PORT = "cargosoft.export.ftp.port"; + public static final String ENV_EXPORT_FTP_USER = "cargosoft.export.ftp.user"; + public static final String ENV_EXPORT_FTP_PASSWORD = "cargosoft.export.ftp.password"; + + private static Logger logger = Logger.getLogger(FTPConnector.class.getName()); + + @Inject + @ConfigProperty(name = ENV_EXPORT_FTP_HOST) + Optional ftpServer; + + @Inject + @ConfigProperty(name = ENV_EXPORT_FTP_PATH) + Optional ftpPath; + + @Inject + @ConfigProperty(name = ENV_EXPORT_FTP_PORT, defaultValue = "21") + int ftpPort; + + @Inject + @ConfigProperty(name = ENV_EXPORT_FTP_USER) + Optional ftpUser; + + @Inject + @ConfigProperty(name = ENV_EXPORT_FTP_PASSWORD) + Optional ftpPassword; + + /** + * This method transfers a snapshot to a ftp server. + * + * @param fileData object + * @throws PluginException + */ + public void put(FileData fileData) throws PluginException { + + if (!ftpServer.isPresent()) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: no ftp host name provided (" + ENV_EXPORT_FTP_HOST + ")!"); + } + + String fileName = fileData.getName(); + + // Compute file path + String ftpWorkingPath = ftpPath.get(); + if (!ftpWorkingPath.startsWith("/")) { + ftpWorkingPath = "/" + ftpWorkingPath; + } + if (!ftpWorkingPath.endsWith("/")) { + ftpWorkingPath = ftpWorkingPath + "/"; + } + InputStream writer = null; + + FTPClient ftpClient = null; + try { + logger.finest("......put " + fileName + " to FTP server: " + ftpServer + "..."); + ftpClient = new FTPSClient("TLS", false); + ftpClient.setControlEncoding("UTF-8"); + ftpClient.connect(ftpServer.get(), ftpPort); + if (ftpClient.login(ftpUser.get(), ftpPassword.get()) == false) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: login failed!"); + } + + ftpClient.enterLocalPassiveMode(); + // ftpClient.setFileType(FTP.ASCII_FILE_TYPE); + ftpClient.setFileType(FTP.BINARY_FILE_TYPE); + ftpClient.setControlEncoding("UTF-8"); + + // verify directories + if (!ftpClient.changeWorkingDirectory(ftpWorkingPath)) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: missing working directory '" + ftpWorkingPath + "' : " + + ftpClient.getReplyString()); + } + + // upload file to FTP server. + writer = new ByteArrayInputStream(fileData.getContent()); + + if (!ftpClient.storeFile(fileName, writer)) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: unable to write '" + ftpWorkingPath + fileName + "' : " + + ftpClient.getReplyString()); + } + + logger.finest("...." + ftpWorkingPath + fileName + " transfered successfull to " + ftpServer); + + } catch (IOException e) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: " + e.getMessage(), e); + } finally { + // do logout.... + try { + if (writer != null) { + writer.close(); + } + ftpClient.logout(); + ftpClient.disconnect(); + } catch (IOException e) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: " + e.getMessage(), e); + } + } + } + + /** + * This method reads data form the current working directory + * + * @param snapshot + * @throws ArchiveException + * @return data + */ + public byte[] get(FTPClient ftpClient, String fileName) throws PluginException { + if (ftpClient == null) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: no ftpClient provided!"); + } + + long l = System.currentTimeMillis(); + ByteArrayOutputStream bos = null; + try { + bos = new ByteArrayOutputStream(); + ftpClient.retrieveFile(fileName, bos); + byte[] result = bos.toByteArray(); + + logger.finest("......" + fileName + " transfered successfull from " + ftpServer + " in " + + (System.currentTimeMillis() - l) + "ms"); + return result; + } catch (IOException e) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: " + e.getMessage(), e); + } finally { + // do logout.... + try { + if (bos != null) { + bos.close(); + } + } catch (IOException e) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: " + e.getMessage(), e); + } + } + } + + /** + * This method changes the current working sub-directy. If no corresponding + * directory exits the method creats one. + * + * @throws ArchiveException + */ + @SuppressWarnings("unused") + private void changeWorkingDirectory(FTPClient ftpClient, String subDirectory) throws PluginException { + // test if we have the subdreictory + try { + if (!ftpClient.changeWorkingDirectory(subDirectory)) { + // try to creat it.... + if (!ftpClient.makeDirectory(subDirectory)) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP Error: unable to create sub-directory '" + subDirectory + "' : " + + ftpClient.getReplyString()); + } + ftpClient.changeWorkingDirectory(subDirectory); + } + } catch (IOException e) { + throw new PluginException(CargosoftExportAdapter.class.getSimpleName(), FTP_ERROR, + "FTP file transfer failed: " + e.getMessage(), e); + } + } +} diff --git a/pom.xml b/pom.xml index 09e12eb..175286a 100644 --- a/pom.xml +++ b/pom.xml @@ -211,6 +211,16 @@ 7.0 provided + + + + org.eclipse.microprofile + microprofile + ${microprofile.version} + pom + provided + + junit