Package org.jboss.internal.soa.esb.util

Source Code of org.jboss.internal.soa.esb.util.SecureFtpImpl

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

/**
*
*/
package org.jboss.internal.soa.esb.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.addressing.eprs.FileEpr;
import org.jboss.soa.esb.addressing.eprs.SFTPEpr;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.util.ClassUtil;
import org.jboss.soa.esb.util.FileUtil;
import org.jboss.soa.esb.util.RemoteFileSystem;
import org.jboss.soa.esb.util.RemoteFileSystemException;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;
import com.jcraft.jsch.ChannelSftp.LsEntry;

/**
*
* Implementation of sftp (Secure FTP over SSH) Based on JSch from JCraft
* http://www.jcraft.com/
*
* @author b_georges
*/

public class SecureFtpImpl implements RemoteFileSystem
{

        private static final Logger _logger = Logger.getLogger(SecureFtpImpl.class);

        private static final String TMP_SUFFIX = ".rosettaPart";

        private static final String SECURE_CHANNEL = "sftp";

        // The objects implementing secure FTP over ssh
        private JSch m_oJSch = new JSch();

        private Session session = null;

        private ChannelSftp m_oSftpChannel = null;

        private int m_iPort;

        private SFTPEpr m_oEpr;

        private ConfigTree m_oParms;

        private String m_sFtpServer, m_sUser, m_sPasswd;

        private String m_sRemoteDir, m_sLocalDir;

        private URI m_oCertificate;
        private String m_sPassphrase;

        /*
         * Constructor
         *
         * @param p_oP Is an EPR used to initialize the object
         *
         * @param connect If true create a new sftp session
         *
         */
        public SecureFtpImpl(SFTPEpr p_oP, boolean p_bConnect) throws ConfigurationException, RemoteFileSystemException
        {
                m_oEpr = p_oP;

                final URI uri ;
                try {
                        uri = m_oEpr.getURI();
                } catch (URISyntaxException e) {
                        throw new RemoteFileSystemException(e);
                }

                m_sFtpServer = uri.getHost();

                String[] sa = null;

                if (uri.getUserInfo() != null)
                        sa = uri.getUserInfo().split(":");

                final int saLen = (sa == null ? 0 : sa.length) ;
                switch(saLen)
                {
                case 2:
                    m_sPasswd = sa[1] ;
                case 1:
                    m_sUser = sa[0] ;
                }

                m_sRemoteDir = uri.getPath();

                if ((m_sRemoteDir == null) || (m_sRemoteDir.equals("")))
                        m_sRemoteDir = FtpUtils.getRemoteDir();

                m_iPort = uri.getPort();

                m_sLocalDir = FtpUtils.getLocalDir();

                try
                {
                        m_oCertificate = p_oP.getCertificateURI() ;
                }
                catch (final URISyntaxException urise)
                {
                    throw new RemoteFileSystemException(urise);
                }
                m_sPassphrase = p_oP.getPassphrase() ;

                configTreeFromEpr();

                initialize(p_bConnect);
        }

