au.com.clearboxsystems.maven.plugins.nodejs.NodeJsWatcherMojo.java Source code

Java tutorial

Introduction

Here is the source code for au.com.clearboxsystems.maven.plugins.nodejs.NodeJsWatcherMojo.java

Source

package au.com.clearboxsystems.maven.plugins.nodejs;
/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * 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.
 */

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.tools.ant.taskdefs.Parallel;
import org.codehaus.plexus.util.cli.CommandLineException;

import java.io.IOException;
import java.io.File;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author: Paul Solomon
 * Date: 13/02/13
 */
@Mojo(name = "watch", defaultPhase = LifecyclePhase.PROCESS_SOURCES)
public class NodeJsWatcherMojo extends NodeJsMojoBase {

    private static final WatchEvent.Kind<?>[] watchEvents = { StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE };
    private WatchService watchService;
    private Map<Path, Task> watchTasks = new HashMap<>();

    private boolean changed = true;

    private final NodeJsMojoBase.TaskFilter filter = new NodeJsMojoBase.TaskFilter() {
        public boolean accept(Task t) {
            return t.watch;
        }
    };

    @Override
    public void execute() throws MojoExecutionException {
        NodeJsMojoBase.NodeInstallInformation info = super.run(filter);

        if (info == null) {
            return;
        }

        for (Task task : tasks) {
            try {
                if (task.watch) {
                    addWatchForTask(task);
                }
            } catch (IOException ex) {
                throw new MojoExecutionException("Error adding watch for task " + task, ex);
            }
        }

        getLog().info("Starting watch vigil");
        try {
            watch(info);
        } catch (CommandLineException ex) {
            throw new MojoExecutionException("Error during watch", ex);
        } catch (InterruptedException ex) {
            throw new MojoExecutionException("Error during watch", ex);
        } catch (IOException ex) {
            throw new MojoExecutionException("Error during watch", ex);
        }
    }

    public void addWatchForTask(final Task task) throws IOException {
        if (task instanceof NodeJsTask) {
            NodeJsTask nodeJsTask = (NodeJsTask) task;
            Path sourceDir = nodeJsTask.workingDirectory.toPath();
            watchTasks.put(sourceDir, task);

            if (watchService == null) {
                watchService = sourceDir.getFileSystem().newWatchService();
            }

            Files.walkFileTree(sourceDir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    dir.register(watchService, watchEvents);
                    watchTasks.put(dir, task);
                    //getLog().info("Adding NodeJS watcher for: " + dir.toString());
                    return FileVisitResult.CONTINUE;
                }
            });
        } else if (task instanceof ClosureCompilerTask) {
            final ClosureCompilerTask closureCompilerTask = (ClosureCompilerTask) task;

            if (watchService == null) {
                watchService = FileSystems.getDefault().newWatchService();
            }

            for (File source : closureCompilerTask.sources) {
                Path path = source.getParentFile().toPath();
                path.register(watchService, watchEvents);
                watchTasks.put(path, task);
                Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                            throws IOException {
                        dir.register(watchService, watchEvents);
                        watchTasks.put(dir, task);
                        //getLog().info("Adding Closure watcher for: " + closureCompilerTask.sources);
                        return FileVisitResult.CONTINUE;
                    }
                });
            }
        } else {
            watchService = null;
        }
    }

    public void watch(NodeJsMojoBase.NodeInstallInformation info)
            throws IOException, InterruptedException, CommandLineException, MojoExecutionException {
        while (true) {
            if (changed) {
                getLog().info("Waiting for changes...");
                changed = false;
            }

            WatchKey watchKey = watchService.take();
            Path dir = (Path) watchKey.watchable();

            List<String> updatedFiles = new ArrayList<>();
            for (WatchEvent<?> event : watchKey.pollEvents()) {
                Path file = dir.resolve((Path) event.context());
                String absolutePath = file.toFile().getAbsolutePath();
                String filename = file.toFile().getName();
                getLog().debug(String.format("watched %s - %s", event.kind().name(), file));

                if (file.toString().endsWith("___jb_bak___") || file.toString().endsWith("___jb_old___")) { // Ignore tmp files from idea
                    continue;
                }

                if (updatedFiles.contains(file.toString())) {
                    continue;
                }

                if (filename.startsWith(".")) {
                    continue;
                }

                if (filename.endsWith("~")) {
                    continue;
                }

                if (Files.isDirectory(file)) {
                    if (event.kind().name().equals(StandardWatchEventKinds.ENTRY_CREATE.name())) {
                        // watch created folder.
                        Task task = watchTasks.get(file.getParent());
                        if (task != null) {
                            file.register(watchService, watchEvents);
                            getLog().info(String.format("added watch for %s", file));
                            watchTasks.put(file, task);
                        }
                    }
                    continue;
                }

                if (event.kind().name().equals(StandardWatchEventKinds.ENTRY_MODIFY.name())
                        || event.kind().name().equals(StandardWatchEventKinds.ENTRY_CREATE.name())) {
                    updatedFiles.add(file.toString());
                    Task task = watchTasks.get(file);
                    if (task == null) {
                        task = watchTasks.get(file.getParent());
                    }
                    if (task != null) {
                        if (task instanceof ClosureCompilerTask) {
                            ClosureCompilerTask closureCompilerTask = (ClosureCompilerTask) task;
                            if (!filename.endsWith(".js")) {
                                // bail out here, because if it's not a .js file then the compiler task won't compile it
                                continue;
                            }
                            /*boolean validFile = false;
                            for (File source : closureCompilerTask.sources) {
                               String path = source.getAbsolutePath(); 
                               if (source.isDirectory()) {
                                  if (absolutePath.startsWith(filename)) {
                                     validFile = true;
                                  }
                               } else {
                                  if (absolutePath.equals(path)) {
                                     validFile = true;
                                  }
                               }
                            }
                            if (!validFile) {
                               continue;
                               }*/
                        }
                        getLog().info(String.format("%s MODIFIED rerunning Task", file));
                        executeTask(task, info);
                        changed = true;
                    }
                }

            }
            watchKey.reset();
        }
    }

}