Package org.apdplat.module.system.service

Source Code of org.apdplat.module.system.service.WatchDirectory

/**
*
* APDPlat - Application Product Development Platform
* Copyright (c) 2013, 杨尚川, yang-shangchuan@qq.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
*/

package org.apdplat.module.system.service;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apdplat.platform.log.APDPlatLogger;
import org.apdplat.platform.log.APDPlatLoggerFactory;

/**
* 目录监控服务
* @author 杨尚川
*/
public class WatchDirectory {
    private static final APDPlatLogger LOG = APDPlatLoggerFactory.getAPDPlatLogger(WatchDirectory.class);
   
    private static WatchService watchService;
    private static final Map<WatchKey, Path> directories = new HashMap<>();
    private static Thread thread = null;
    /**
     * 开始监控目录(启动一个新的线程)
     * @param dir 绝对路径
     */
    public static void startWatch(final String dir) {
        if(!PropertyHolder.getBooleanProperty("watch.directory.enable")){
            LOG.info("未启用目录监控服务");
            return;
        }
        LOG.info("启用目录监控服务");
        Path start = Paths.get(dir);
        try {
            watchService = FileSystems.getDefault().newWatchService();
            registerTree(start);
        } catch (IOException ex) {
            LOG.error("监控目录失败:" + start.toAbsolutePath(), ex);
            LOG.error("Failed to monitor directory:" + start.toAbsolutePath(), ex, Locale.ENGLISH);
            return;
        }
        LOG.info("开始监控目录:" + start.toAbsolutePath());
        LOG.info("Start to monitor directory:" + start.toAbsolutePath(), Locale.ENGLISH);
        thread = new Thread(new Runnable(){

            @Override
            public void run() {
                watch();
            }
           
        });
        thread.start();
    }
    /**
     * 停止目录监控
     */
    public static void stopWatch(){
        if(thread != null){
            thread.interrupt();
        }
    }
    private static void watch(){
        try {
            while (true) {
                final WatchKey key = watchService.take();
                if(key == null){
                    continue;
                }
                for (WatchEvent<?> watchEvent : key.pollEvents()) {
                    final WatchEvent.Kind<?> kind = watchEvent.kind();
                    //忽略无效事件
                    if (kind == StandardWatchEventKinds.OVERFLOW) {
                        continue;
                    }
                    final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
                    //path是相对路径(相对于监控目录)
                    final Path contextPath = watchEventPath.context();
                    LOG.debug("contextPath:"+contextPath);
                    //获取监控目录
                    final Path directoryPath = directories.get(key);
                    LOG.debug("directoryPath:"+directoryPath);
                    //得到绝对路径
                    final Path absolutePath = directoryPath.resolve(contextPath);
                    LOG.debug("absolutePath:"+absolutePath);
                    LOG.debug("kind:"+kind);
                    //判断事件类别
                    switch (kind.name()) {
                        case "ENTRY_CREATE":
                            if (Files.isDirectory(absolutePath, LinkOption.NOFOLLOW_LINKS)) {
                                LOG.info("新增目录:" + absolutePath);
                                LOG.info("Create directory:" + absolutePath, Locale.ENGLISH);
                                //为新增的目录及其所有子目录注册监控事件
                                registerTree(absolutePath);
                            }else{
                                LOG.info("新增文件:" + absolutePath);
                                LOG.info("Create file:" + absolutePath, Locale.ENGLISH);                               
                            }
                            break;
                        case "ENTRY_DELETE":
                            LOG.info("删除:" + absolutePath);
                            LOG.info("Delete:" + absolutePath, Locale.ENGLISH);
                            break;
                    }
                }
                boolean valid = key.reset();
                if (!valid) {
                    LOG.info("停止监控目录:"+directories.get(key));
                    directories.remove(key);
                    if (directories.isEmpty()) {
                        LOG.error("退出监控");
                        break;
                    }
                }
            }
        } catch (IOException ex) {
            LOG.error("监控目录出错", ex);
        } catch (InterruptedException ex) {
            LOG.info("监控目录线程退出");
        } finally{
            try {
                watchService.close();
                LOG.info("关闭监控目录服务");
            } catch (IOException ex) {
                LOG.error("关闭监控目录服务出错", ex);
            }
        }
    }
    /**
     * 为指定目录及其所有子目录注册监控事件
     * @param start 目录
     * @throws IOException
     */
    private static void registerTree(Path start) throws IOException {
        Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                    throws IOException {
                registerPath(dir);
                return FileVisitResult.CONTINUE;
            }
        });
    }
    /**
     * 为指定目录注册监控事件
     * @param path
     * @throws IOException
     */
    private static void registerPath(Path path) throws IOException {
        LOG.debug("监控目录:" + path);
        WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_DELETE);
        directories.put(key, path);
    }
    public static void main(String[] args) {
        WatchDirectory.startWatch("D:\\Workspaces\\NetBeansProjects\\APDPlat\\APDPlat_Web\\target\\APDPlat_Web-2.5\\");
    }
}
TOP

Related Classes of org.apdplat.module.system.service.WatchDirectory

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.