        private void initialize(boolean bConnect) throws ConfigurationException, RemoteFileSystemException
        {
                checkParms();
               
                if (bConnect)
                {
                        _logger.debug("Connecting to SFTP server") ;
                        try
                        {
                                if (m_iPort > 0)
                                    session = m_oJSch.getSession(m_sUser, m_sFtpServer, m_iPort);
                                else
                                    session = m_oJSch.getSession(m_sUser, m_sFtpServer);
       
                                if (m_sPasswd != null)
                                {
                                    final UserInfo ui = new SecureFtpUserInfo(null, m_sPasswd) ;
                                    session.setUserInfo(ui) ;
                                    session.setConfig("PreferredAuthentications", "password,keyboard-interactive") ;
                                }
                                else if (m_oCertificate != null)
                                {
                                    final String certificate = m_oCertificate.toString() ;
                                    final InputStream is ;
                                    final String certificateName ;
                                    final InputStream resourceIS = ClassUtil.getResourceAsStream(certificate, getClass()) ;
                                    if (resourceIS != null)
                                    {
                                        is = resourceIS ;
                                        certificateName = getSimpleName(certificate) ;
                                    }
                                    else
                                    {
                                        certificateName = getSimpleName(m_oCertificate.getPath()) ;
                                        try
                                        {
                                            if (m_oCertificate.isAbsolute())
                                            {
                                                is = m_oCertificate.toURL().openStream() ;
                                            }
                                            else
                                            {
                                                final File file = new File(m_oCertificate.getPath()) ;
                                                is = file.toURL().openStream() ;
                                            }
                                        }
                                        catch (final IOException ioe)
                                        {
                                            throw new ConfigurationException("Unexpected IOException accessing: " + certificate, ioe) ;
                                        }
                                    }
                                    final byte[] privateKey = StreamUtils.readStream(is) ;
                                    m_oJSch.addIdentity(certificateName, privateKey, null, null) ;
                                   
                                    final UserInfo ui = new SecureFtpUserInfo(m_sPassphrase, null);
                                    session.setUserInfo(ui);
                                    session.setConfig("PreferredAuthentications", "publickey") ;
                                }
                               
                                session.setConfig("StrictHostKeyChecking", "no") ;

                                session.connect();
       
                                final Channel channel  = session.openChannel(SECURE_CHANNEL);
                                channel.connect();
       
                                m_oSftpChannel = (ChannelSftp) channel;
       
                                if (!session.isConnected())
                                        throw new RemoteFileSystemException("Can't connect to FTP server");
                        }
                        catch (JSchException ex)
                        {
                                if ((session != null) && session.isConnected())
                                {
                                    session.disconnect() ;
                                }
                                _logger.error("Caught Secure FTP Exception.");
                                _logger.debug("Caught Secure FTP Exception.", ex);
                               
                                throw new RemoteFileSystemException(ex);
                        }
                }
        }

        private static String getSimpleName(final String name)
            throws ConfigurationException
        {
            if (name == null)
            {
                throw new ConfigurationException("Null certificate name") ;
            }
            final int lastIndex = name.lastIndexOf('/') ;
            if (lastIndex >= 0)
            {
                final int startIndex = lastIndex+1 ;
                if (startIndex == name.length())
                {
                    throw new ConfigurationException("Invalid certificate name: " + name) ;
                }
                return name.substring(startIndex) ;
            }
            return name ;
        }

        private void checkParms() throws ConfigurationException
        {
            String att = m_oParms.getAttribute(FileEpr.URL_TAG);
            URI uri = null;
           
            try
            {
                    if (att != null)
                            uri = new URI(att);
            }
            catch (URISyntaxException ex)
            {
                    throw new ConfigurationException(ex);
            }
           
                m_sFtpServer = (null != uri) ? uri.getHost() : m_oParms.getAttribute(PARMS_FTP_SERVER);
                if (null == m_sFtpServer)
                        throw new ConfigurationException("No SFTP server specified");

                String[] sa = (null == uri) ? null : uri.getUserInfo().split(":");
                m_sUser = (null != sa) ? sa[0] : m_oParms.getAttribute(PARMS_USER);
                if (null == m_sUser)
                        throw new ConfigurationException("No username specified for SFTP");

                m_sPasswd = ((null != sa) && (sa.length > 1)) ? sa[1] : m_oParms.getAttribute(PARMS_PASSWD);

                m_sRemoteDir = (null != uri) ? uri.getPath() : m_oParms.getAttribute(PARMS_REMOTE_DIR);
                if (null == m_sRemoteDir)
                        m_sRemoteDir = "";

                m_sLocalDir = m_oParms.getAttribute(PARMS_LOCAL_DIR);
                if (null == m_sLocalDir)
                        m_sLocalDir = ".";

                String sAux = m_oParms.getAttribute(PARMS_PORT);
               
                try
                {
                        m_iPort = (null != uri) ? uri.getPort() : (null == sAux) ? 22 : Integer.parseInt(sAux);
                        final String certificate = m_oParms.getAttribute(PARMS_CERTIFICATE) ;
                        if (certificate != null)
                        {
                                m_oCertificate = new URI(certificate) ;
                        }
                }
                catch (Exception ex)
                {
                        throw new ConfigurationException(ex);
                }
               
                m_sPassphrase = m_oParms.getAttribute(PARMS_PASSPHRASE) ;
        }

