📄 directoryscanner.java
字号:
/* * DirectoryScanner.java * * Created on July 10, 2006, 4:20 PM * * @(#)DirectoryScanner.java 1.2 06/08/02 * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */package com.sun.jmx.examples.scandir;import static com.sun.jmx.examples.scandir.ScanManager.getNextSeqNumber;import com.sun.jmx.examples.scandir.ScanManagerMXBean.ScanState;import static com.sun.jmx.examples.scandir.ScanManagerMXBean.ScanState.*;import static com.sun.jmx.examples.scandir.config.DirectoryScannerConfig.Action.*;import com.sun.jmx.examples.scandir.config.XmlConfigUtils;import com.sun.jmx.examples.scandir.config.DirectoryScannerConfig;import com.sun.jmx.examples.scandir.config.DirectoryScannerConfig.Action;import com.sun.jmx.examples.scandir.config.ResultRecord;import java.io.File;import java.io.FileFilter;import java.io.IOException;import java.util.Arrays;import java.util.Collections;import java.util.EnumSet;import java.util.HashSet;import java.util.LinkedList;import java.util.Set;import java.util.logging.Level;import java.util.logging.Logger;import javax.management.AttributeChangeNotification;import javax.management.InstanceNotFoundException;import javax.management.ListenerNotFoundException;import javax.management.MBeanNotificationInfo;import javax.management.Notification;import javax.management.NotificationBroadcasterSupport;import javax.management.NotificationEmitter;import javax.management.NotificationFilter;import javax.management.NotificationListener;/** * A <code>DirectoryScanner</code> is an MBean that * scans a file system starting at a given root directory, * and then looks for files that match a given criteria. * <p> * When such a file is found, the <code>DirectoryScanner</code> takes * the action for which it was configured: emit a notification, * <i>and or</i> log a {@link * com.sun.jmx.examples.scandir.config.ResultRecord} for this file, * <i>and or</i> delete that file. * </p> * <p> * The code that would actually delete the file is commented out - so that * nothing valuable is lost if this example is run by mistake on the wrong * set of directories.<br> * Logged results are logged by sending them to the {@link ResultLogManager}. * </p> * <p> * <code>DirectoryScannerMXBeans</code> are created, initialized, and * registered by the {@link ScanManagerMXBean}. * The {@link ScanManagerMXBean} will also schedule and run them in * background by calling their {@link #scan} method. * </p> * <p>Client code is not expected to create or register directly any such * MBean. Instead, clients are expected to modify the configuration, using * the {@link ScanDirConfigMXBean}, and then apply it, using the {@link * ScanManagerMXBean}. Instances of <code>DirectoryScannerMXBeans</code> * will then be created and registered (or unregistered and garbage collected) * as a side effect of applying that configuration. * </p> * * @author Sun Microsystems, 2006 - All rights reserved. */public class DirectoryScanner implements DirectoryScannerMXBean, NotificationEmitter { /** * The type for <i>com.sun.jmx.examples.scandir.filematch</i> notifications. * Notifications of this type will be emitted whenever a file that * matches this {@code DirectoryScanner} criteria is found, but only if * this {@code DirectoryScanner} was configured to {@link * Action#NOTIFY notify} for matching files. **/ public static final String FILE_MATCHES_NOTIFICATION = "com.sun.jmx.examples.scandir.filematch"; /** * A logger for this class. **/ private static final Logger LOG = Logger.getLogger(DirectoryScanner.class.getName()); // Attribute : State // private volatile ScanState state = STOPPED; // The DirectoryScanner delegates the implementation of // the NotificationEmitter interface to a wrapped instance // of NotificationBroadcasterSupport. // private final NotificationBroadcasterSupport broadcaster; // The root directory at which this DirectoryScanner will start // scanning. Constructed from config.getRootDirectory(). // private final File rootFile; // This DirectoryScanner config - this is a constant which is // provided at construction time by the {@link ScanManager}. // private final DirectoryScannerConfig config; // The set of actions for which this DirectoryScanner is configured. // Constructed from config.getActions() // final Set<Action> actions; // The ResultLogManager that this DirectoryScanner will use to log // info. This is a hard reference to another MBean, provided // at construction time by the ScanManager. // The ScanManager makes sure that the life cycle of these two MBeans // is consistent. // final ResultLogManager logManager; /** * Constructs a new {@code DirectoryScanner}. * <p>This constructor is * package protected, and this MBean cannot be created by a remote * client, because it needs a reference to the {@link ResultLogManager}, * which cannot be provided from remote. * </p> * <p>This is a conscious design choice: {@code DirectoryScanner} MBeans * are expected to be completely managed (created, registered, unregistered) * by the {@link ScanManager} which does provide this reference. * </p> * * @param config This {@code DirectoryScanner} configuration. * @param logManager The info log manager with which to log the info * records. * @throws IllegalArgumentException if one of the parameter is null, or if * the provided {@code config} doesn't have its {@code name} set, * or if the {@link DirectoryScannerConfig#getRootDirectory * root directory} provided in the {@code config} is not acceptable * (not provided or not found or not readable, etc...). **/ public DirectoryScanner(DirectoryScannerConfig config, ResultLogManager logManager) throws IllegalArgumentException { if (logManager == null) throw new IllegalArgumentException("log=null"); if (config == null) throw new IllegalArgumentException("config=null"); if (config.getName() == null) throw new IllegalArgumentException("config.name=null"); broadcaster = new NotificationBroadcasterSupport(); // Clone the config: ensure data encapsulation. // this.config = XmlConfigUtils.xmlClone(config); // Checks that the provided root directory is valid. // Throws IllegalArgumentException if it isn't. // rootFile = validateRoot(config.getRootDirectory()); // Initialize the Set<Action> for which this DirectoryScanner // is configured. // if (config.getActions() == null) actions = Collections.emptySet(); else actions = EnumSet.copyOf(Arrays.asList(config.getActions())); this.logManager = logManager; } // see DirectoryScannerMXBean public void stop() { // switch state to stop and send AttributeValueChangeNotification setStateAndNotify(STOPPED); } // see DirectoryScannerMXBean public String getRootDirectory() { return rootFile.getAbsolutePath(); } // see DirectoryScannerMXBean public ScanState getState() { return state; } // see DirectoryScannerMXBean public DirectoryScannerConfig getConfiguration() { return config; } // see DirectoryScannerMXBean public String getCurrentScanInfo() { final ScanTask currentOrLastTask = currentTask; if (currentOrLastTask == null) return "Never Run"; return currentOrLastTask.getScanInfo(); } // This variable points to the current (or latest) scan. // private volatile ScanTask currentTask = null; // see DirectoryScannerMXBean public void scan() { final ScanTask task; synchronized (this) { final LinkedList<File> list; switch (state) { case RUNNING: case SCHEDULED: throw new IllegalStateException(state.toString()); case STOPPED: case COMPLETED: // only accept to scan if state is STOPPED or COMPLETED. list = new LinkedList<File>(); list.add(rootFile); break; default: throw new IllegalStateException(String.valueOf(state)); } // Create a new ScanTask object for our root directory file. // currentTask = task = new ScanTask(list,this); // transient state... will be switched to RUNNING when // task.execute() is called. This code could in fact be modified // to use java.util.concurent.Future and, to push the task to // an executor. We would then need to wait for the task to // complete before returning. However, this wouldn't buy us // anything - since this method should wait for the task to // finish anyway: so why would we do it? // As it stands, we simply call task.execute() in the current // thread - brave and fearless readers may want to attempt the // modification ;-) // setStateAndNotify(SCHEDULED); } task.execute(); } // This method is invoked to carry out the configured actions on a // matching file. // Do not call this method from within synchronized() { } as this // method may send notifications! // void actOn(File file) { // Which action were actually taken // final Set<Action> taken = new HashSet<Action>(); boolean logresult = false; // Check out which actions are configured and carry them out. // for (Action action : actions) { switch (action) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -