Java tutorial
package org.jsweet; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import java.io.File; import java.io.IOException; import java.nio.file.*; import java.util.List; import static java.nio.file.StandardWatchEventKinds.*; /* Copyright 2016 Eric Ponthiaux -/- ponthiaux.eric@gmail.com 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. */ /* @author EPOTH -/- ponthiaux.e@sfeir.com -/- ponthiaux.eric@gmail.com */ @Mojo(name = "jetty-watch", defaultPhase = LifecyclePhase.TEST, requiresDependencyResolution = ResolutionScope.COMPILE) public class JSweetJettyWatchMojo extends AbstractJSweetMojo { private TranspilerThread transpilerThread; private JettyThread jettyThread; public void execute() throws MojoFailureException, MojoExecutionException { MavenProject project = getMavenProject(); setOutDir(project.getBasedir() + "/src/main/webapp/" + getRelativeOutDir()); setCandiesJsOut(new File(project.getBasedir() + "/src/main/webapp/" + getRelativeOutDir())); getLog().info("Starting transpiler thread ..."); getLog().info("Transpilator output directory " + getOutDir()); transpilerThread = new TranspilerThread(this, createJSweetTranspiler(project)); transpilerThread.start(); while (!transpilerThread.isRunning()) { Thread.yield(); } /* */ getLog().info("Starting jetty thread ... "); jettyThread = new JettyThread(this); jettyThread.start(); while (!jettyThread.isRunning()) { Thread.yield(); } /* */ WatchService jsweetWatcher = createJSweetWatcher(project); WatchService jettyWatcher = createJettyWatcher(project); /* */ for (;;) { /* */ int jettyWatchReturn = jettyWatch(jettyWatcher); if (jettyWatchReturn == -1) { try { jettyWatcher.close(); jettyWatcher = createJettyWatcher(project); } catch (IOException ioException) { getLog().info(ioException); } } /* */ Thread.yield(); /* */ int jsweetWatchReturn = jsweetWatch(jsweetWatcher); if (jsweetWatchReturn == -1) { try { jsweetWatcher.close(); jsweetWatcher = createJSweetWatcher(project); } catch (IOException ioException) { getLog().info(ioException); } } /* */ Thread.yield(); /* */ } } private WatchService createJSweetWatcher(MavenProject project) { WatchService watchService = null; try { @SuppressWarnings("unchecked") List<String> sourcePaths = project.getCompileSourceRoots(); getLog().info("Updating jsweet source paths"); ResourceScanner sourceScanner = new ResourceScanner(this, sourcePaths, includes, excludes, sharedIncludes ); watchService = FileSystems.getDefault().newWatchService(); WatcherUtils.registerPaths(this, watchService, sourceScanner.scan()); /* */ } catch (IOException ioException) { getLog().info(ioException); } return watchService; } private WatchService createJettyWatcher(MavenProject project) { WatchService watchService = null; try { @SuppressWarnings("unchecked") List<String> sourcePaths = project.getCompileSourceRoots(); getLog().info("Updating server source paths"); ResourceScanner sourceScanner = new ResourceScanner(this, sourcePaths, excludes, includes, sharedIncludes ); watchService = FileSystems.getDefault().newWatchService(); WatcherUtils.registerPaths(this, watchService, sourceScanner.scan()); /* */ } catch (IOException ioException) { getLog().info(ioException); } return watchService; } private static class FileEvent { public FileEvent(long timeInMillis, String fileName) { this.timeInMillis = timeInMillis; this.fileName = fileName; } long timeInMillis; String fileName; } private FileEvent lastWebFileEvent = new FileEvent(System.currentTimeMillis(), ""); private boolean hasSameWebFileEvent(String fileName) { if (lastWebFileEvent.fileName.equals(fileName)) { if (lastWebFileEvent.timeInMillis + 1000 > (System.currentTimeMillis())) { return true; } else { lastWebFileEvent = new FileEvent(System.currentTimeMillis(), fileName); return false; } } else { lastWebFileEvent = new FileEvent(System.currentTimeMillis(), fileName); return false; } } private FileEvent lastServerFileEvent = new FileEvent(System.currentTimeMillis(), ""); private boolean hasSameServerFileEvent(String fileName) { if (lastServerFileEvent.fileName.equals(fileName)) { if (lastServerFileEvent.timeInMillis + 1000 > (System.currentTimeMillis())) { return true; } else { lastServerFileEvent = new FileEvent(System.currentTimeMillis(), fileName); return false; } } else { lastServerFileEvent = new FileEvent(System.currentTimeMillis(), fileName); return false; } } /* */ private int jsweetWatch(WatchService watchService) { WatchKey key; key = watchService.poll(); if (key == null) return 0; for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); if (kind == OVERFLOW) { continue; } @SuppressWarnings("unchecked") WatchEvent<Path> ev = (WatchEvent<Path>) event; Path filename = ev.context(); /* */ if (kind == ENTRY_MODIFY) { if (!hasSameWebFileEvent(filename.toString())) { if (isJavaFile(filename.toString())) { getLog().info("File change detected * " + filename); transpilerThread.tick(); } } } /* */ if (kind == ENTRY_CREATE) { if (!hasSameWebFileEvent(filename.toString())) { if (isJavaFile(filename.toString())) { getLog().info("File change detected * " + filename); transpilerThread.tick(); } else if (!isTempFile(filename.toString())) { getLog().info("New directory added !"); return -1; } } } if (!key.reset()) { key.cancel(); } } return 0; } private int jettyWatch(WatchService watchService) { WatchKey key; key = watchService.poll(); if (key == null) return 0; for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); if (kind == OVERFLOW) { continue; } @SuppressWarnings("unchecked") WatchEvent<Path> ev = (WatchEvent<Path>) event; Path filename = ev.context(); /* */ if (kind == ENTRY_MODIFY) { if (!hasSameServerFileEvent(filename.toString())) { if (isJavaFile(filename.toString())) { getLog().info("File change detected * " + filename); jettyThread.tick(); } } } /* */ if (kind == ENTRY_CREATE) { if (!hasSameServerFileEvent(filename.toString())) { if (isJavaFile(filename.toString())) { getLog().info("File change detected * " + filename); jettyThread.tick(); } else if (!isTempFile(filename.toString())) { getLog().info("New directory added !"); return -1; } } } if (!key.reset()) { key.cancel(); } } return 0; } /* */ private boolean isJavaFile(String fileName) { return fileName.endsWith(".java"); } /* to handle intelij "save in a temporary file feature on windows" */ private boolean isTempFile(String fileName) { return fileName.indexOf(".java") != -1; } }