        /*
         * Deletes a file on the SFTP-Server
         *
         * @param fileName The file's Name to be removed from the SFTP-Server
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#deleteRemoteFile(java.lang.String)
         */
        public void deleteRemoteFile(String p_sFile) throws RemoteFileSystemException
        {
                if (_logger.isDebugEnabled())
                {
                        _logger.debug("deleteRemoteFile(" + p_sFile + "), remote dir " + getRemoteDir()) ;
                }
               
                try
                {
                        m_oSftpChannel.cd(getRemoteDir()) ;
                        m_oSftpChannel.rm(p_sFile);
                }
                catch (SftpException ex)
                {
                        throw new RemoteFileSystemException(ex);
                }
        }

        /*
         * Deletes a file on the SFTP-Server
         *
         * @param fileName The file to be removed from the SFTP-Server
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#remoteDelete(java.io.File)
         */
        public void remoteDelete(File p_oFile) throws RemoteFileSystemException
        {
                final String remoteFile = FtpUtils.fileToFtpString(p_oFile) ;
                if (_logger.isDebugEnabled())
                {
                        _logger.debug("remoteDelete(" + remoteFile + ")") ;
                }
                try
                {
                        m_oSftpChannel.rm(remoteFile);
                }
                catch (SftpException ex)
                {
                        throw new RemoteFileSystemException(ex);
                }
        }

        /*
         * Returns a list of Filenames for the directory specified in p_Suffix
         *
         * @param p_sSuffix The remote directory path from the SFTP-Server
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#getFileListFromRemoteDir(java.lang.String)
         */
        public String[] getFileListFromRemoteDir(String p_sSuffix) throws RemoteFileSystemException
        {
                if (_logger.isDebugEnabled())
                {
                        _logger.debug("getFileListFromRemoteDir(" + p_sSuffix + "), remote dir " + getRemoteDir()) ;
                }
                try
                {
                        m_oSftpChannel.cd(getRemoteDir()) ;
                }
                catch (SftpException ex)
                {
                        throw new RemoteFileSystemException(ex);
                }
                String sSuffix = (null == p_sSuffix) ? "*" : "*" + p_sSuffix;
                final Vector vFileList ;
                try
                {
                        vFileList = m_oSftpChannel.ls(sSuffix);
                }
                catch (SftpException ex)
                {
                        if (ex.id == ChannelSftp.SSH_FX_NO_SUCH_FILE)
                        {
                            return null ;
                        }
                        throw new RemoteFileSystemException(ex);
                }
               
                List<String> lFileList = new ArrayList<String>();
                if (vFileList != null)
                {
                        for (int i = 0; i < vFileList.size(); i++)
                        {
                                Object obj = vFileList.elementAt(i);
                               
                                if (obj instanceof LsEntry)
                                {
                                        SftpATTRS oSftAttr = ((LsEntry) obj).getAttrs();
                                        if (!oSftAttr.isDir())
                                        {
                                                lFileList.add(((LsEntry) obj).getFilename());
                                        }
                                }
                        }
                }
               
                return (String[]) lFileList.toArray(new String[lFileList.size()]);
        }

