Package net.sf.xbus.technical.ftp

Source Code of net.sf.xbus.technical.ftp.FTPConnection

package net.sf.xbus.technical.ftp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.util.Hashtable;
import java.util.Vector;

import net.sf.xbus.base.core.Constants;
import net.sf.xbus.base.core.XException;
import net.sf.xbus.base.core.config.Configuration;
import net.sf.xbus.base.core.trace.Trace;

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

/**
* <code>FTPConnection</code> manages connections to FTP servers and provide
* methods for read and write access of files via FTP.
*/
public class FTPConnection
{
  static final private String CHAPTER_FTPCONNECTION = "FTPConnection";

  /*
   * Variables used to implement the Singleton pattern
   */
  private static Hashtable mFTPConnections = new Hashtable();

  private static final Object classLock = FTPConnection.class;

  /*
   * Other variables
   */
  private String mName = null;

  private FTPClient mFTPClient = null;

  private boolean mOpen = false;

  private String mHost = null;

  private int mPort = 0;

  /**
   * The constructor is private, instances of <code>FTPConnection</code> can
   * only be generated via the method <code>getInstance()</code>. Each
   * instance is put in a <code>Hashtable</code> with the concatenation of
   * the thread name and the connection name as the key.
   */
  private FTPConnection(String name)
  {
    mName = name;
    mFTPConnections.put(getFullName(name), this);
  }

  /**
   * Delivers an open instance of <code>FTPConnection</code>.
   * <p />
   *
   * If it is the first call with this name for the actual thread, a new
   * <code>FTPConnection</code> object will be created. Subsequent calls in
   * this thread will deliver the object, that has been created by the first
   * call.
   *
   * @param name
   *            name of the FTPConnection
   * @return an open FTPConnection
   * @throws XException
   *             if something goes wrong
   */
  public static FTPConnection getInstance(String name) throws XException
  {
    synchronized (classLock)
    {
      FTPConnection ftpConnection = (FTPConnection) mFTPConnections
          .get(getFullName(name));

      if (ftpConnection == null)
      {
        ftpConnection = new FTPConnection(name);
      }

      ftpConnection.open(false);
      return ftpConnection;
    }
  }

  /**
   * Opens a connection to a FTP server, does the login and sets the file
   * type.
   *
   * @param force
   *            Forces the connection to be opened
   * @throws XException
   *             if something goes wrong
   */
  private void open(boolean force) throws XException
  {
    if ((!mOpen) || force)
    {
      mFTPClient = new FTPClient();

      /*
       * Connect to the FTP Server
       */
      Configuration config = Configuration.getInstance();
      mHost = config.getValue(CHAPTER_FTPCONNECTION, mName, "Host");
      mPort = config.getValueAsIntOptional(CHAPTER_FTPCONNECTION, mName,
          "Port");

      try
      {
        if (mPort > 0)
        {
          mFTPClient.connect(mHost, mPort);
        }
        else
        {
          mFTPClient.connect(mHost);
        }

        int reply = getReplyCode();

        if (!FTPReply.isPositiveCompletion(reply))
        {
          close();
          Vector params = new Vector(2);
          params.add(mHost);
          params.add(getReplyString());
          throw new XException(Constants.LOCATION_EXTERN,
              Constants.LAYER_TECHNICAL,
              Constants.PACKAGE_TECHNICAL_FTP, "1", params);
        }

        mOpen = true;

        /*
         * Login to the FTP server
         */
        String user = config.getValue(CHAPTER_FTPCONNECTION, mName,
            "User");
        String password = config.getValueOptional(
            CHAPTER_FTPCONNECTION, mName, "Password");
        String account = config.getValueOptional(CHAPTER_FTPCONNECTION,
            mName, "Account");

        boolean successful = false;
        if (account == null)
        {
          successful = mFTPClient.login(user, password);
        }
        else
        {
          successful = mFTPClient.login(user, password, account);
        }

        if (!successful)
        {
          close();
          Vector params = new Vector(3);
          params.add(mHost);
          params.add(user);
          if (account == null)
          {
            throw new XException(Constants.LOCATION_EXTERN,
                Constants.LAYER_TECHNICAL,
                Constants.PACKAGE_TECHNICAL_FTP, "2", params);

          }
          else
          {
            params.add(user);
            throw new XException(Constants.LOCATION_EXTERN,
                Constants.LAYER_TECHNICAL,
                Constants.PACKAGE_TECHNICAL_FTP, "3", params);
          }

        }

        /*
         * Set the file type
         */
        int fileTypeInt = 0;
        String fileTypeString = config.getValueOptional(
            CHAPTER_FTPCONNECTION, mName, "FileType");
        if (fileTypeString == null)
        {
          fileTypeString = "ASCII";
        }
        if (fileTypeString.toUpperCase().equals("ASCII"))
        {
          fileTypeInt = FTP.ASCII_FILE_TYPE;
        }
        else if (fileTypeString.toUpperCase().equals("BINARY"))
        {
          fileTypeInt = FTP.BINARY_FILE_TYPE;
        }
        else
        {
          close();
          Vector params = new Vector(1);
          params.add(fileTypeString);
          throw new XException(Constants.LOCATION_EXTERN,
              Constants.LAYER_TECHNICAL,
              Constants.PACKAGE_TECHNICAL_FTP, "2", params);
        }
        mFTPClient.setFileType(fileTypeInt);
      }
      catch (XException e)
      {
        close();
        throw e;
      }
      catch (SocketException e)
      {
        close();
        throw new XException(Constants.LOCATION_EXTERN,
            Constants.LAYER_TECHNICAL,
            Constants.PACKAGE_TECHNICAL_FTP, "0", e);
      }
      catch (IOException e)
      {
        close();
        throw new XException(Constants.LOCATION_EXTERN,
            Constants.LAYER_TECHNICAL,
            Constants.PACKAGE_TECHNICAL_FTP, "0", e);
      }
    }
  }

