From 43948fd320056375367b2f7fb433dec0eadef800 Mon Sep 17 00:00:00 2001 From: 4pr0n Date: Sun, 9 Mar 2014 00:20:22 -0800 Subject: [PATCH] Document *all* the things --- .../ripme/ripper/AbstractRipper.java | 73 ++++++++++++++++++- .../ripme/ripper/DownloadFileThread.java | 9 ++- .../ripme/ripper/DownloadThreadPool.java | 8 +- .../ripme/ripper/RipperInterface.java | 4 + .../com/rarchives/ripme/ui/MainWindow.java | 3 + .../rarchives/ripme/ui/RipStatusMessage.java | 3 + .../java/com/rarchives/ripme/utils/Utils.java | 26 ++++++- 7 files changed, 119 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java b/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java index 90931e77..4eb3abbe 100644 --- a/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java +++ b/src/main/java/com/rarchives/ripme/ripper/AbstractRipper.java @@ -32,7 +32,6 @@ public abstract class AbstractRipper protected DownloadThreadPool threadPool; protected Observer observer = null; - protected int itemsTotal; protected Map itemsPending = new HashMap(); protected Map itemsCompleted = new HashMap(); protected Map itemsErrored = new HashMap(); @@ -59,7 +58,7 @@ public abstract class AbstractRipper setWorkingDir(url); this.threadPool = new DownloadThreadPool(); } - + public void setObserver(Observer obs) { this.observer = obs; } @@ -107,6 +106,15 @@ public abstract class AbstractRipper threadPool.addThread(new DownloadFileThread(url, saveAs, this)); } + /** + * Queues file to be downloaded and saved. With options. + * @param url + * URL to download. + * @param prefix + * Prefix to prepend to the saved filename. + * @param subdirectory + * Sub-directory of the working directory to save the images to. + */ public void addURLToDownload(URL url, String prefix, String subdirectory) { String saveAs = url.toExternalForm(); saveAs = saveAs.substring(saveAs.lastIndexOf('/')+1); @@ -137,17 +145,32 @@ public abstract class AbstractRipper addURLToDownload(url, saveFileAs); } + /** + * Waits for downloading threads to complete. + */ protected void waitForThreads() { completed = false; threadPool.waitForThreads(); } + /** + * Notifies observers that source is being retrieved. + * @param url + * URL being retrieved + */ public void retrievingSource(URL url) { RipStatusMessage msg = new RipStatusMessage(STATUS.LOADING_RESOURCE, url); observer.update(this, msg); observer.notifyAll(); } + /** + * Notifies observers that a file download has completed. + * @param url + * URL that was completed. + * @param saveAs + * Where the downloaded file is stored. + */ public void downloadCompleted(URL url, File saveAs) { if (observer == null) { return; @@ -167,6 +190,11 @@ public abstract class AbstractRipper } } + /** + * Notifies observers that a file could not be downloaded (includes a reason). + * @param url + * @param reason + */ public void downloadErrored(URL url, String reason) { if (observer == null) { return; @@ -180,6 +208,12 @@ public abstract class AbstractRipper } } + /** + * Notify observers that a download could not be completed, + * but was not technically an "error". + * @param url + * @param message + */ public void downloadProblem(URL url, String message) { if (observer == null) { return; @@ -193,6 +227,9 @@ public abstract class AbstractRipper } } + /** + * Notifies observers and updates state if all files have been ripped. + */ private void checkIfComplete() { if (!completed && itemsPending.size() == 0) { completed = true; @@ -209,10 +246,20 @@ public abstract class AbstractRipper return url; } + /** + * @return + * Path to the directory in which all files + * ripped via this ripper will be stored. + */ public File getWorkingDir() { return workingDir; } + /** + * Sets directory to save all ripped files to. + * @param url + * URL to define how the workin directory should be saved. + */ public void setWorkingDir(URL url) throws IOException { String path = Utils.getWorkingDirectory().getCanonicalPath(); if (!path.endsWith(File.separator)) { @@ -243,12 +290,16 @@ public abstract class AbstractRipper return ripper; } catch (Exception e) { // Incompatible rippers *will* throw exceptions during instantiation. - //logger.error("Exception while instantiating: " + constructor.getName(), e); } } throw new Exception("No compatible ripper found"); } + /** + * @return + * List of constructors for all eligible Rippers. + * @throws Exception + */ private static List> getRipperConstructors() throws Exception { List> constructors = new ArrayList>(); for (Class clazz : Utils.getClassesForPackage("com.rarchives.ripme.ripper.rippers")) { @@ -259,6 +310,11 @@ public abstract class AbstractRipper return constructors; } + /** + * Sends an update message to the relevant observer(s) on this ripper. + * @param status + * @param message + */ public void sendUpdate(STATUS status, Object message) { if (observer == null) { return; @@ -269,11 +325,19 @@ public abstract class AbstractRipper } } + /** + * @return + * Integer between 0 and 100 defining the progress of the album rip. + */ public int getCompletionPercentage() { double total = itemsPending.size() + itemsErrored.size() + itemsCompleted.size(); return (int) (100 * ( (total - itemsPending.size()) / total)); } + /** + * @return + * Human-readable information on the status of the current rip. + */ public String getStatusText() { StringBuilder sb = new StringBuilder(); sb.append(getCompletionPercentage()) @@ -284,6 +348,9 @@ public abstract class AbstractRipper return sb.toString(); } + /** + * Rips the album when the thread is invoked. + */ public void run() { try { rip(); diff --git a/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java b/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java index 4dd2e4f3..8cb8000a 100644 --- a/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java +++ b/src/main/java/com/rarchives/ripme/ripper/DownloadFileThread.java @@ -12,6 +12,10 @@ import org.jsoup.Jsoup; import com.rarchives.ripme.ui.RipStatusMessage.STATUS; import com.rarchives.ripme.utils.Utils; +/** + * Thread for downloading files. + * Includes retry logic, observer notifications, and other goodies. + */ public class DownloadFileThread extends Thread { private static final Logger logger = Logger.getLogger(DownloadFileThread.class); @@ -31,8 +35,11 @@ public class DownloadFileThread extends Thread { this.retries = Utils.getConfigInteger("download.retries", 1); } + /** + * Attempts to download the file. Retries as needed. + * Notifies observers upon completion/error/warn. + */ public void run() { - // Check if file already exists if (saveAs.exists()) { if (Utils.getConfigBoolean("file.overwrite", false)) { logger.info("[!] Deleting existing file" + prettySaveAs); diff --git a/src/main/java/com/rarchives/ripme/ripper/DownloadThreadPool.java b/src/main/java/com/rarchives/ripme/ripper/DownloadThreadPool.java index 56e0281f..11f69af9 100644 --- a/src/main/java/com/rarchives/ripme/ripper/DownloadThreadPool.java +++ b/src/main/java/com/rarchives/ripme/ripper/DownloadThreadPool.java @@ -8,6 +8,9 @@ import org.apache.log4j.Logger; import com.rarchives.ripme.utils.Utils; +/** + * Simple wrapper around a FixedThreadPool. + */ public class DownloadThreadPool { private static final Logger logger = Logger.getLogger(DownloadThreadPool.class); @@ -34,9 +37,10 @@ public class DownloadThreadPool { public void waitForThreads() { threadPool.shutdown(); try { - threadPool.awaitTermination(60, TimeUnit.SECONDS); + // XXX What if some rips take longer than 120 seconds to complete? + threadPool.awaitTermination(120, TimeUnit.SECONDS); } catch (InterruptedException e) { - logger.error("Interrupted while waiting for threads to finish: ", e); + logger.error("[!] Interrupted while waiting for threads to finish: ", e); } } } diff --git a/src/main/java/com/rarchives/ripme/ripper/RipperInterface.java b/src/main/java/com/rarchives/ripme/ripper/RipperInterface.java index d6c811e8..5c4e6e0d 100644 --- a/src/main/java/com/rarchives/ripme/ripper/RipperInterface.java +++ b/src/main/java/com/rarchives/ripme/ripper/RipperInterface.java @@ -4,6 +4,10 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +/** + * I have no idea why I made this interface. Everything is captured within the AbstractRipper. + * Oh well, here's to encapsulation and abstraction! (raises glass) + */ public interface RipperInterface { public void rip() throws IOException; public boolean canRip(URL url); diff --git a/src/main/java/com/rarchives/ripme/ui/MainWindow.java b/src/main/java/com/rarchives/ripme/ui/MainWindow.java index e0ebdc0f..1cdee66a 100644 --- a/src/main/java/com/rarchives/ripme/ui/MainWindow.java +++ b/src/main/java/com/rarchives/ripme/ui/MainWindow.java @@ -43,6 +43,9 @@ import org.apache.log4j.Logger; import com.rarchives.ripme.ripper.AbstractRipper; import com.rarchives.ripme.utils.Utils; +/** + * Everything UI-related starts and ends here. + */ public class MainWindow implements Runnable { private static final Logger logger = Logger.getLogger(MainWindow.class); diff --git a/src/main/java/com/rarchives/ripme/ui/RipStatusMessage.java b/src/main/java/com/rarchives/ripme/ui/RipStatusMessage.java index c7bd28fb..45c01edc 100644 --- a/src/main/java/com/rarchives/ripme/ui/RipStatusMessage.java +++ b/src/main/java/com/rarchives/ripme/ui/RipStatusMessage.java @@ -1,5 +1,8 @@ package com.rarchives.ripme.ui; +/** + * Contains information about downloaded files and rips, and their states. + */ public class RipStatusMessage { public enum STATUS { diff --git a/src/main/java/com/rarchives/ripme/utils/Utils.java b/src/main/java/com/rarchives/ripme/utils/Utils.java index 9569c6a0..8124c981 100644 --- a/src/main/java/com/rarchives/ripme/utils/Utils.java +++ b/src/main/java/com/rarchives/ripme/utils/Utils.java @@ -14,9 +14,12 @@ import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.log4j.Logger; +/** + * Common utility functions used in various places throughout the project. + */ public class Utils { - public static final String RIP_DIRECTORY = "rips"; + public static final String RIP_DIRECTORY = "rips"; private static final File configFile = new File("src/main/resources/rip.properties"); private static final Logger logger = Logger.getLogger(Utils.class); @@ -29,6 +32,12 @@ public class Utils { } } + /** + * Get the root rips directory. + * @return + * Root directory to save rips to. + * @throws IOException + */ public static File getWorkingDirectory() throws IOException { String path = new File(".").getCanonicalPath() + File.separator; path += RIP_DIRECTORY + File.separator; @@ -75,10 +84,25 @@ public class Utils { return prettySaveAs; } + /** + * Removes the current working directory from a given filename + * @param file + * @return + * 'file' without the leading current working directory + */ public static String removeCWD(String file) { return removeCWD(new File(file)); } + /** + * Get a list of all Classes within a package. + * Works with file system projects and jar files! + * Borrowed from StackOverflow, but I don't have a link :[ + * @param pkgname + * The name of the package + * @return + * List of classes within the package + */ public static ArrayList> getClassesForPackage(String pkgname) { ArrayList> classes = new ArrayList>(); String relPath = pkgname.replace('.', '/');