Package ninja

Source Code of ninja.WatchAndRestartMachine

/**
* Copyright (C) 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ninja;

import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
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.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.nio.file.SensitivityWatchEventModifier;

public class WatchAndRestartMachine {
   
    List<String> exludePatterns;

    private static Logger logger = LoggerFactory.getLogger(WatchAndRestartMachine.class);

    RunClassInSeparateJvmMachine ninjaJettyInsideSeparateJvm;

    WatchService watchService;

    DelayedRestartTrigger restartAfterSomeTimeAndChanges;

    private final Map<WatchKey, Path> mapOfWatchKeysToPaths;

    /**
     * Creates a WatchService and registers the given
pathectoryToWatchRecursivelyForChangesectory
     */
    public WatchAndRestartMachine(
            String classNameWithMainToRun,
            Path directoryToWatchRecursivelyForChanges,
            List<String> classpath,
            List<String> excludeRegexPatterns,
            String contextPath,
            String port) throws IOException {

       
        this.exludePatterns = excludeRegexPatterns;
       
        this.ninjaJettyInsideSeparateJvm = new RunClassInSeparateJvmMachine(
                classNameWithMainToRun, classpath, contextPath, port);

        this.restartAfterSomeTimeAndChanges
                = new DelayedRestartTrigger(
                        ninjaJettyInsideSeparateJvm);
       
        this.restartAfterSomeTimeAndChanges.start();

        this.watchService = FileSystems.getDefault().newWatchService();
        this.mapOfWatchKeysToPaths = new HashMap<WatchKey, Path>();

        //System.out.format("Scanning: %s ...\n", directoryToWatchRecursivelyForChanges);
        registerAll(directoryToWatchRecursivelyForChanges);

    }

    /**
     * Register the given path with the WatchService
     */
    private void register(Path path) throws IOException {

        ////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //// USUALLY THIS IS THE DEFAULT WAY TO REGISTER THE EVENTS:
        ////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//        WatchKey watchKey = path.register(
//                watchService,
//                ENTRY_CREATE,
//                ENTRY_DELETE,
//                ENTRY_MODIFY);
       
        ////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        //// BUT THIS IS DAMN SLOW (at least on a Mac)
        //// THEREFORE WE USE EVENTS FROM COM.SUN PACKAGES THAT ARE WAY FASTER
        //// THIS MIGHT BREAK COMPATIBILITY WITH OTHER JDKs
        //// MORE: http://stackoverflow.com/questions/9588737/is-java-7-watchservice-slow-for-anyone-else
        ////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
        WatchKey watchKey = path.register(
                watchService,
           new WatchEvent.Kind[]{
               StandardWatchEventKinds.ENTRY_CREATE,
               StandardWatchEventKinds.ENTRY_MODIFY,
               StandardWatchEventKinds.ENTRY_DELETE
           },
           SensitivityWatchEventModifier.HIGH);
       
       

       
        mapOfWatchKeysToPaths.put(watchKey, path);

    }


    private void registerAll(final Path path) throws IOException {
        // register directory and sub-directories
        Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path path,
                    BasicFileAttributes attrs)
                    throws IOException {
                register(path);
                return FileVisitResult.CONTINUE;
            }
        });
    }

    public void startWatching() {

        for (;;) {

            WatchKey watchKey;
            try {
                watchKey = watchService.take();
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
                return;
            }

            Path path = mapOfWatchKeysToPaths.get(watchKey);
            if (path == null) {
                System.err.println("WatchKey not recognized!!");
                continue;
            }



            for (WatchEvent<?> watchEvent : watchKey.pollEvents()) {
                WatchEvent.Kind watchEventKind = watchEvent.kind();

                // TBD - provide example of how OVERFLOW watchEvent is handled
                if (watchEventKind == OVERFLOW) {
                    continue;
                }

                // Context for directory entry watchEvent is the file name of entry
                WatchEvent<Path> ev = (WatchEvent<Path>) watchEvent;
                Path name = ev.context();
                Path child = path.resolve(name);

                // print out watchEvent
                //System.out.format("%s: %s\n", watchEvent.kind().name(), child);
               
                if (watchEventKind == ENTRY_MODIFY) {
                   
                    // we are not interested in events from parent directories...
                    if (! child.toFile().isDirectory()) {
                       
                        if (!checkIfMatchesPattern(exludePatterns, child.toFile().getAbsolutePath())) {
                       
                            System.out.println(
                                    "Found file modification - triggering reload:  "
                                        + child.toFile().getAbsolutePath());
                           
                            restartAfterSomeTimeAndChanges.triggerRestart();
                           
                        }
                   
                    }

                }

                // ninjaJettyInsideSeparateJvm.restartNinjaJetty();
                // if directory is created, then
                // register it and its sub-directories recursively
                if (watchEventKind == ENTRY_CREATE) {
                   
                    restartAfterSomeTimeAndChanges.triggerRestart();
                   
                    try {
                        if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
                            registerAll(child);
                        }
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                        // ignore to keep sample readable
                    }

                }

            }

            // reset watchKey and remove from set if directory no longer accessible
            boolean valid = watchKey.reset();
            if (!valid) {
                mapOfWatchKeysToPaths.remove(watchKey);

                // all directories are inaccessible
                if (mapOfWatchKeysToPaths.isEmpty()) {
                    break;
                }

            }

        }

    }
   
   
   
    public static boolean checkIfMatchesPattern(List<String> regexPatterns, String string) {
   
       
        for (String regex : regexPatterns) {
       
            if (string.matches(regex)) {
                return true;
            }
           
        }
       
       
        return false;
    }
   
  

}
TOP

Related Classes of ninja.WatchAndRestartMachine

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.