  /**
   * Closes the connection to the FTP server
   */
  public void close()
  {
    if (mOpen)
    {
      try
      {
        if (mFTPClient != null)
        {
          mFTPClient.disconnect();
        }
      }
      catch (Exception e)
      {
        Trace.warn("Cannot disconnect from FTP server for connection "
            + mName);
      }
    }

    mOpen = false;
  }

  /**
   * Returns the reply code send by the FTP server after an operation
   */
  private int getReplyCode()
  {
    return mFTPClient.getReplyCode();
  }

  /**
   * Returns the reply string send by the FTP server after an operation
   */
  private String getReplyString()
  {
    return mFTPClient.getReplyString();
  }

  /**
   * Retrieves the content of a file from the FTP server.
   *
   * @param workDir
   *            working directory where the file is stored, may be null
   * @param fileName
   *            name of the file without any directory information
   * @param encoding
   *            encoding of the file
   * @return content of the file
   * @throws XException
   *             if something goes wrong, e.g. the file doesn't exist
   */
  public String retrieveFile(String workDir, String fileName, String encoding)
      throws XException
  {
    try
    {
      changeWorkDir(workDir);

      ByteArrayOutputStream outStream = new ByteArrayOutputStream();

      boolean successful = mFTPClient.retrieveFile(fileName, outStream);
      if (!successful)
      {
        outStream.close();
        Vector params = new Vector(2);
        params.add(fileName);
        params.add(getReplyString());
        throw new XException(Constants.LOCATION_EXTERN,
            Constants.LAYER_TECHNICAL,
            Constants.PACKAGE_TECHNICAL_FTP, "5", params);
      }
      String retString = outStream.toString(encoding);
      outStream.close();
      return retString;
    }
    catch (Throwable e)
    {
      throw new XException(Constants.LOCATION_EXTERN,
          Constants.LAYER_TECHNICAL, Constants.PACKAGE_TECHNICAL_FTP,
          "0", e);
    }

  }

  /**
   * Changes the working directory used for file operations.
   *
   * @param workDir
   *            name of the new working directory
   * @throws XException
   *             if something goes wrong
   */
  private void changeWorkDirInternal(String workDir) throws FTPException,
      IOException
  {
    if (!mFTPClient.changeWorkingDirectory(workDir))
    {
      throw new FTPException();
    }
  }

