
org.ow2.petals.bc.ftp.service.FTPService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of petals-bc-ftp Show documentation
Show all versions of petals-bc-ftp Show documentation
A binding component used to transfer files using ftp
/**
* Copyright (c) 2007-2012 EBM WebSourcing, 2012-2016 Linagora
*
* This program/library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or (at your
* option) any later version.
*
* This program/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 program/library; If not, see http://www.gnu.org/licenses/
* for the GNU Lesser General Public License version 2.1.
*/
package org.ow2.petals.bc.ftp.service;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;
import javax.activation.DataHandler;
import javax.jbi.messaging.MessagingException;
import org.ow2.petals.bc.ftp.FTPConstants;
import org.ow2.petals.bc.ftp.FTPUtil;
import org.ow2.petals.bc.ftp.FtpProvideExtFlowStepBeginLogData;
import org.ow2.petals.bc.ftp.FtpProvideExtFlowStepEndLogData;
import org.ow2.petals.bc.ftp.MissingElementException;
import org.ow2.petals.bc.ftp.connection.WrappedFTPClient;
import org.ow2.petals.commons.log.FlowAttributes;
import org.ow2.petals.commons.log.Level;
import org.ow2.petals.commons.log.PetalsExecutionContext;
import org.ow2.petals.component.framework.api.Message;
import org.ow2.petals.component.framework.api.Message.MEPConstants;
import org.ow2.petals.component.framework.api.message.Exchange;
import org.ow2.petals.component.framework.logger.ProvideExtFlowStepFailureLogData;
import org.ow2.petals.component.framework.util.MtomUtil;
import org.ow2.petals.component.framework.util.MtomUtil.MtomMapping;
import org.ow2.petals.component.framework.util.SourceUtil;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.ebmwebsourcing.easycommons.lang.StringHelper;
import com.ebmwebsourcing.easycommons.uuid.SimpleUUIDGenerator;
import com.ebmwebsourcing.easycommons.xml.XMLHelper;
/**
* The FTP JBI listener. Writes a file to FTP server on incoming JBI message.
*
* @author Mathieu CARROLLE - EBM WebSourcing
* @author Adrien Louis - EBM WebSourcing
* @author Roland Naudin - EBM WebSourcing
*/
public class FTPService {
/**
* An UUID generator.
*/
private final SimpleUUIDGenerator simpleUUIDGenerator = new SimpleUUIDGenerator();
private final Logger logger;
public FTPService(final Logger logger) {
super();
this.logger = logger;
}
/***
* FTP DEL Operation
*
* @param exchange
* @param connectionInfo
* @param inMessage
* @throws MissingElementException
* @throws Exception
*/
public void processDel(final Exchange exchange, final Document inMessage, final WrappedFTPClient client)
throws MessagingException, MissingElementException {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("JBI exchange received - Process DEL operation");
}
try {
// Checks the MEP of the incoming message
if (!exchange.isInOnlyPattern()) {
throw new MessagingException(FTPUtil.getOperationValidMep(FTPConstants.DEL_OPERATION,
Message.MEPConstants.IN_ONLY_PATTERN));
}
// retrieve the filename to get
final Node filePatternNode = XMLHelper.findChild(inMessage.getFirstChild(), null,
FTPConstants.FTP_FILENAME, false);
final String filePattern;
if (filePatternNode != null) {
filePattern = filePatternNode.getTextContent();
} else {
throw new MissingElementException(FTPConstants.FTP_FILENAME);
}
if (filePattern != null) {
final String newFlowStepId = this.simpleUUIDGenerator.getNewID();
final FlowAttributes flowAttributes = PetalsExecutionContext.getFlowAttributes();
final String flowInstanceId;
final String flowStepId;
if (flowAttributes != null) {
flowInstanceId = flowAttributes.getFlowInstanceId();
flowStepId = flowAttributes.getFlowStepId();
} else {
flowInstanceId = null;
flowStepId = null;
}
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepBeginLogData(flowInstanceId, flowStepId,
newFlowStepId, client.getConnectionInfo().getDirectory(), "(" + filePattern + ")"));
try {
// do the FTP DEL operation
client.del(filePattern);
this.logger
.log(Level.MONIT, "", new FtpProvideExtFlowStepEndLogData(flowInstanceId, newFlowStepId));
} catch (final IOException e) {
final StringBuilder errorSB = new StringBuilder();
errorSB.append("Can not delete file on FTP server [");
errorSB.append(client.getConnectionInfo().getServer());
errorSB.append("] : IOException : ");
errorSB.append(e.getMessage());
this.logger.log(Level.MONIT, "", new ProvideExtFlowStepFailureLogData(flowInstanceId,
newFlowStepId, errorSB.toString()));
throw new MessagingException(errorSB.toString());
}
}
} finally {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("DEL operation ended");
}
}
}
/**
* FTP DIR operation.
* a Fault is returned for bad request or IO problems
*
* @param exchange
* the message exchange, MUST be non null
* @throws MessagingException
* bad MEP
*/
public void processDir(final Exchange exchange, final WrappedFTPClient client) throws MessagingException {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("JBI exchange received - Process DIR operation");
}
try {
if (!exchange.isInOutPattern()) {
throw new MessagingException(FTPUtil.getOperationValidMep(FTPConstants.DIR_OPERATION,
MEPConstants.IN_OUT_PATTERN));
}
final String newFlowStepId = this.simpleUUIDGenerator.getNewID();
final FlowAttributes flowAttributes = PetalsExecutionContext.getFlowAttributes();
final String flowInstanceId;
final String flowStepId;
if (flowAttributes != null) {
flowInstanceId = flowAttributes.getFlowInstanceId();
flowStepId = flowAttributes.getFlowStepId();
} else {
flowInstanceId = null;
flowStepId = null;
}
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepBeginLogData(flowInstanceId, flowStepId,
newFlowStepId, client.getConnectionInfo().getDirectory()));
try {
// do the FTP DIR operation
final List fileNames = client.listFolderContent();
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepEndLogData(flowInstanceId, newFlowStepId));
// generate filename list
final String result = FTPUtil.generateFileNameList(fileNames, exchange.getOperation());
exchange.getOutMessage().setContent(SourceUtil.createSource(result));
} catch (final IOException e) {
final String errorMsg = "Can not list files on FTP server [" + client.getConnectionInfo().getServer()
+ "]. Cause : " + e.getMessage();
this.logger.log(Level.MONIT, "", new ProvideExtFlowStepFailureLogData(flowInstanceId, newFlowStepId,
errorMsg));
FTPUtil.setIOFaultOnExchange(exchange, errorMsg);
}
} finally {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("DIR operation ended");
}
}
}
/**
*
* FTP GET operation
* get the file as a source message a Fault is returned for bad request or IO problems
*
* @param exchange
* the message exchange, MUST be non null
* @param connectionInfo
* @param inMessage
* @throws MessagingException
* bad MEP
*/
public void processGet(final Exchange exchange, final Document inMessage, final WrappedFTPClient client)
throws MessagingException {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("JBI exchange received - Process GET operation");
}
try {
// Checks the MEP of the incoming message
if (!exchange.isInOutPattern()) {
throw new MessagingException(FTPUtil.getOperationValidMep(FTPConstants.GET_OPERATION,
Message.MEPConstants.IN_OUT_PATTERN));
}
// retrieve the filename to get
final Node filePatternNode = XMLHelper.findChild(inMessage.getFirstChild(), null,
FTPConstants.FTP_FILENAME, false);
final String filePattern;
if (filePatternNode != null) {
filePattern = filePatternNode.getTextContent();
} else {
filePattern = null;
}
if (StringHelper.isNullOrEmpty(filePattern)) {
FTPUtil.setMissingElementFaultOnExchange(exchange, FTPConstants.FTP_FILENAME);
} else {
final String newFlowStepId = this.simpleUUIDGenerator.getNewID();
final FlowAttributes flowAttributes = PetalsExecutionContext.getFlowAttributes();
final String flowInstanceId;
final String flowStepId;
if (flowAttributes != null) {
flowInstanceId = flowAttributes.getFlowInstanceId();
flowStepId = flowAttributes.getFlowStepId();
} else {
flowInstanceId = null;
flowStepId = null;
}
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepBeginLogData(flowInstanceId, flowStepId,
newFlowStepId, client.getConnectionInfo().getDirectory(), "(" + filePattern + ")"));
try {
// do the FTP GET operation
final Document doc = client.get(filePattern);
if (client.getConnectionInfo().getDeleteProcessedFile()) {
// TODO: Perhaps should we log 2 MONIT traces, one for each interaction with FTP server ?
client.del(filePattern);
}
this.logger
.log(Level.MONIT, "", new FtpProvideExtFlowStepEndLogData(flowInstanceId, newFlowStepId));
final Element rootElt = doc.createElementNS(exchange.getOperation().getNamespaceURI(),
"ver:getResponse");
rootElt.appendChild(doc.getDocumentElement());
doc.appendChild(rootElt);
exchange.setOutMessageContent(doc);
} catch (final IOException e) {
final String errorMsg = "Can not get file [" + filePattern + "] on FTP server ["
+ client.getConnectionInfo().getServer() + "]. Cause : " + e.getMessage();
this.logger.log(Level.MONIT, "", new ProvideExtFlowStepFailureLogData(flowInstanceId,
newFlowStepId, errorMsg));
FTPUtil.setIOFaultOnExchange(exchange, errorMsg);
}
}
} finally {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("GET operation ended");
}
}
}
/**
*
* FTP GET operation
* get the file as a source message a Fault is returned for bad request or IO problems
*
* @param exchange
* the message exchange, MUST be non null
* @param connectionInfo
* @param inMessage
* @throws MessagingException
* bad MEP
*/
public void processGetAsAttachment(final Exchange exchange, final Document inMessage, final WrappedFTPClient client)
throws MessagingException {
this.logger.fine("JBI exchange received - Process GET AS ATTACHMENT operation");
try {
// Checks the MEP of the incoming message
if (!exchange.isInOutPattern()) {
throw new MessagingException(FTPUtil.getOperationValidMep(FTPConstants.GET_ATTACHMENT_OPERATION,
Message.MEPConstants.IN_OUT_PATTERN));
}
// retrieve the filename to get
final Node filePatternNode = XMLHelper.findChild(inMessage.getFirstChild(), null,
FTPConstants.FTP_FILENAME, true);
final String filePattern;
if (filePatternNode != null) {
filePattern = filePatternNode.getTextContent();
} else {
filePattern = null;
}
if (StringHelper.isNullOrEmpty(filePattern)) {
FTPUtil.setMissingElementFaultOnExchange(exchange, FTPConstants.FTP_FILENAME);
} else {
final String newFlowStepId = this.simpleUUIDGenerator.getNewID();
final FlowAttributes flowAttributes = PetalsExecutionContext.getFlowAttributes();
final String flowInstanceId;
final String flowStepId;
if (flowAttributes != null) {
flowInstanceId = flowAttributes.getFlowInstanceId();
flowStepId = flowAttributes.getFlowStepId();
} else {
flowInstanceId = null;
flowStepId = null;
}
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepBeginLogData(flowInstanceId, flowStepId,
newFlowStepId, client.getConnectionInfo().getDirectory(), "(" + filePattern + ")"));
try {
// do the FTP GET operation
final DataHandler file = client.getFileAsAttachment(filePattern);
if (client.getConnectionInfo().getDeleteProcessedFile()) {
// TODO: Perhaps should we log 2 MONIT traces, one for each interaction with FTP server ?
client.del(file.getName());
}
this.logger
.log(Level.MONIT, "", new FtpProvideExtFlowStepEndLogData(flowInstanceId, newFlowStepId));
exchange.setOutMessageAttachment(file.getName(), file);
final Document outDoc = FTPUtil.generateMTOMResponse(file.getName(), exchange.getOperation());
exchange.setOutMessageContent(outDoc);
} catch (final IOException e) {
final String errorMsg = "Can not get file [" + filePattern + "] on FTP server ["
+ client.getConnectionInfo().getServer() + "]. Cause : " + e.getMessage();
this.logger.log(Level.MONIT, "", new ProvideExtFlowStepFailureLogData(flowInstanceId,
newFlowStepId, errorMsg));
FTPUtil.setIOFaultOnExchange(exchange, errorMsg);
}
}
} finally {
this.logger.fine("GET AS ATTACHMENT operation ended");
}
}
private final String filenamesAsPatterns(final Collection filenames) {
assert !filenames.isEmpty();
final StringBuffer sb = new StringBuffer("(");
for (final String filename : filenames) {
sb.append(filename);
sb.append("|");
}
sb.deleteCharAt(sb.length() - 1);
sb.append(")");
return sb.toString();
}
/**
* FTP MGET operation
* All files are getted as attachments
*
* @param exchange
* @param connectionInfo
* @param inMessage
* @throws Exception
*/
public void processMGet(final Exchange exchange, final Document inMessage, final WrappedFTPClient client)
throws MessagingException {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("JBI exchange received - Process MGET operation");
}
try {
if (!exchange.isInOutPattern()) {
throw new MessagingException(FTPUtil.getOperationValidMep(FTPConstants.MGET_OPERATION,
MEPConstants.IN_OUT_PATTERN));
}
// retrieve filenames to get
final NodeList list = inMessage.getFirstChild().getChildNodes();
final List filenames = new LinkedList();
for (int index = 0; index < list.getLength(); index++) {
if (FTPConstants.FTP_FILENAME.equalsIgnoreCase(list.item(index).getLocalName())) {
filenames.add(list.item(index).getTextContent());
}
}
if (filenames.size() == 0) {
FTPUtil.setMissingElementFaultOnExchange(exchange, FTPConstants.FTP_FILENAME);
} else {
final String newFlowStepId = this.simpleUUIDGenerator.getNewID();
final FlowAttributes flowAttributes = PetalsExecutionContext.getFlowAttributes();
final String flowInstanceId;
final String flowStepId;
if (flowAttributes != null) {
flowInstanceId = flowAttributes.getFlowInstanceId();
flowStepId = flowAttributes.getFlowStepId();
} else {
flowInstanceId = null;
flowStepId = null;
}
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepBeginLogData(flowInstanceId, flowStepId,
newFlowStepId, client.getConnectionInfo().getDirectory(), filenamesAsPatterns(filenames)));
try {
// do the FTP MGET operation
final Map files = client.mGet(filenames);
// add attachments on the OUT message
for (Entry entry : files.entrySet()) {
exchange.getOutMessage().addAttachment(entry.getKey(), entry.getValue());
}
final List retrievedFilenames = new LinkedList(files.keySet());
final Document outDoc = FTPUtil.generateMTOMListResponse(retrievedFilenames,
exchange.getOperation());
exchange.setOutMessageContent(outDoc);
if (client.getConnectionInfo().getDeleteProcessedFile()) {
client.mDel(retrievedFilenames);
}
this.logger
.log(Level.MONIT, "", new FtpProvideExtFlowStepEndLogData(flowInstanceId, newFlowStepId));
} catch (final IOException e) {
final String errorMsg = "Can not get files [" + filenames + "] on FTP server ["
+ client.getConnectionInfo().getServer() + "]. Cause : " + e.getMessage();
this.logger.log(Level.MONIT, "", new ProvideExtFlowStepFailureLogData(flowInstanceId,
newFlowStepId, errorMsg));
FTPUtil.setIOFaultOnExchange(exchange, errorMsg);
}
}
} finally {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("MGET operation ended");
}
}
}
/**
* Put attachments on the ftp server TODO an FTP connection is done for each file...
*
* @param exchange
* @param connectionInfo
* @throws MessagingException
*/
public void processMPut(final Exchange exchange, final Document inputDocument, final WrappedFTPClient client)
throws MessagingException {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("JBI exchange received - Process MPUT operation");
}
try {
// Checks the MEP of the incoming message
if (!exchange.isInOnlyPattern()) {
throw new MessagingException(FTPUtil.getOperationValidMep(FTPConstants.MPUT_OPERATION,
MEPConstants.IN_ONLY_PATTERN));
}
// Check if the message has attachements
if (exchange.getInMessageAttachments().isEmpty()) {
final StringBuilder errorSB = new StringBuilder();
errorSB.append("One or more attachments expected.");
throw new MessagingException(errorSB.toString());
}
final String newFlowStepId = this.simpleUUIDGenerator.getNewID();
final FlowAttributes flowAttributes = PetalsExecutionContext.getFlowAttributes();
final String flowInstanceId;
final String flowStepId;
if (flowAttributes != null) {
flowInstanceId = flowAttributes.getFlowInstanceId();
flowStepId = flowAttributes.getFlowStepId();
} else {
flowInstanceId = null;
flowStepId = null;
}
try {
// rebuild a hashmap containing files and their names
final MtomMapping mapping = MtomUtil.getMtomMapping(exchange, inputDocument.getDocumentElement());
final Map attachments = mapping.getContentIdToDataHandler();
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine(mapping.toString());
}
final String filenamesAsPatterns = filenamesAsPatterns(attachments.keySet());
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepBeginLogData(flowInstanceId, flowStepId,
newFlowStepId, client.getConnectionInfo().getDirectory(), filenamesAsPatterns));
client.mPut(attachments);
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepEndLogData(flowInstanceId, newFlowStepId));
} catch (final IOException e) {
final StringBuilder errorSB = new StringBuilder();
errorSB.append("Can not put files on FTP server [");
errorSB.append(client.getConnectionInfo().getServer());
errorSB.append("] : IOException : ");
errorSB.append(e.getMessage());
this.logger.log(Level.MONIT, "", new ProvideExtFlowStepFailureLogData(flowInstanceId, newFlowStepId,
errorSB.toString()));
throw new MessagingException(errorSB.toString());
}
} finally {
this.logger.fine("MPUT operation ended");
}
}
/**
* Put the source on the ftp server with the given filename a Fault is returned on IO problems TODO the content to
* send is a String, which is not optimal
*
* @param exchange
* @param fileName
* @param connectionInfo
* @param inMessage
* @throws MessagingException
* @throws MissingElementException
*/
public void processPut(final Exchange exchange, final Document inMessage, final WrappedFTPClient client)
throws MessagingException, MissingElementException {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("JBI exchange received - Process PUT operation");
}
try {
if (exchange == null) {
throw new MessagingException("exchange parameter is null");
}
// Checks the MEP of the incoming message
if (!exchange.isInOnlyPattern()) {
throw new MessagingException(FTPUtil.getOperationValidMep(FTPConstants.PUT_OPERATION,
MEPConstants.IN_ONLY_PATTERN));
}
// Check the root node
final Node root = inMessage.getFirstChild();
if (root == null || !FTPConstants.PUT_OPERATION.equalsIgnoreCase(root.getLocalName())) {
throw new MissingElementException(FTPConstants.PUT_OPERATION);
}
final Node fileNameNode = XMLHelper.findChild(root, null, FTPConstants.FTP_FILENAME, false);
if (fileNameNode == null || !FTPConstants.FTP_FILENAME.equalsIgnoreCase(fileNameNode.getLocalName())) {
throw new MissingElementException(FTPConstants.FTP_FILENAME);
}
final Node bodyNode = XMLHelper.findChild(root, null, FTPConstants.BODY, false);
if (bodyNode == null) {
throw new MissingElementException(FTPConstants.BODY);
}
final String newFlowStepId = this.simpleUUIDGenerator.getNewID();
final FlowAttributes flowAttributes = PetalsExecutionContext.getFlowAttributes();
final String flowInstanceId;
final String flowStepId;
if (flowAttributes != null) {
flowInstanceId = flowAttributes.getFlowInstanceId();
flowStepId = flowAttributes.getFlowStepId();
} else {
flowInstanceId = null;
flowStepId = null;
}
try {
final String body = XMLHelper.toString(bodyNode.getChildNodes());
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepBeginLogData(flowInstanceId, flowStepId,
newFlowStepId, client.getConnectionInfo().getDirectory(), fileNameNode.getTextContent()));
client.putString(fileNameNode.getTextContent(), body);
this.logger.log(Level.MONIT, "", new FtpProvideExtFlowStepEndLogData(flowInstanceId, newFlowStepId));
} catch (final IOException e) {
final StringBuilder errorSB = new StringBuilder();
errorSB.append("Can not put XML content on FTP server [");
errorSB.append(client.getConnectionInfo().getServer());
errorSB.append("] : IOException : ");
errorSB.append(e.getMessage());
this.logger.log(Level.MONIT, "", new ProvideExtFlowStepFailureLogData(flowInstanceId, newFlowStepId,
errorSB.toString()));
throw new MessagingException(errorSB.toString());
} catch (final DOMException e) {
final StringBuilder errorSB = new StringBuilder();
errorSB.append("Can not put XML content on FTP server [");
errorSB.append(client.getConnectionInfo().getServer());
errorSB.append("] : DOMException : ");
errorSB.append(e.getMessage());
this.logger.log(Level.MONIT, "", new ProvideExtFlowStepFailureLogData(flowInstanceId, newFlowStepId,
errorSB.toString()));
throw new MessagingException(errorSB.toString());
}
} finally {
if (this.logger.isLoggable(Level.FINE)) {
this.logger.fine("PUT operation ended");
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy