de.ep3.ftpc.model.CrawlerThread.java Source code

Java tutorial

Introduction

Here is the source code for de.ep3.ftpc.model.CrawlerThread.java

Source

/*
 * FTP Crawler - A simple file crawler for UNIX based FTP servers
 * Copyright (C) 2014 Tobias Krebs
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package de.ep3.ftpc.model;

import de.ep3.ftpc.model.i18n.I18nManager;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import java.io.IOException;
import java.util.Vector;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * This is the always running (but most of its time sleeping) daemon crawler thread.
 *
 * It manages a list of crawler results and messages that can be asynchronously obtained
 * by other classes (usually by the crawler results controller, who will then be
 * responsible to render them).
 */
public class CrawlerThread extends Thread {

    private Crawler crawler;
    private I18nManager i18n;

    private FTPClient ftpClient;
    private boolean loggedIn = false;
    private Server currentServer;

    private CrawlerDirectories crawlerDirectories;
    private Vector<CrawlerResult> crawlerResults;
    private ConcurrentLinkedQueue<String> messageQueue;
    private String statusMessage;

    private int defaultSleep = 1000;
    private int runningSleep = 10;
    private int pausedSleep = 2000;
    private int currentSleep = defaultSleep;

    public CrawlerThread(Crawler crawler, I18nManager i18n) {
        this.crawler = crawler;
        this.i18n = i18n;

        crawlerResults = new Vector<>();
        messageQueue = new ConcurrentLinkedQueue<>();

        setDaemon(true);
        start();
    }

    public Vector<CrawlerResult> getCrawlerResults() {
        return crawlerResults;
    }

    public ConcurrentLinkedQueue<String> getMessageQueue() {
        return messageQueue;
    }

    public synchronized String getStatusMessage() {
        return statusMessage;
    }

    public synchronized void setStatusMessage(String statusMessage) {
        this.statusMessage = statusMessage;
    }

    private synchronized void setTranslatedStatusMessage(String token) {
        this.statusMessage = i18n.translate(token);
    }

    private synchronized void setTranslatedStatusMessage(String token, Object... args) {
        this.statusMessage = String.format(i18n.translate(token), args);
    }

    @Override
    public void run() {
        while (!isInterrupted()) {
            try {
                runStatusCheck();
                Thread.sleep(currentSleep);
            } catch (InterruptedException e) {
                interrupt();
            }
        }

        tryDisconnect();
    }

    private void runStatusCheck() {
        switch (crawler.getStatus()) {
        case IDLE:
            tryDisconnect();
            currentSleep = defaultSleep;
            break;
        case RUNNING:
            if (ftpClient == null) {
                ftpClient = new FTPClient();
            }

            if (!ftpClient.isConnected()) {
                currentServer = crawler.getServer();

                try {
                    setTranslatedStatusMessage("crawlerTryConnect");

                    ftpClient.connect(currentServer.need("server.ip"),
                            Integer.parseInt(currentServer.need("server.port")));

                    int replyCode = ftpClient.getReplyCode();

                    if (!FTPReply.isPositiveCompletion(replyCode)) {
                        throw new IOException(i18n.translate("crawlerServerRefused"));
                    }

                    if (currentServer.has("user.name")) {
                        String userName = currentServer.get("user.name");
                        String userPassword = "";

                        if (currentServer.hasTemporary("user.password")) {
                            userPassword = currentServer.getTemporary("user.password");
                        }

                        loggedIn = ftpClient.login(userName, userPassword);

                        if (!loggedIn) {
                            throw new IOException(i18n.translate("crawlerServerAuthFail"));
                        }
                    }

                    ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

                    setTranslatedStatusMessage("crawlerConnected");

                    /* Prepare directories */

                    crawlerDirectories = new CrawlerDirectories(ftpClient, currentServer.get("include-paths"),
                            currentServer.get("exclude-paths"));
                    crawlerResults.clear();

                } catch (IOException e) {
                    messageQueue.add(i18n.translate("crawlerConnectionFailed", currentServer.need("server.name"),
                            e.getMessage()));
                    tryStop();

                    return;
                }
            }

            try {
                runSearch();
            } catch (IOException e) {
                messageQueue.add(i18n.translate("crawlerProblem", e.getMessage()));
                tryStop();
            }

            currentSleep = runningSleep;
            break;
        case PAUSED:
            if (ftpClient != null && ftpClient.isConnected()) {
                try {
                    ftpClient.noop();

                    setTranslatedStatusMessage("crawlerPaused");
                } catch (IOException e) {
                    messageQueue.add(e.getMessage());
                    tryStop();
                }
            }

            currentSleep = pausedSleep;
            break;
        }
    }

    private void runSearch() throws IOException {
        CrawlerFile file = crawlerDirectories.getNextFile();

        if (file == null) {
            setTranslatedStatusMessage("crawlerDone");
            tryStop();
        } else {
            setTranslatedStatusMessage("crawlDir", file.getFullName());

            if (file.isRelevant(currentServer, i18n)) {
                String fileType = currentServer.get("crawler.file-type");

                CrawlerResult crawlerResult = new CrawlerResult(file, fileType, currentServer, ftpClient);

                // Add crawler results to the list, so that the panel can display the download progress already
                crawlerResults.add(crawlerResult);

                switch (fileType) {
                case "image-all":
                case "image-custom":
                    try {
                        crawlerResult.generatePreview();
                    } catch (IOException e) {
                    }
                    break;
                }

                crawlerResult.setPreviewPercentage(100);
            }
        }
    }

    private void tryStop() {
        tryDisconnect();

        switch (crawler.getStatus()) {
        case RUNNING:
        case PAUSED:
            crawler.stop();
            break;
        }

        setTranslatedStatusMessage("crawlerStopped");
    }

    private void tryDisconnect() {
        if (ftpClient != null && ftpClient.isConnected()) {
            setTranslatedStatusMessage("crawlerTryDisconnect");

            try {
                if (loggedIn) {
                    ftpClient.logout();
                }

                ftpClient.disconnect();

                setTranslatedStatusMessage("crawlerDisconnected");
            } catch (IOException e) {
                messageQueue.add(e.getMessage());
            }
        }

        loggedIn = false;
        currentServer = null;
    }

}