  /**
   * Changes the working directory used for file operations.
   *
   * @param workDir
   *            name of the new working directory
   * @throws XException
   *             if something goes wrong
   */
  private void changeWorkDir(String workDir) throws XException
  {
    try
    {
      if (workDir != null)
      {
        changeWorkDirInternal(workDir);
      }
    }
    catch (Exception e1)
    {
      try
      {
        /*
         * Reopen connection and try a second time
         */
        Trace
            .warn("FTP connection may be gone, will try a second time");
        open(true);
        changeWorkDirInternal(workDir);
      }
      catch (FTPException e)
      {
        Vector params = new Vector(1);
        params.add(workDir);
        throw new XException(Constants.LOCATION_EXTERN,
            Constants.LAYER_TECHNICAL,
            Constants.PACKAGE_TECHNICAL_FTP, "12", params);
      }
      catch (IOException e)
      {

        throw new XException(Constants.LOCATION_EXTERN,
            Constants.LAYER_TECHNICAL,
            Constants.PACKAGE_TECHNICAL_FTP, "0");
      }

    }
  }

  /**
   * Writes the given data to a file on the FTP server. Existing files will be
   * overwritten.
   *
   * @param data
   *            new content of the file on the server
   * @param workDir
   *            working directory where the file shall be stored, may be null
   * @param fileName
   *            name of the file without any directory information
   * @param encoding
   *            encoding of the file
   * @throws XException
   *             if something goes wrong, e.g. the working directory doesn't
   *             exist
   */
  public void storeFile(String data, String workDir, String fileName,
      String encoding) throws XException
  {
    try
    {
      changeWorkDir(workDir);

      ByteArrayInputStream inStream = new ByteArrayInputStream(data
          .getBytes(encoding));
      boolean successful = mFTPClient.storeFile(fileName, inStream);
      inStream.close();
      if (!successful)
      {
        Vector params = new Vector(2);
        params.add(fileName);
        params.add(getReplyString());
        throw new XException(Constants.LOCATION_EXTERN,
            Constants.LAYER_TECHNICAL,
            Constants.PACKAGE_TECHNICAL_FTP, "9", params);
      }
    }
    catch (UnsupportedEncodingException e)
    {
      throw new XException(Constants.LOCATION_EXTERN,
          Constants.LAYER_TECHNICAL, Constants.PACKAGE_TECHNICAL_FTP,
          "0", e);
    }
    catch (IOException e)
    {
      throw new XException(Constants.LOCATION_EXTERN,
          Constants.LAYER_TECHNICAL, Constants.PACKAGE_TECHNICAL_FTP,
          "0", e);
    }
  }

  /**
   * Renames a file on the FTP server.
   *
   * @param workDir
   *            working directory, may be null
   * @param fromFile
   *            old name of the file, without any directory information
   * @param toFile
   *            new name of the file, without any directory information
   * @throws XException
   *             if something goes wrong, e.g. the <code>fromFile</code>
   *             doesn't exist
   */
  public void rename(String workDir, String fromFile, String toFile)
      throws XException
  {
    try
    {
      changeWorkDir(workDir);

      boolean successful = mFTPClient.rename(fromFile, toFile);
      if (!successful)
      {
        Vector params = new Vector(3);
        params.add(fromFile);
        params.add(toFile);
        params.add(getReplyString());
        throw new XException(Constants.LOCATION_EXTERN,
            Constants.LAYER_TECHNICAL,
            Constants.PACKAGE_TECHNICAL_FTP, "7", params);
      }
    }
    catch (IOException e)
    {
      throw new XException(Constants.LOCATION_EXTERN,
          Constants.LAYER_TECHNICAL, Constants.PACKAGE_TECHNICAL_FTP,
          "0", e);
    }
  }

