⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directorypoller.java

📁 一个简易的轮训小程序 哈哈哈哈哈哈后 嘿嘿嘿嘿黑诶
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
package org.sadun.util.polling;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.sadun.util.BidirectionalComparator;
import org.sadun.util.PathNormalizer;
import org.sadun.util.Terminable;

import com.deltax.util.listener.BaseSignalSourceThread;
import com.deltax.util.listener.ExceptionSignal;

/**
 * A Thread class to periodically poll the contents of one or more directories.
 * External asynchronous processes may put some files in one of the controlled directories,
 * and the poller can be used to detect their arrival.
 * <p>
 * Once started, this thread polls one or more directories every <i>x</i> milliseconds,
 * (see {@link DirectoryPoller#setPollInterval(long) setPollInterval()} and
 * {@link DirectoryPoller#getPollInterval() getPollInterval()}), looking for new files
 * satisfying a  given filter.
 * <br>Optionally, the thread may start by going to sleep (if
 * {@link DirectoryPoller#setStartBySleeping(boolean) setStartBySleeping()} is invoked).
 * <p>
 * To communicate results, the thread notifies events to any registered listener (see
 * below). Notably, if any files are "found", a {@link FileSetFoundEvent FileSetFoundEvent}
 * event is notified.
 * <p>
 * A {@link java.io.FilenameFilter java.io.FilenameFilter} can be provided at construction to identify the files to
 * look for. Besides, the poller can be set to run in two different time-based filtering modes (disabled by
 * default), which select only files satisfying the user-given filter and
 * <p>
 * <ul>
 * <li> whose <i>last modification time</i><a href="#note"><sup>*</sup></a> (<b>LMF</b>) is greater
 * than the time of the last polling <i>(default)</i>
 * <p><font size=-1>(Only files added to the directory after the last polling pass are selected)</font>
 * <p><i>or</i><p>
 * <li> whose <b>LMF</b> is greater than the higher <b>LMF</b> rilevated in
 * the file set selected in the last polling pass (or 0 for the first pass).
 * <p><font size=-1>(Only files which are newer than the newer file already polled are selected)</font>
 * </ul>
 * <p>
 * Use {@link DirectoryPoller#setTimeBased(boolean) setTimeBased()} and {@link
 * DirectoryPoller#isTimeBased() isTimeBased()} to enable the time-based mode and
 * {@link DirectoryPoller#setPollingTimeBased(boolean) setPollingTimeBased()}
 * and {@link DirectoryPoller#isPollingTimeBased() isPollingTimeBased()} to
 * select the specific subtype of time-based mode.
 * <p>
 * Without time-based mode, on every pass the poller will select <i>all</i> the files
 * in a controlled directory that match the filter, so it's client code responsability
 * to phisically move the files already processed somewhere else (see also the
 * <a href="#automove">automove</a> mode below).
 * <p>
 * The poller always notifies an event for a set of file discovered in a particular
 * directory. It may optionally notify a separate event for each file (see {@link
 * DirectoryPoller#setSendSingleFileEvent(boolean) setSendSingleFileEvent()} and
 * {@link DirectoryPoller#isSendSingleFileEvent() isSendSingleFileEvent()}).
 * <p>
 * The following events (all time-stamped) are produced:
 * <ul>
 * <li> {@link CycleStartEvent CycleStartEvent}
 * <br> The poller has awaken, and is starting to look in the directory set
 * <li> {@link DirectoryLookupStartEvent DirectoryLookupStartEvent}
 * <br> The poller is starting to look into a specific directory
 * <li> {@link FileSetFoundEvent FileSetFoundEvent}
 * <br> The poller has found some files in a directory, which match the polling criteria
 * <li> {@link FileFoundEvent FileFoundEvent} (<i>optional</i>)
 * <br> The poller has found one file in a directory, which match the polling criteria
 * <li> {@link DirectoryLookupEndEvent DirectoryLookupStartEvent}
 * <br> The poller has finished to look a specific directory
 * <li> {@link CycleEndEvent CycleEndEvent}
 * <br> The poller has finished to look in the directory set, and is going to sleep
 * </ul>
 * <p>
 * Any object implementing the {@link com.deltax.util.lf.Listener com.deltax.Listener} interface
 * can be registered and be notified of these events. However, a predefined listener,
 * {@link DefaultListener DefaultListener} is provided, which dispatches events to an object
 * implementing the {@link PollManager PollManager} interface, and a base
 * implementation of {@link PollManager PollManager}, {@link BasePollManager
 * BasePollManager} is provided as well.
 * <p>
 * The simplest way to receive events from the poller is therefore to create a class
 * extending {@link BasePollManager BasePollManager} overriding the proper
 * method(s) and register it to the directory poller by using
 * {@link DirectoryPoller#addPollManager(PollManager) addPollManager()}.
 * <p>
 * The order in which file events are received can be controlled by providing a
 * {@link java.util.Comparator} object which assigns an order to the file sets
 * read on each cycle and assigning it by {@link #setFilesSortComparator(Comparator)}.
 * By default, no order is imposed, i.e. the file events will be fired in an arbitrary 
 * order, depending on the operating system. (Two pre-packaged comparators 
 * {@link DirectoryPoller.ModificationTimeComparator} 
 * and {@link DirectoryPoller.FileSizeComparator} are provided by this class). 
 * <p>
 * <i>Note</i>: listeners will receive events <b><i>asynchronously</i></b> with respect
 * to the poller thread.
 * Therefore, if file processing is performed without moving the file out of the polled
 * directory, the polling interval should be big enough to allow such processing to
 * complete, or the same file may be notified more than once (expecially if time-based
 * polling is disabled).
 * <a name="automove"><p>
 * The version 1.2 of the class adds a new runtime mode - the <b>autoMove</b> mode.
 * When running in this mode, the poller automatically moves all the files found
 * in a controlled directory to an associated directory (which is <i>not</i> polled)
 * <i>before</i> notifying the listeners and/or the pollmanager. The events notified will
 * refer to the <i>new</i> location of the file.
 * <p>
 * This allows the user to set very short polling periods while ensuring that even slow
 * file processing will not cause the same file to be polled more than once (even if the
 * time-based polling mode is disabled).
 * <p>
 * If any exception occurs during the move operation, the relevant methods
 * of {@link PollManager PollManager} are invoked (as a consequence of the notification
 * of an underlying {@link com.deltax.util.listener.ExceptionSignal
 * com.deltax.util.listener.ExceptionSignal}).
 * <p>
 * If autoMove mode is enabled (see {@link DirectoryPoller#setAutoMove(boolean) setAutoMove()})
 * an arbitary directory may be explicitly associated to one of the controlled directories
 * by using {@link DirectoryPoller#setAutoMoveDirectory(java.io.File, java.io.File)
 * setAutoMoveDirectory()}.
 * <p>
 * If autoMove mode is enabled and the byPassLockedFiles property is true (defaults to false), 
 * locked files will be ignored. Otherwise, an exception signal will be raised if any file found in 
 * the controlled directory is locked.
 * <p>
 * If not, the poller will automatically associate to each
 * controlled directory a subdirectory whose name is defined by the public constant
 * {@link DirectoryPoller#DEFAULT_AUTOMOVE_DIRECTORY
 * DirectoryPoller.DEFAULT_AUTOMOVE_DIRECTORY}. The poller will attempt to create
 * the associated directory, if necessary - and on failure, an ExceptionSignal is
 * sent to the listeners, and the poller shuts down.
 * <p>
 * Note that ExceptionSignals are sent only when the auto-move mode is enabled.
 * </a>
 * <p>
 * <a name="note">(*) as returned by <tt>File.lastModified()</tt>.</a>
 *
 * @author C. Sadun (patched by Doug.Liao@fnf.com)
 * @version 1.4.4
 */
