Blaise Bruno - 2004-02-05

Dear all,

I had a problem with an ftp transfer. When you transfer a file on a unix machine with ftp protocol, the file appears immediately on the destination. It can be a problem on the destination, if you have a system that take this file before the end of this transfer. One solution is to use a status file sended after the file itself. The destination is listening on this status file and when the status file appears the file itself is ready to use.

I have introduce a new option into the FtpWriter stage called 'ftpFlagFileName' and when this option is present into the definition, the process method will store a supplementary file with this name into the same location.

Please find the modified code:

/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    nor may "Apache" appear in their name, without prior written
*    permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* Portions of this software are based upon public domain software
* originally written at the National Center for Supercomputing Applications,
* University of Illinois, Urbana-Champaign.
* ====================================================================
*
* Babeldoc:  The Universal Document Processor
*
* $Header: /cvsroot/babeldoc/babeldoc/modules/core/src/com/babeldoc/core/pipeline/stage/FtpWriterPipelineStage.java,v 1.6 2003/06/27 02:19:59 triphop Exp $
* $DateTime$
* $Author: triphop $
*
*/
package com.babeldoc.core.pipeline.stage;

import com.babeldoc.core.I18n;
import com.babeldoc.core.option.ConfigOption;
import com.babeldoc.core.option.IConfigOptionType;
import com.babeldoc.core.pipeline.PipelineDocument;
import com.babeldoc.core.pipeline.PipelineException;
import com.babeldoc.core.pipeline.PipelineStageInfo;
import com.babeldoc.core.pipeline.PipelineStageResult;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

import java.io.ByteArrayInputStream;

import java.util.ArrayList;
import java.util.Collection;

/**
* FtpWriterPipelineStage.  This pipeline stage writes the document to the ftp
* host.
*
* @author bmcdonald
* @version 1.0
*/
public class FtpWriterPipelineStage extends GenericWriterPipelineStage {
  /** Constants */
  public static final String FTP_HOST = "ftpHost";
  public static final String FTP_USERNAME = "ftpUsername";
  public static final String FTP_PASSWORD = "ftpPassword";
  public static final String FTP_FOLDER = "ftpFolder";
  public static final String FTP_FILENAME = "ftpFilename";
  public static final String FTP_FLAG = "ftpFlagFileName";

  /**
   * Return this stages info
   */
  public FtpWriterPipelineStage() {
    super(new PipelineStageInfo() {
        public String getName() {
          return "FtpWriter";
        }

        public String getDescription() {
          return I18n.get("core.pipeline.stage.ftpwriter.desc");
        }

        public Collection getTypeSpecificOptions() {
          ArrayList options = new ArrayList();

          //add specific options
          options.add(new ConfigOption(FTP_HOST, IConfigOptionType.STRING,
              null, false, I18n.get("100025")));
          options.add(new ConfigOption(FTP_USERNAME, IConfigOptionType.STRING,
              null, false, I18n.get("100026")));
          options.add(new ConfigOption(FTP_PASSWORD, IConfigOptionType.STRING,
              null, false, I18n.get("100027")));
          options.add(new ConfigOption(FTP_FOLDER, IConfigOptionType.STRING,
              null, false, I18n.get("100028")));
          options.add(new ConfigOption(FTP_FILENAME, IConfigOptionType.STRING,
              null, false, I18n.get("100029")));
          options.add(new ConfigOption(FTP_FLAG, IConfigOptionType.STRING,
              null, false, I18n.get("100030")));

          return options;
        }
      });
  }

  /**
   * Send the document to the ftp site
   *
   * @param ftpHost
   * @param ftpUsername
   * @param ftpPassword
   * @param ftpFolder
   * @param ftpFilename
   * @param document
   *
   * @throws Exception DOCUMENT ME!
   */
  public static void sendFtpMessage(String ftpHost, String ftpUsername,
    String ftpPassword, String ftpFolder, String ftpFilename, String ftpFlag,
    PipelineDocument document) throws Exception {
    FTPClient ftp = new FTPClient();
    ftp.connect(ftpHost);

    if (ftp.login(ftpUsername, ftpPassword)) {
      if (ftp.changeWorkingDirectory(ftpFolder)) {
        if (document.isBinary()) {
          ftp.setFileType(FTP.BINARY_FILE_TYPE);
        }

        ByteArrayInputStream bais = new ByteArrayInputStream(document.getBytes());

        if (!ftp.storeFile(ftpFilename, bais)) {
          throw new Exception(I18n.get("100030"));
        }
       
        if ((ftpFlag != null) && (ftpFlag.length()>0)){
          StringBuffer fn = new StringBuffer("Flag for ");
          fn.append(ftpFilename);
          bais = new ByteArrayInputStream(fn.toString().getBytes());
          if (!ftp.storeFile(ftpFlag, bais)) {
            throw new Exception(I18n.get("100030"));
          }
        }
      } else {
        throw new Exception(I18n.get("100031"));
      }
    } else {
      throw new Exception(I18n.get("100032"));
    }
  }

  /**
   * pipeline stage.  Write the document to the ftp host.
   *
   * @return the name of the next stage in the pipe line or nothing
   *
   * @throws PipelineException DOCUMENT ME!
   */
  public PipelineStageResult[] process() throws PipelineException {
    try {
      String ftpHost = getOptions(FTP_HOST);
      String ftpUsername = getOptions(FTP_USERNAME);
      String ftpPassword = getOptions(FTP_PASSWORD);
      String ftpFolder = getOptions(FTP_FOLDER);
      String ftpFilename = getOptions(FTP_FILENAME);
      String ftpFlag = getOptions(FTP_FLAG);

      sendFtpMessage(ftpHost, ftpUsername, ftpPassword, ftpFolder, ftpFilename, ftpFlag,
        this.getContentDocument());

      return super.processHelper();
    } catch (Exception except) {
      throw new PipelineException("[FlatToXmlPipelineStage.process] Exception",
        except);
    }
  }
}