        /*
         * Set the new directory to p_SDir
         *
         * @param p_sDir The remote directory path name we want to "cd" to.
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#setRemoteDir(java.lang.String)
         */
        public void setRemoteDir(String p_sDir) throws RemoteFileSystemException
        {
                m_sRemoteDir = p_sDir ;
        }

        /*
         * Rename the Remote Directory name p_sFrom with p_sTo
         *
         * @param p_sFrom The remote directory name we want to rename
         *
         * @param p_sTo The new remote directory name
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#renameInRemoteDir(java.lang.String,
         *      java.lang.String)
         */
        public void renameInRemoteDir(String p_sFrom, String p_sTo)
            throws RemoteFileSystemException
        {
                if (_logger.isDebugEnabled())
                {
                        _logger.debug("renameInRemoteDir(" + p_sFrom + ", " + p_sTo + "), remote dir " + getRemoteDir()) ;
                }
                try
                {
                        m_oSftpChannel.cd(getRemoteDir()) ;
                        m_oSftpChannel.rename(p_sFrom, p_sTo) ;
                }
                catch (SftpException se)
                {
                        throw new RemoteFileSystemException("Faile to rename file", se) ;
                }
        }

        /*
         * Rename the Remote File name p_sFrom with p_sTo
         *
         * @param p_oFrom The remote file name we want to rename
         *
         * @param p_oTo The new remote file name
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#remoteRename(java.io.File,
         *      java.io.File)
         */
        public void remoteRename(File p_oFrom, File p_oTo) throws RemoteFileSystemException
        {
                final String from = FtpUtils.fileToFtpString(p_oFrom) ;
                final String to = FtpUtils.fileToFtpString(p_oTo) ;
                if (_logger.isDebugEnabled())
                {
                        _logger.debug("remoteRename(" + from + ", " + to + "), remote dir " + getRemoteDir()) ;
                }
                try
                {
                        m_oSftpChannel.cd(getRemoteDir()) ;
                        m_oSftpChannel.rename(from, to);
                }
                catch (SftpException se)
                {
                        throw new RemoteFileSystemException("Faile to rename file", se) ;
                }
        }

        /*
         * Upload the local File p_ofile to p_sRemoteName
         *
         * @param p_oFile The local file name we want to upload
         *
         * @param p_sRemoteName The remote file name [can be the same as p_oFile of
         * course]
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#uploadFile(java.io.File,
         *      java.lang.String)
         */
        public void uploadFile(File p_oFile, String p_sRemoteName) throws RemoteFileSystemException
        {
            if (_logger.isDebugEnabled())
            {
                    _logger.debug("uploadFile(" + p_oFile + ", " + p_sRemoteName + "), remote dir " + getRemoteDir()) ;
            }
            try
            {
                    m_oSftpChannel.cd(getRemoteDir()) ;
                   
                    final String sRemoteTmp = p_sRemoteName + TMP_SUFFIX;
                   
                    final OutputStream os = m_oSftpChannel.put(sRemoteTmp) ;
                    try
                    {
                        final FileInputStream fis = new FileInputStream(p_oFile) ;
                        try
                        {
                            copyStream(fis, os) ;
                        }
                        finally
                        {
                            fis.close() ;
                        }
                    }
                    finally
                    {
                        os.flush() ;
                        os.close() ;
                    }
                    m_oSftpChannel.rename(sRemoteTmp, p_sRemoteName);
            }
            catch (final IOException ioe)
            {
                throw new RemoteFileSystemException(ioe) ;
            }
            catch (SftpException ex)
            {
                    throw new RemoteFileSystemException(ex);
            }
    }