public class DirectoryPoller extends BaseSignalSourceThread implements Terminable {


    /**
     * An exception raised by the poller when auto-move mode is enabled,
     * but the move operation failed.
     */
    public class AutomoveException extends Exception {

        private File origin;
        private File dest;

        AutomoveException(File origin, File dest, String msg) {
            super(msg);
            this.origin=origin;
            this.dest=dest;
            if (verbose)
                System.out.println("[Automove] Exception: "+msg);
        }

        /**
         * Return the poller associated to this exception.
         * @return the poller associated to this exception.
         */
        public DirectoryPoller getPoller() { return DirectoryPoller.this; }

        /**
         * Return the file to be moved
         * @return the file to be moved
         */
        public File getOrigin() { return origin; }

        /**
         * Return the destination file
         * @return the destination file
         */
        public File getDestination() { return dest; }
    }

    /**
     * An exception raised by the poller when auto-move mode is enabled,
     * but the target file of the move operation exists and cannot be
     * deleted.
     */
    public class AutomoveDeleteException extends AutomoveException {
        AutomoveDeleteException(File origin, File dest, String msg) {
            super(origin, dest, msg);
        }
    }

    /**
     * The name of subdirectory automatically associated by the poller to any controlled
     * directory for the autoMode mode, unless {@link DirectoryPoller#setAutoMoveDirectory(java.io.File,
     * java.io.File) setAutoMoveDirectory()} is explicitly called before starting
     * the poller.
     * <p>
     * The current value is &quot;<b><tt>received</tt></b>&quot;
     */
    public static final String DEFAULT_AUTOMOVE_DIRECTORY = "received";

