net.securnetwork.itebooks.downloader.EbookDownloader.java Source code

Java tutorial

Introduction

Here is the source code for net.securnetwork.itebooks.downloader.EbookDownloader.java

Source

/*******************************************************************************
 * Copyright (c) 2012 Massimo Rabbi <mrabbi@users.sourceforge.net>.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Massimo Rabbi <mrabbi@users.sourceforge.net> - initial API and implementation
 ******************************************************************************/
package net.securnetwork.itebooks.downloader;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.List;
import java.util.StringTokenizer;
import java.util.prefs.Preferences;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Source;

import org.apache.commons.io.FileUtils;

/**
 * Main class with the program entry point.
 * 
 * @author Massimo Rabbi <mrabbi@users.sourceforge.net>
 *
 */
public final class EbookDownloader {
    // Program version
    private static final String VERSION = "0.2"; //$NON-NLS-1$
    // Program arguments
    private static final String END_INDEX_ARG = "-end="; //$NON-NLS-1$
    private static final String START_INDEX_ARG = "-start="; //$NON-NLS-1$
    private static final String OUTPUT_FOLDER_ARG = "-outputFolder="; //$NON-NLS-1$
    private static final String RESUME_ARG = "-resume"; //$NON-NLS-1$
    // Ebooks site related constants
    private static final int MIN_EBOOK_INDEX = 1;
    private static final int MAX_EBOOK_INDEX = 872; // This is the index of the last ebook 
    // available at August 2nd 2012.
    // Should be used only as fallback in case it is not possible
    // to retrieve the latest ebook id from the web page.
    private static final String BASE_URL = "http://it-ebooks.info"; //$NON-NLS-1$
    private static final String BASE_EBOOK_URL = BASE_URL + "/book/"; //$NON-NLS-1$
    private static final String SLASH = "/"; //$NON-NLS-1$
    // Preferences
    private static final Preferences prefs = Preferences.userRoot().node(EbookDownloader.class.getName());
    private static final String LAST_SAVED_EBOOK_PREF = "lastEbookSaved"; //$NON-NLS-1$
    private static final String OUTPUT_FOLDER_PREF = "outputFolder"; //$NON-NLS-1$

    /**
     * Program main method.
     * 
     * @param args the program arguments
     */
    public static void main(String[] args) {
        if (validateArguments(args)) {
            int start = MIN_EBOOK_INDEX;
            int end = getLastEbookIndex();
            String destinationFolder = null;
            // Check if resume mode
            if (args.length == 1 && args[0].equals(RESUME_ARG)) {
                start = Integer.parseInt(prefs.get(LAST_SAVED_EBOOK_PREF, MIN_EBOOK_INDEX - 1 + "")) + 1; //$NON-NLS-1$
                destinationFolder = prefs.get(OUTPUT_FOLDER_PREF, null);
            } else {
                destinationFolder = getDestinationFolder(args);
            }

            if (destinationFolder == null) {
                System.err.println(Messages.getString("EbookDownloader.NoDestinationFolderFound")); //$NON-NLS-1$
                return;
            } else {
                // Possibly fix the destination folder path
                destinationFolder = destinationFolder.replace("\\", "/");
                if (!destinationFolder.endsWith("/")) {
                    destinationFolder += "/";
                }
                prefs.put(OUTPUT_FOLDER_PREF, destinationFolder);
            }

            if (args.length == 3) {
                start = getStartIndex(args);
                end = getEndIndex(args);
            }
            try {
                for (int i = start; i <= end; i++) {
                    String ebookPage = BASE_EBOOK_URL + i + SLASH;
                    Source sourceHTML = new Source(new URL(ebookPage));
                    List<Element> allTables = sourceHTML.getAllElements(HTMLElementName.TABLE);
                    Element detailsTable = allTables.get(0);
                    // Try to build an info bean for the ebook
                    String bookTitle = EbookPageParseUtils.getTitle(detailsTable);
                    if (bookTitle != null) {
                        EbookInfo ebook = createEbookInfo(bookTitle, i, detailsTable);
                        String filename = destinationFolder + Misc.getValidFilename(ebook.getTitle(),
                                ebook.getSubTitle(), ebook.getYear(), ebook.getFileFormat());
                        System.out.print(MessageFormat.format(Messages.getString("EbookDownloader.InfoDownloading"), //$NON-NLS-1$
                                new Object[] { ebook.getSiteId() }));
                        try {
                            URL ebookPageURL = new URL(ebook.getDownloadLink());
                            HttpURLConnection con = (HttpURLConnection) ebookPageURL.openConnection();
                            con.setRequestMethod("GET");
                            con.setRequestProperty("Referer", ebookPage);
                            InputStream conIS = con.getInputStream();
                            FileUtils.copyInputStreamToFile(conIS, new File(filename));
                            System.out.println(Messages.getString("EbookDownloader.DownloadingOK")); //$NON-NLS-1$
                            prefs.put(LAST_SAVED_EBOOK_PREF, i + ""); //$NON-NLS-1$
                            conIS.close();
                        } catch (Exception e) {
                            System.out.println(Messages.getString("EbookDownloader.DownloadingKO")); //$NON-NLS-1$
                        }
                    }
                }

            } catch (Exception e) {
                System.err.println(Messages.getString("EbookDownloader.FatalError")); //$NON-NLS-1$
                e.printStackTrace();
            }
        } else {
            printHelp();
        }
    }