        /*
         * Download the remote File p_sFile to p_sFile.
         *
         * @param p_sFile The remote file name we want to download
         *
         * @param p_sFinalName The local file name
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#downloadFile(java.lang.String,
         *      java.lang.String)
         */
        public void downloadFile(String p_sFile, String p_sFinalName) throws IOException, RemoteFileSystemException
        {
            if (_logger.isDebugEnabled())
            {
                    _logger.debug("downloadFile(" + p_sFile + ", " + p_sFinalName + "), remote dir " + getRemoteDir()) ;
            }
            try
            {
                final File to = new File(p_sFinalName) ;
                final File oLocalDir = new File(m_sLocalDir);
                final File oNew = (to.isAbsolute() ? to : new File(oLocalDir, p_sFinalName)) ;
                if (oNew.exists())
                    oNew.delete();
               
                final File toTmp = new File(p_sFinalName + TMP_SUFFIX) ;
                final File oNewTmp = (toTmp.isAbsolute() ? toTmp : new File(oLocalDir, p_sFinalName + TMP_SUFFIX)) ;
                if (oNewTmp.exists())
                    oNewTmp.delete();
               
                m_oSftpChannel.cd(getRemoteDir()) ;
                final InputStream is = m_oSftpChannel.get(p_sFile) ;
               
                try
                {
                    final FileOutputStream fos = new FileOutputStream(oNewTmp) ;
                    try
                    {
                        copyStream(is, fos) ;
                    }
                    finally
                    {
                        fos.close() ;
                    }
                }
                finally
                {
                    is.close() ;
                }
                FileUtil.renameTo(oNewTmp, oNew) ;
            }
            catch (SftpException ex)
            {
                    throw new RemoteFileSystemException(ex);
            }
        }

        /*
         * Returns the current remote directory
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#getRemoteDir()
         */
        public String getRemoteDir()
        {
                return m_sRemoteDir;
        }

        /*
         * Terminates the sftp session.
         *
         * @see org.jboss.soa.esb.util.RemoteFileSystem#quit()
         */
        public void quit()
        {
                _logger.debug("quitting") ;
                m_oSftpChannel.disconnect() ;
                session.disconnect() ;
        }

        private void configTreeFromEpr() throws ConfigurationException
        {
                m_oParms = new ConfigTree("fromEpr");
                try
                {
                        m_oParms.setAttribute(RemoteFileSystem.PARMS_FTP_SERVER,
                                        m_sFtpServer);
                        m_oParms.setAttribute(RemoteFileSystem.PARMS_USER, m_sUser);
                        if (m_sPasswd != null)
                            m_oParms.setAttribute(RemoteFileSystem.PARMS_PASSWD, m_sPasswd);
                        m_oParms.setAttribute(RemoteFileSystem.PARMS_REMOTE_DIR,
                                        m_sRemoteDir);
                        if (m_iPort > 0)
                            m_oParms.setAttribute(RemoteFileSystem.PARMS_PORT, Integer
                                        .toString(m_iPort));
                        m_oParms.setAttribute(RemoteFileSystem.PARMS_LOCAL_DIR, m_sLocalDir);
                        m_oParms.setAttribute(RemoteFileSystem.PARMS_ASCII, Boolean
                                        .toString(false));
                        if (m_oCertificate != null)
                            m_oParms.setAttribute(RemoteFileSystem.PARMS_CERTIFICATE, m_oCertificate.toString()) ;
                        if (m_sPassphrase != null)
                            m_oParms.setAttribute(RemoteFileSystem.PARMS_PASSPHRASE, m_sPassphrase) ;
                }
                catch (Exception e)
                {
                        throw new ConfigurationException(e);
                }
        }

       
        private void copyStream(final InputStream is, final OutputStream os)
            throws IOException
        {
            final BufferedInputStream bis = new BufferedInputStream(is) ;
            final BufferedOutputStream bos = new BufferedOutputStream(os) ;
           
            final byte[] buffer = new byte[256] ;
            while(true)
            {
                final int count = bis.read(buffer) ;
                if (count <= 0)
                {
                    break ;
                }
                bos.write(buffer, 0, count) ;
            }
            bos.flush() ;
        }
}
TOP

Related Classes of org.jboss.internal.soa.esb.util.SecureFtpImpl

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.