    private static int counter=0;
    private volatile boolean  shutdownRequested = false;
    private FilenameFilter filter;
    private File[]dirs;
    private long[] baseTime;

    private boolean verbose=( System.getProperty("org.sadun.verbose") != null);
    private boolean timeBasedOnLastLookup=true;

	protected List pollManagersList = new ArrayList();

    private boolean autoMove=false;
    private Map autoMoveDirs = new HashMap();

    private FilenameFilter originalFilter;
    private long pollInterval = 10000;
    private boolean startBySleeping=false;
    private boolean sendSingleFileEvent=false;

    private int currentDir=-1;

    private Comparator filesSortComparator = null;

    private boolean bypassLockedFiles = false;

    private volatile boolean sleeping=false;

    private volatile boolean debugExceptions;
      
    private static class DirectoryFilter implements FilenameFilter {

        FilenameFilter additionalFilter;

        DirectoryFilter(FilenameFilter additionalFilter) {
            this.additionalFilter=additionalFilter;
        }


        public boolean accept(File dir, String name) {
            if (new File(dir, name).isDirectory()) return false;
            return additionalFilter.accept(dir, name);
        }

        public String toString() {
            return "Directory filter over a "+additionalFilter;
        }
        
        FilenameFilter getAdditionalFilter() { return additionalFilter; }

    }

    private class TimeFilter implements FilenameFilter {

        private FilenameFilter additionalFilter;

        public TimeFilter(FilenameFilter additionalFilter) {
            this.additionalFilter=additionalFilter;
        }

        public boolean accept(File dir, String name) {
            File f = new File(dir,name);
            if (f.isDirectory()) return false;
            if (f.lastModified() <= baseTime[currentDir]) {
                if (verbose)
                    System.out.println(name+"("+f.lastModified()+"): out of base time ("+baseTime[currentDir]+"), ignoring");
                return false;
            } else {
                if (verbose)
                    System.out.println(name+"("+f.lastModified()+"): older than base time ("+baseTime[currentDir]+"), accepted");
            }

            return additionalFilter.accept(dir, name);
        }
    }

    public static final class NullFilenameFilter implements FilenameFilter {
        public boolean accept(File dir, String name) { return true; }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -