Package IO

Source Code of IO.Downloader

package IO;

import callback.ICallback;
import callback.IDownloadCallback;
import configuration.Configuration;
import configuration.objects.Dropbox;
import configuration.objects.URLPattern;
import exception.CantLoadPluginException;
import exception.FailedToDownloadException;
import exception.FailedToRenameException;
import exception.PluginNotFoundException;
import interfaces.IPlugin;
import main.PluginLoader;

import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Created by tama on 6/27/14.
*
* Try to download an image from an url
*/
public class Downloader implements Runnable
{
    private static String JPEG_TYPE = "image/jpeg";
    private static String PNG_TYPE = "image/png";
    private static String GIF_TYPE = "image/gif";

    private static Map<String, String> extensions;

    private String url;
    private String title;
    private Configuration conf;
    private PluginLoader loader;
    private String localFolder;
    private IDownloadCallback callback;

    private String getThread()
    {
        return "[" + new Date().toString() + "]";
    }

    public Downloader(Configuration conf, PluginLoader loader, String url, String title)
    {
        init(conf, loader, url, title, null);
    }

    public Downloader(Configuration conf, PluginLoader loader, String url, String title, IDownloadCallback callback)
    {
        init(conf, loader, url, title, callback);
    }

    private void init(Configuration conf, PluginLoader loader, String url, String title, IDownloadCallback callback)
    {
        this.url = url;
        this.title = title;
        this.conf = conf;
        this.loader = loader;
        this.callback = callback;

        extensions = new HashMap<String, String>();
        extensions.put(JPEG_TYPE, "jpeg");
        extensions.put(PNG_TYPE, "png");
        extensions.put(GIF_TYPE, "gif");

        System.out.println(getThread() + "Downloading [" + title + "] (" + url + ")");
    }