    /*
     * Prints program help.
     */
    private static void printHelp() {
        System.out.println("#################################################################"); //$NON-NLS-1$
        System.out.println(
                MessageFormat.format("# Ebook Downloader version {0}\t\t\t\t\t#", new Object[] { VERSION })); //$NON-NLS-1$
        System.out.println(MessageFormat.format("# Dumps ebook files from {0}\t\t\t#", new Object[] { BASE_URL })); //$NON-NLS-1$
        System.out.println("# Author: Massimo Rabbi (fud0) <mrabbi@users.sourceforge.net> \t#"); //$NON-NLS-1$
        System.out.println("#################################################################"); //$NON-NLS-1$
        System.out.println("Example of usage (1) - download all possible ebooks to the specified folder: "); //$NON-NLS-1$
        System.out.println("\tjava -jar ebookdownloader.jar -outputFolder=<folderLocation>"); //$NON-NLS-1$
        System.out.println(
                "Example of usage (2) - download selected ebooks, using a range id, to the specified folder: "); //$NON-NLS-1$
        System.out.println(
                "\tjava -jar ebookdownloader.jar -outputFolder=<folderLocation> -start=<startIndex> -end=<endIndex>"); //$NON-NLS-1$
        System.out.println("Example of usage (3) - resume a previous interrupted download: "); //$NON-NLS-1$
        System.out.println("\tjava -jar ebookdownloader.jar -resume"); //$NON-NLS-1$
    }

    /*
     * Checks if the format and number of the arguments is good.
     */
    private static boolean validateArguments(String[] args) {
        if (args.length == 1 && (args[0].startsWith(EbookDownloader.OUTPUT_FOLDER_ARG)
                || args[0].startsWith(EbookDownloader.RESUME_ARG))) {
            return true;
        }
        if (args.length == 3 && args[0].startsWith(EbookDownloader.OUTPUT_FOLDER_ARG)
                && args[1].startsWith(EbookDownloader.START_INDEX_ARG)
                && args[2].startsWith(EbookDownloader.END_INDEX_ARG)) {
            return true;
        }
        return false;
    }

    /*
     * Reads program arguments for destination folder info.
     */
    private static String getDestinationFolder(String[] args) {
        return args[0].substring(EbookDownloader.OUTPUT_FOLDER_ARG.length());
    }

    /*
     * Reads program arguments for the index of the first ebook to download.
     */
    private static Integer getStartIndex(String[] args) {
        return Integer.parseInt(args[1].substring(EbookDownloader.START_INDEX_ARG.length()));
    }

    /*
     * Reads program arguments for the index of the last ebook to download.
     */
    private static Integer getEndIndex(String[] args) {
        return Integer.parseInt(args[2].substring(EbookDownloader.END_INDEX_ARG.length()));
    }

    /*
     * Creates an information bean with details on the specified ebook.
     */
    private static EbookInfo createEbookInfo(String bookTitle, int id, Element detailsTable) {
        EbookInfo ebook = new EbookInfo();
        ebook.setTitle(bookTitle);
        ebook.setSiteId(id);
        ebook.setSiteURL(BASE_EBOOK_URL + id + SLASH);
        ebook.setSubTitle(EbookPageParseUtils.getSubtitle(detailsTable));
        ebook.setPublisher(EbookPageParseUtils.getPublisher(detailsTable));
        ebook.setAuthor(EbookPageParseUtils.getAuthor(detailsTable));
        ebook.setIsbn(EbookPageParseUtils.getISBN(detailsTable));
        ebook.setYear(EbookPageParseUtils.getYear(detailsTable));
        ebook.setPages(EbookPageParseUtils.getPages(detailsTable));
        ebook.setLanguage(EbookPageParseUtils.getLanguage(detailsTable));
        ebook.setFileSizeMB(EbookPageParseUtils.getFileSize((detailsTable)));
        ebook.setFileFormat(EbookPageParseUtils.getFileFormat(detailsTable));
        ebook.setDownloadLink(EbookPageParseUtils.getDownloadLink(detailsTable));
        return ebook;
    }

    /*
     * Retrieves the index of last available ebook.
     */
    private static int getLastEbookIndex() {
        try {
            Source sourceHTML = new Source(new URL(BASE_URL));
            List<Element> allTDs = sourceHTML.getAllElements(HTMLElementName.TD);
            for (Element td : allTDs) {
                List<Element> innerH2s = td.getAllElements(HTMLElementName.H2);
                if (!innerH2s.isEmpty() && "Last Upload Ebooks".equalsIgnoreCase( //$NON-NLS-1$
                        innerH2s.get(0).getTextExtractor().toString())) {
                    // Found interesting section
                    List<Element> allTDElements = td.getAllElements(HTMLElementName.TD);
                    Element lastEbookLink = allTDElements.get(0).getAllElements(HTMLElementName.A).get(0);
                    String lastEbookRelativeHref = lastEbookLink.getAttributeValue("href"); //$NON-NLS-1$
                    StringTokenizer tokenizer = new StringTokenizer(lastEbookRelativeHref, "/"); //$NON-NLS-1$
                    for (int i = 1; i < tokenizer.countTokens(); i++) {
                        tokenizer.nextToken();
                    }
                    return Integer.parseInt(tokenizer.nextToken());
                }

            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return MAX_EBOOK_INDEX;
    }
}