Subversion Repositories bacoAlunos

Rev

Rev 1945 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package pt.estgp.estgweb.web;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;
import pt.estgp.estgweb.domain.UserSession;
import pt.estgp.estgweb.domain.UserSessionImpl;
import pt.estgp.estgweb.utils.*;
import pt.estgp.estgweb.utils.Globals;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.URL;
import java.util.HashMap;

/**
 * @author Jorge
 * @date 18/Jan/2009
 * @time 18:35:11
 */

public class FtpServer
{
    private static final 1.5.0/docs/api/java/util/logging/Logger.html">Logger logger = 1.5.0/docs/api/java/util/logging/Logger.html">Logger.getLogger(FtpServer.class);


    private static HashMap<String, FtpServer> servers = new HashMap<String, FtpServer>();


    1.5.0/docs/api/java/lang/String.html">String host = null;
    int port = 21;
    1.5.0/docs/api/java/lang/String.html">String username = null;
    1.5.0/docs/api/java/lang/String.html">String password = null;
    1.5.0/docs/api/java/lang/String.html">String errorMsg = "";


    public FtpServer(1.5.0/docs/api/java/lang/String.html">String host, int port)
    {
        this.host = host;
        if (port > 0)
            this.port = port;
    }

    public FtpServer(1.5.0/docs/api/java/lang/String.html">String host, int port, 1.5.0/docs/api/java/lang/String.html">String username, 1.5.0/docs/api/java/lang/String.html">String password)
    {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    public static FtpServer getFtpServerForCurrentUser(1.5.0/docs/api/java/lang/String.html">String urlStr, HttpServletRequest request) throws 1.5.0/docs/api/java/net/MalformedURLException.html">MalformedURLException
    {
        1.5.0/docs/api/java/net/URL.html">URL url = new 1.5.0/docs/api/java/net/URL.html">URL(urlStr);
        int port = url.getPort();
        if (port <= 0)
            port = 21;
        1.5.0/docs/api/java/lang/String.html">String host = url.getHost();
        UserSession userSession = UserSessionProxy.loadUserSessionFromRequest(request);
        1.5.0/docs/api/java/lang/String.html">String username = userSession.getUsername();
        1.5.0/docs/api/java/lang/String.html">String password = ((UserSessionImpl)userSession).getUserPasswordInSession();
        return new FtpServer(host,port,username,password);
    }

    private static final int FTP_TIMEOUT_SECONDS = pt.estgp.estgweb.utils.Globals.FTP_TIMEOUT_SECONDS;

    public static class Connector implements 1.5.0/docs/api/java/lang/Runnable.html">Runnable
    {
        FTPClient ftp;
        1.5.0/docs/api/java/lang/String.html">String host;
        int port;

        public Connector(FTPClient ftp, 1.5.0/docs/api/java/lang/String.html">String host, int port) {
            this.ftp = ftp;
            this.host = host;
            this.port = port;
        }

        @1.5.0/docs/api/java/lang/Override.html">Override
        public void run() {
            try {
                ftp.connect(host, port);
            } catch (1.5.0/docs/api/java/io/IOException.html">IOException e) {
                logger.error(e,e);
            }
        }
    }
    public FtpClientWrapper getClientWrapperAutoReconnect() throws 1.5.0/docs/api/java/io/IOException.html">IOException
    {
        return new FtpClientWrapper(this,3);
    }
    public FTPClient getClient() throws 1.5.0/docs/api/java/io/IOException.html">IOException
    {
        errorMsg = null;
        Connector connector = new Connector(new MyFTPClient(),host,port);

        logger.info("CONNECTING... waiting " + FTP_TIMEOUT_SECONDS + " seconds");
        1.5.0/docs/api/java/lang/Thread.html">Thread t = new 1.5.0/docs/api/java/lang/Thread.html">Thread(connector);
        t.start();
        try {
            for(int i=0;i<FTP_TIMEOUT_SECONDS;i++)
            {
                1.5.0/docs/api/java/lang/Thread.html">Thread.sleep(1000);
                if(!t.isAlive())
                {
                    if(connector.ftp.isConnected())
                        break;
                }
            }
            if(!connector.ftp.isConnected())
            {
                errorMsg = "errors.ftp.timeout";
                logger.info("Not Connected will interrupt");
                t.interrupt();
                return null;
            }
        } catch (1.5.0/docs/api/java/lang/InterruptedException.html">InterruptedException e) {
           logger.error(e,e);
           errorMsg = "errors.ftp.interrupt";
        }

        if (username != null && password != null)
        {
            //connector.ftp.setDataTimeout(1000000000);
            connector.ftp.setDataTimeout(10000);
            try {
                //connector.ftp.setSoTimeout(1000000000);
                connector.ftp.setSoTimeout(10000);
            } catch (1.5.0/docs/api/java/net/SocketException.html">SocketException e) {
                e.printStackTrace();
            }
            //connector.ftp.setDefaultTimeout(1000000000);
            connector.ftp.setDefaultTimeout(10000);
            if(connector.ftp.login(username,password))
            {
                return connector.ftp;
            }
            else
            {
                errorMsg = "errors.ftp.no.permission";
                logger.warn("Cant login user: " + username);
            }
        }
        if(errorMsg == null)
            errorMsg = "errors.ftp.unknown.error";
        return null;

        /* estava assim
        if (username != null)
            ftp.user(username);
        if (password != null)
            ftp.pass(password);*/

        //return ftp;
    }


    public 1.5.0/docs/api/java/lang/String.html">String getErrorMsg() {
        return errorMsg;
    }

    public 1.5.0/docs/api/java/lang/String.html">String getHost()
    {
        return host;
    }

    public void setHost(1.5.0/docs/api/java/lang/String.html">String host)
    {
        this.host = host;
    }

    public int getPort()
    {
        return port;
    }

    public void setPort(int port)
    {
        this.port = port;
    }

    public 1.5.0/docs/api/java/lang/String.html">String getUsername()
    {
        return username;
    }

    public void setUsername(1.5.0/docs/api/java/lang/String.html">String username)
    {
        this.username = username;
    }

    public 1.5.0/docs/api/java/lang/String.html">String getPassword()
    {
        return password;
    }

    public void setPassword(1.5.0/docs/api/java/lang/String.html">String password)
    {
        this.password = password;
    }

    public static FtpServer getServer(1.5.0/docs/api/java/lang/String.html">String urlStr, 1.5.0/docs/api/java/lang/String.html">String user, 1.5.0/docs/api/java/lang/String.html">String pass)
    {
        FtpServer ftpServer = servers.get(urlStr);
        if (ftpServer == null)
            ftpServer = addServer(urlStr, user, pass);
        return ftpServer;
    }

    public static FtpServer getNewServer(1.5.0/docs/api/java/lang/String.html">String urlStr, 1.5.0/docs/api/java/lang/String.html">String user, 1.5.0/docs/api/java/lang/String.html">String pass)
    {

        try
        {
            1.5.0/docs/api/java/net/URL.html">URL url = new 1.5.0/docs/api/java/net/URL.html">URL(urlStr);
            1.5.0/docs/api/java/lang/String.html">String host = url.getHost();
            int port = url.getPort();
            if (port <= 0)
                port = 21;
            logger.info("Connecting to " + host + "in port:" + port);
            return new FtpServer(host, port, user, pass);
        }
        catch (1.5.0/docs/api/java/net/MalformedURLException.html">MalformedURLException e)
        {
            logger.error(e, e);
        }
        catch (1.5.0/docs/api/java/io/IOException.html">IOException e)
        {
            logger.error(e, e);
        }
        return null;

    }

    /**
     * Add a ftpServer to Cache
     *
     * @param urlStr to parse
     * @param user   username
     * @param pass   password
     * @return ftpServer
     */

    private static synchronized FtpServer addServer(1.5.0/docs/api/java/lang/String.html">String urlStr, 1.5.0/docs/api/java/lang/String.html">String user, 1.5.0/docs/api/java/lang/String.html">String pass)
    {
        try
        {
            1.5.0/docs/api/java/net/URL.html">URL url = new 1.5.0/docs/api/java/net/URL.html">URL(urlStr);
            1.5.0/docs/api/java/lang/String.html">String host = url.getHost();
            int port = url.getPort();
            if (port <= 0)
                port = 21;
            logger.info("Connecting to " + host + " in port:" + port);
            FtpServer ftpServer = new FtpServer(host, port, user, pass);
            servers.put(urlStr, ftpServer);
            return ftpServer;
        }
        catch (1.5.0/docs/api/java/net/MalformedURLException.html">MalformedURLException e)
        {
            logger.error(e, e);
        }
        catch (1.5.0/docs/api/java/io/IOException.html">IOException e)
        {
            logger.error(e, e);
        }
        return null;
    }

    public static class FtpClientWrapper
    {
        FtpServer server;
        FTPClient client = null;
        private int restartTimes = 2;
        private int tries = 0;
        private 1.5.0/docs/api/java/lang/String.html">String lastWorkingDirectory = "";
        private int fileType;

        private int TIMEOUT_FILES = 1000 * 60;

        public int getTIMEOUT_FILES() {
            return TIMEOUT_FILES;
        }

        /**
         * in miliseconds
         * @param TIMEOUT_FILES
         */

        public void setTIMEOUT_FILES(int TIMEOUT_FILES) {
            this.TIMEOUT_FILES = TIMEOUT_FILES;
        }

        public FtpClientWrapper(FtpServer server,int restartTimesOnFail) throws 1.5.0/docs/api/java/io/IOException.html">IOException {

            this.server = server;
            this.restartTimes = restartTimesOnFail;
            client = server.getClient();
            client.setDataTimeout(TIMEOUT_FILES);
            client.setSoTimeout(10000);

            //client.setSoTimeout(TIMEOUT_FILES);
            client.setDefaultTimeout(10000);
            client.enterLocalActiveMode();
        }


        /*public boolean changeWorkingDirectory(String pathname) throws IOException
        {
            return changeWorkingDirectory(pathname, false);
        }*/


        public boolean changeWorkingDirectory(1.5.0/docs/api/java/lang/String.html">String pathname,boolean absolute) throws 1.5.0/docs/api/java/io/IOException.html">IOException
        {
            try{
                tries++;
                boolean b = client.changeWorkingDirectory(pathname);
                tries = 0;
                if(b)
                {
                    if(absolute)
                        lastWorkingDirectory = pathname;
                    else
                        lastWorkingDirectory = lastWorkingDirectory + "/" + pathname;
                }
                return b;
            }
            catch(1.5.0/docs/api/java/io/IOException.html">IOException e)
            {
                if(tries > restartTimes)
                {
                    tries = 0;
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.enterLocalActiveMode();
                    logger.error("Restart exceed maximum restart times of " + restartTimes);
                    throw e;
                }
                else
                {
                    logger.warn("FTP Fail will try restart " + tries + "º connection of " + restartTimes + " error: " + e.toString());
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.enterLocalActiveMode();
                    if(absolute)
                        return changeWorkingDirectory(pathname,true);
                    else
                    {
                        client.changeWorkingDirectory(lastWorkingDirectory);
                        return changeWorkingDirectory(pathname,false);
                    }
                }
            }
        }

        public void changeToParentDirectory() throws 1.5.0/docs/api/java/io/IOException.html">IOException
        {
            try{
                tries++;
                boolean b = client.changeToParentDirectory();
                tries = 0;
                if(b)
                {
                    lastWorkingDirectory = lastWorkingDirectory.substring(0,lastWorkingDirectory.indexOf("/"));
                }
            }
            catch(1.5.0/docs/api/java/io/IOException.html">IOException e)
            {
                if(tries > restartTimes)
                {
                    tries = 0;
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    logger.error("Restart exceed maximum restart times of " + restartTimes);
                    throw e;
                }
                else
                {
                    logger.warn("FTP Fail will try restart " + tries + "º connection of " + restartTimes + " error: " + e.toString());
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.changeWorkingDirectory(lastWorkingDirectory);
                    changeToParentDirectory();
                }
            }
        }


        public void enterLocalPassiveMode() {
            client.enterLocalPassiveMode();
        }


        public void enterLocalActiveMode() {
            client.enterLocalActiveMode();
        }


        public boolean storeFile(1.5.0/docs/api/java/lang/String.html">String remote, 5+0%2Fdocs%2Fapi+InputStream">InputStream local) throws 1.5.0/docs/api/java/io/IOException.html">IOException {
            try{
                tries++;
                boolean b = client.storeFile(remote, local);
                tries = 0;
                return b;
            }
            catch(1.5.0/docs/api/java/io/IOException.html">IOException e)
            {
                if(tries > restartTimes)
                {
                    tries = 0;
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.enterLocalActiveMode();
                    logger.error("Restart exceed maximum restart times of " + restartTimes);
                    throw e;
                }
                else
                {
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.enterLocalActiveMode();
                    logger.warn("FTP Fail will try restart " + tries + "º connection of " + restartTimes + " error: " + e.toString());
                    return client.storeFile(remote, local);
                }
            }
        }

        public void close() throws 1.5.0/docs/api/java/io/IOException.html">IOException {
            client.quit();
            client.disconnect();
        }

        public void reconnect(boolean recoverWorkingDirectory) throws 1.5.0/docs/api/java/io/IOException.html">IOException
        {
            close();
            client = server.getClient();
            if(recoverWorkingDirectory)
                client.changeWorkingDirectory(lastWorkingDirectory);
            client.enterLocalActiveMode();
        }


        public boolean logout() throws 1.5.0/docs/api/java/io/IOException.html">IOException {
            return client.logout();
        }


        public boolean abort() throws 1.5.0/docs/api/java/io/IOException.html">IOException {
            return client.abort();
        }


        public 1.5.0/docs/api/java/lang/String.html">String[] listNames() throws 1.5.0/docs/api/java/io/IOException.html">IOException {

            try{
                tries++;
                1.5.0/docs/api/java/lang/String.html">String[] b = client.listNames();
                tries = 0;
                return b;
            }
            catch(1.5.0/docs/api/java/io/IOException.html">IOException e)
            {
                if(tries > restartTimes)
                {
                    tries = 0;
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.changeWorkingDirectory(lastWorkingDirectory);
                    client.enterLocalActiveMode();
                    logger.error("Restart exceed maximum restart times of " + restartTimes);
                    throw e;
                }
                else
                {
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.changeWorkingDirectory(lastWorkingDirectory);
                    client.enterLocalActiveMode();
                    logger.warn("FTP Fail will try restart " + tries + "º connection of " + restartTimes + " error: " + e.toString());
                    return client.listNames();
                }
            }
        }


        public FTPFile[] listFiles() throws 1.5.0/docs/api/java/io/IOException.html">IOException {
            try{
                tries++;
                FTPFile[] b = client.listFiles();
                tries = 0;
                return b;
            }
            catch(1.5.0/docs/api/java/io/IOException.html">IOException e)
            {
                if(tries > restartTimes)
                {
                    tries = 0;
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.changeWorkingDirectory(lastWorkingDirectory);
                    client.enterLocalActiveMode();
                    logger.error("Restart exceed maximum restart times of " + restartTimes);
                    throw e;
                }
                else
                {
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.changeWorkingDirectory(lastWorkingDirectory);
                    client.enterLocalActiveMode();
                    logger.warn("FTP Fail will try restart " + tries + "º connection of " + restartTimes + " error: " + e.toString());
                    return client.listFiles();
                }
            }
        }


        /**Metodo que nao manda Escepção em caso de timeout da operação
         * este metodo não é seguro pode estar em disconnect e nao deteta lendo 0 ficheiros sem dar erro*/

        public FTPFile[] listFiles(1.5.0/docs/api/java/lang/String.html">String pathname) throws 1.5.0/docs/api/java/io/IOException.html">IOException {
            try{
                tries++;

                FTPFile[] b = client.listFiles(pathname);
                if(!client.isConnected())
                    throw new 1.5.0/docs/api/java/io/IOException.html">IOException("Client disconnected guessed by BACO");
                tries = 0;
                return b;
            }
            catch(1.5.0/docs/api/java/io/IOException.html">IOException e)
            {
                if(tries > restartTimes)
                {
                    tries = 0;
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.changeWorkingDirectory(lastWorkingDirectory);
                    client.enterLocalActiveMode();
                    logger.error("Restart exceed maximum restart times of " + restartTimes);
                    throw e;
                }
                else
                {
                    client = server.getClient();
                    client.setDataTimeout(TIMEOUT_FILES);
                    client.changeWorkingDirectory(lastWorkingDirectory);
                    client.enterLocalActiveMode();
                    logger.warn("FTP Fail will try restart " + tries + "º connection of " + restartTimes + " error: " + e.toString());
                    return client.listFiles(pathname);
                }
            }
        }

        public FtpIsolatedInputStream  retrieveAbsoluteFileStream(1.5.0/docs/api/java/lang/String.html">String pathFile) throws 1.5.0/docs/api/java/io/IOException.html">IOException
        {
            //String urlStr = "ftp://" + server.getUsername() + ":" + server.getPassword() + "@" + server.getHost() + "/" + URIUtil.encodePath(pathFile,"ISO-8859-1");
            logger.info("Retrieving: " + pathFile);
            //URL url = new URL(urlStr);
            //return url.openStream();
            return new FtpIsolatedInputStream(pathFile,true);
        }

        public FtpIsolatedInputStream retrieveFileStreamInCurrentFolder(1.5.0/docs/api/java/lang/String.html">String name) throws 1.5.0/docs/api/java/io/IOException.html">IOException
        {
            //FTPClient client = server.getClient();
            //client.setDataTimeout(TIMEOUT_FILES);
            //client.changeWorkingDirectory(lastWorkingDirectory);
            logger.info("Retrieving: " + name);
            return new FtpIsolatedInputStream(name,false);
        }

        public void setBufferSize(int bufferSize) {
            client.setBufferSize(bufferSize);
        }

        public int getBufferSize() {
            return client.getBufferSize();
        }


        public void setFileType(int fileType) throws 1.5.0/docs/api/java/io/IOException.html">IOException {
            client.setFileType(fileType);
        }

        public void setDefaultFileType() throws 1.5.0/docs/api/java/io/IOException.html">IOException {
            client.setFileType(FTP.ASCII_FILE_TYPE);
        }

        public class FtpIsolatedInputStream
        {
            FTPClient clientIsolated;
            5+0%2Fdocs%2Fapi+InputStream">InputStream inputStream;

            public FtpIsolatedInputStream(1.5.0/docs/api/java/lang/String.html">String file,boolean absolute) throws 1.5.0/docs/api/java/io/IOException.html">IOException
            {
                clientIsolated = server.getClient();
                clientIsolated.setDataTimeout(TIMEOUT_FILES);
                clientIsolated.setFileType(FTP.BINARY_FILE_TYPE);
                if(!absolute)
                {
                    clientIsolated.changeWorkingDirectory(lastWorkingDirectory);
                }
                inputStream = clientIsolated.retrieveFileStream(file);
            }

            public 5+0%2Fdocs%2Fapi+InputStream">InputStream getInputStream() {
                return inputStream;
            }
            public void close(){
                try{
                    if(clientIsolated.isConnected())
                    {
                        clientIsolated.quit();
                        clientIsolated.disconnect();
                    }
                    else
                    {
                        1.5.0/docs/api/java/lang/System.html">System.out.println("Client isolated already disconnect");
                    }
                }catch(1.5.0/docs/api/java/lang/Throwable.html">Throwable e)
                {
                    logger.error(e,e);
                }

            }
        }

    }


    public static final int FTP_DATA_STORE_TIMEOUT_SECONDS = Globals.FTP_DATA_STORE_TIMEOUT_SECONDS;
    public class MyFTPClient extends FTPClient implements 1.5.0/docs/api/java/lang/Runnable.html">Runnable
    {
        1.5.0/docs/api/java/lang/String.html">String remote = "";
        5+0%2Fdocs%2Fapi+InputStream">InputStream local = null;
        boolean storeResult = false;

        public void run() {
            try {
                storeResult = super.storeFile(remote, local);
            } catch (1.5.0/docs/api/java/io/IOException.html">IOException e) {
                logger.error(e,e);
            }
        }
        @1.5.0/docs/api/java/lang/Override.html">Override
        public boolean storeFile(1.5.0/docs/api/java/lang/String.html">String remote, 5+0%2Fdocs%2Fapi+InputStream">InputStream local) throws 1.5.0/docs/api/java/io/IOException.html">IOException
        {
            logger.info("FTP store Timeout protection of " + FTP_DATA_STORE_TIMEOUT_SECONDS + " seconds");
            this.remote = remote;
            this.local = local;
            1.5.0/docs/api/java/lang/Thread.html">Thread t = new 1.5.0/docs/api/java/lang/Thread.html">Thread(this);
            t.start();
            try {
                for(int i=0;i<FTP_DATA_STORE_TIMEOUT_SECONDS;i++)
                {
                    1.5.0/docs/api/java/lang/Thread.html">Thread.sleep(1000);
                    if(!t.isAlive())
                    {
                       break;
                    }
                }
                if(t.isAlive())
                {
                    logger.info("Timeout expired will interrupt");
                    t.interrupt();
                    return false;
                }
            } catch (1.5.0/docs/api/java/lang/InterruptedException.html">InterruptedException e) {
                logger.error(e,e);
            }
            return storeResult;
        }


    }





}