    /** Main method */
    public void run()
    {
        /* Get the different existing patterns */
        List<URLPattern> patterns = (List<URLPattern>)conf.get(Configuration.PATTERNS_TAG);

        /* Get the local folder */
        localFolder = (String)conf.get(Configuration.LOCAL_FOLDER_TAG);

        if (patterns == null)
            return;

        boolean found = false;
        int i = 0;

        try
        {
            for (; !found && i < patterns.size(); ++i)
            {
                URLPattern pattern = patterns.get(i);

                // The pattern is not active, skip it
                if (!pattern.active)
                {
                    continue;
                }

                // If the url pattern matches the pattern defined in the configuration ...
                Pattern urlPattern = pattern.pattern;
                if (urlPattern == null)
                    continue;

                Matcher matcher = urlPattern.matcher(url);
                if (matcher.find())
                {
                    //Load the corresponding pattern and download it !
                    IPlugin plugin = loader.getPlugin(pattern.pluginName);

                    //We found and loaded a plugin able to handle the link
                    found = true;

                    if (plugin != null)
                    {
                        //System.out.println(getThread() + "Using plugin " + pattern.pluginName);

                        List<String> urls = plugin.getLinks(url);
                        for (String url : urls)
                        {
                            download(url, localFolder, title, new ICallback() {
                                @Override
                                public void onDownloadFinished(File downloaded) {
                                    //Check if we should upload to Dropbox
                                    Dropbox dropbox = (Dropbox) conf.get(Configuration.DROPBOX_TAG);

                                    if (dropbox != null)
                                    {
                                         DropboxUploader.upload(downloaded, dropbox.access_token, dropbox.upload_folder);
                                    }

                                    if (callback != null)
                                    {
                                        callback.onSuccess(title);
                                    }
                                }
                            });
                        }
                    }
                    else
                    {
                        callback.onError(title, new CantLoadPluginException(pattern.pluginName));
                    }
                }
            }

            if (!found)
            {
                callback.onError(title, new PluginNotFoundException(url));
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            if (callback != null)
            {
                callback.onError(title, e);
            }
        }
    }

    /**
     * Download a file, with a callback called once the download is successful
     * @param url The URL to the file to download
     * @param localFolder the local folder in which the file will be downloaded
     * @param title the title of the link
     * @param downloadCallback the callback once the download is successful
     */
    private void download(String url, String localFolder, String title, ICallback downloadCallback)
    {
        InputStream stream = null;
        OutputStream out = null;
        try
        {
            stream = new URL(url).openStream();

            //Write to temporary file
            File tmp = File.createTempFile("img", "");

            out = new FileOutputStream(tmp);
            int read = 0;
            byte[] buffer = new byte[1024];

            while ((read = stream.read(buffer)) != -1)
            {
                out.write(buffer, 0, read);
            }

            File downloadedFile = rename(tmp, localFolder, title);

            if (downloadedFile == null)
            {
                /* Some error occured or the file is not valid, delete the temporary file */
                tmp.delete();
                callback.onError(title, new FailedToRenameException());
            }
            else
            {
                if (downloadCallback != null)
                {
                    downloadCallback.onDownloadFinished(downloadedFile);
                }
            }
        }
        catch (Exception e)
        {
            callback.onError(title, new FailedToDownloadException(e));
        }
        finally
        {
            try
            {
                if (stream != null)
                    stream.close();
            }
            catch (IOException e) {} //TODO : exception handling ?

            try
            {
                if (out != null)
                    out.close();
            }
            catch (IOException e) {} //TODO : exception handling ?
        }
    }

    /**
     * Rename a temporary file to the correct name according to the title of the link and the existing files
     * @param tmp the temporary file
     * @param localFolder the folder where the file will be moved
     * @param title the title of the link
     * @throws IOException IO error (file not found...)
     */
    private File rename(File tmp, String localFolder, String title) throws IOException
    {
        String fileType = Files.probeContentType(tmp.toPath());
        String extension = extensions.get(fileType);

        if (extension == null)
        {
            //System.out.println(getThread() + "File type unknown (" + fileType + "), defaulting to jpeg");
            //Default extension = jpeg
            extension = extensions.get(JPEG_TYPE);
        }

        /* Extension not authorized */
        List<String> authorizedExtensions = (List<String>) conf.get(Configuration.EXTENSIONS_ALLOWED_TAG);
        if (authorizedExtensions == null || !authorizedExtensions.contains(extension))
        {
            return null;
        }

        int extensionSize = extension.length() + 1;

        //System.out.println(getThread() + "File : " + extension + " [" + extensionSize + "]");

        //Check if the destination file exists, add random suffix if already existant
        StringBuilder sb = new StringBuilder();
        sb.append(localFolder);
        if (!localFolder.endsWith("/"))
        {
            sb.append("/");
        }
        sb.append(title).append(".").append(extension);

        boolean ok = false;

        File finalFile = null;

        int count = 1;

        String tmpName = sb.toString();

        while (!ok && count <= 25)
        {
            finalFile = new File(tmpName);

            //System.out.println(getThread() + ">> Trying " + tmpName);

            if (!finalFile.exists())
            {
                ok = true;
            }
            else
            {
                if (count == 1)
                {
                    //First try, replace extension with (1).extension
                    //e.g file_name (1).jpg
                    tmpName = tmpName.replace("." + extension, "(1)." + extension);
                }
                else
                {
                    //Replace file_name (n).jpg with file_name(n+1).jpg
                    //e.g file_name (1).jpg -> file_name (2).jpg
                    String toReplace = "(" + String.valueOf(count - 1) + ")." + extension;
                    String newName = "(" + String.valueOf(count) + ")." + extension;
                    tmpName = tmpName.replace(toReplace, newName);
                }
                count++;
            }
        }

        //Move the file !
        if (ok)
        {
            tmp.renameTo(finalFile);
            return finalFile;
        }

        return null;
    }
}
TOP

Related Classes of IO.Downloader

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.