  /**
   * Deletes a file on the FTP server.
   *
   * @param workDir
   *            working directory, may be null
   * @param fileName
   *            name of the file that shall be deleted, without any directory
   *            information
   * @throws XException
   *             if something goes wrong, e.g. the file doesn't exist
   */
  public void delete(String workDir, String fileName) throws XException
  {
    if (mOpen)
    {
      try
      {
        changeWorkDir(workDir);

        boolean successful = mFTPClient.deleteFile(fileName);
        if (!successful)
        {
          Vector params = new Vector(2);
          params.add(fileName);
          params.add(getReplyString());
          throw new XException(Constants.LOCATION_EXTERN,
              Constants.LAYER_TECHNICAL,
              Constants.PACKAGE_TECHNICAL_FTP, "8", params);
        }
      }
      catch (IOException e)
      {
        throw new XException(Constants.LOCATION_EXTERN,
            Constants.LAYER_TECHNICAL,
            Constants.PACKAGE_TECHNICAL_FTP, "0", e);
      }
    }
  }

  /**
   * Checks if a file exists on the FTP server.
   *
   * @param workDir
   *            working directory, may be null
   * @param fileName
   *            name of the file, without any directory information
   * @return <code>true</code> if the file exists, <code>false</code> if
   *         not
   * @throws XException
   *             if something goes wrong
   */
  public boolean existsFile(String workDir, String fileName)
      throws XException
  {
    try
    {
      changeWorkDir(workDir);

      String[] files = mFTPClient.listNames(fileName);
      if ((files != null) && (files.length == 1)
          && (fileName.equals(files[0])))
      {
        return true;
      }
      else
      {
        return false;
      }
    }
    catch (IOException e)
    {
      throw new XException(Constants.LOCATION_EXTERN,
          Constants.LAYER_TECHNICAL, Constants.PACKAGE_TECHNICAL_FTP,
          "0", e);
    }
  }

  /**
   * Returns a string containing host, port, working directory and name of the
   * file, mainly used for tracing.
   *
   * @param workDir
   *            working directory, may be null
   * @param fileName
   *            name of the file, without any directory information
   * @return string as described above
   */
  public String getFTPName(String workDir, String fileName)
  {
    StringBuffer buffer = new StringBuffer("ftp://").append(mHost);
    if (mPort > 0)
    {
      buffer.append(":").append(mPort);
    }
    if (workDir != null)
    {
      buffer.append(workDir);
    }
    buffer.append("/");
    buffer.append(fileName);

    return buffer.toString();
  }

  /**
   * Extracts the name of the directory from a complete file name.
   *
   * @param name
   *            complete name of a file, containing directory and file name
   * @return name of the directory with leading slash, <code>null</code> if
   *         the name doesn't contain any directory information
   */
  static public String getWorkingDirectory(String name)
  {
    String workDir = null;
    int index = 0;

    if ((index = name.lastIndexOf("/")) >= 0)
    {
      workDir = name.substring(0, index);
    }

    if ((workDir != null) && (!workDir.startsWith("/")))
    {
      StringBuffer newWorkDir = new StringBuffer(workDir.length() + 1);
      newWorkDir.append("/").append(workDir);
      workDir = newWorkDir.toString();
    }

    return workDir;
  }

  /**
   * Extracts the name of the file itself from a complete file name.
   *
   * @param name
   *            complete name of a file, containing directory and file name
   * @return name of the file itself
   * @throws XException
   *             if the name of the file can't be extracted, e.g. the given
   *             name ends with a slash
   */
  static public String getFileName(String name) throws XException
  {
    String fileName = null;
    int index = 0;
    int lastPos = name.length() - 1;

    if ((index = name.lastIndexOf("/")) < 0)
    {
      /*
       * no slash => no directory
       */
      fileName = name;
    }
    else
    {
      if (index < lastPos)
      {
        /*
         * There is at least one character after the slash
         */
        fileName = name.substring(index + 1);
      }
    }

    if (fileName == null)
    {
      Vector params = new Vector(1);
      params.add(name);
      throw new XException(Constants.LOCATION_EXTERN,
          Constants.LAYER_TECHNICAL, Constants.PACKAGE_TECHNICAL_FTP,
          "11", params);
    }

    return fileName;
  }

  static private String getFullName(String name)
  {
    return new StringBuffer().append(name).append(".").append(
        Thread.currentThread().getName()).toString();
  }
}
TOP

Related Classes of net.sf.xbus.technical.ftp.FTPConnection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.