Skip to content

Commit

Permalink
Fixing Watch and Inline
Browse files Browse the repository at this point in the history
  • Loading branch information
aldrinleal committed Sep 13, 2013
1 parent 9ff9fed commit 76606eb
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 84 deletions.
6 changes: 3 additions & 3 deletions src/main/java/br/com/ingenieux/mojo/jbake/GenerateMojo.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package br.com.ingenieux.mojo.jbake;

/*
* Copyright 2001-2005 The Apache Software Foundation.
* Copyright 2013 ingenieux Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,13 +33,13 @@ public class GenerateMojo extends AbstractMojo {
* Location of the Output Directory.
*/
@Parameter(property = "jbake.outputDirectory", defaultValue = "${project.build.directory}/${project.build.finalName}", required = true)
private File outputDirectory;
protected File outputDirectory;

/**
* Location of the Output Directory.
*/
@Parameter(property = "jbake.inputDirectory", defaultValue = "${project.basedir}/src/main/jbake", required = true)
private File inputDirectory;
protected File inputDirectory;

public void execute() throws MojoExecutionException {
try {
Expand Down
91 changes: 10 additions & 81 deletions src/main/java/br/com/ingenieux/mojo/jbake/InlineMojo.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package br.com.ingenieux.mojo.jbake;

/*
* Copyright 2001-2005 The Apache Software Foundation.
* Copyright 2013 ingenieux Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,19 +16,8 @@
* limitations under the License.
*/

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
Expand All @@ -40,19 +29,7 @@
* Runs jbake on a folder while watching and serving a folder with it
*/
@Mojo(name = "inline", requiresDirectInvocation = true)
public class InlineMojo extends GenerateMojo {
/**
* Location of the Output Directory.
*/
@Parameter(property = "jbake.outputDirectory", defaultValue = "${project.build.directory}/${project.build.finalName}", required = true)
private File outputDirectory;

/**
* Location of the Output Directory.
*/
@Parameter(property = "jbake.inputDirectory", defaultValue = "${project.basedir}/src/main/jbake", required = true)
private File inputDirectory;

public class InlineMojo extends WatchMojo {
/**
* Listen Port
*/
Expand All @@ -65,71 +42,23 @@ public class InlineMojo extends GenerateMojo {
@Parameter(property = "jbake.port", defaultValue = "8080")
private Integer port;

public void execute() throws MojoExecutionException {
super.execute();

getLog().info("Now listening for changes on path " + inputDirectory.getPath());
protected Launcher launcher = null;

Map<String, String> args = new HashMap<String, String>();

Launcher launcher = null;
protected void stopServer() {
launcher.shutdown();
}

protected void initServer() throws MojoExecutionException {
try {
Map<String, String> args = new HashMap<String, String>();

args.put("webroot", outputDirectory.getAbsolutePath());
args.put("httpPort", port.toString());
args.put("httpListenAddress", listenAddress);

launcher = new Launcher(args);

final Path inPath = FileSystems.getDefault().getPath(
inputDirectory.getAbsolutePath());
final WatchService watchService = inPath.getFileSystem()
.newWatchService();

inPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE);

final AtomicBoolean done = new AtomicBoolean(false);
final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

(new Thread() {
@Override
public void run() {
try {
getLog().info("Running. Hit <ENTER> to finish");
reader.readLine();
} catch (Exception exc) {
} finally {
done.set(true);
}
}
}).run();

do {
WatchKey watchKey = watchService.take();
Thread.sleep(1000L);

if (watchKey.reset()) {
watchKey.cancel();
watchService.close();
return;
}

List<WatchEvent<?>> events = watchKey.pollEvents();

if (! events.isEmpty()) {
getLog().info("Refreshing");
super.execute();
}
} while (! done.get());
} catch (Exception exc) {
getLog().info("Oops", exc);

throw new MojoExecutionException("Oops", exc);
} finally {
getLog().info("Finishing");
launcher.shutdown();
throw new MojoExecutionException("Ooops", exc);
}
}
}
92 changes: 92 additions & 0 deletions src/main/java/br/com/ingenieux/mojo/jbake/WatchMojo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package br.com.ingenieux.mojo.jbake;

/*
* Copyright 2013 ingenieux Labs
*
* 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 java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;

import br.com.ingenieux.mojo.jbake.util.DirWatcher;

/**
* Runs jbake on a folder while watching for changes
*/
@Mojo(name = "watch", requiresDirectInvocation = true)
public class WatchMojo extends GenerateMojo {
public void execute() throws MojoExecutionException {
super.execute();

getLog().info(
"Now listening for changes on path " + inputDirectory.getPath());

initServer();

try {
final AtomicBoolean done = new AtomicBoolean(false);
final BufferedReader reader = new BufferedReader(
new InputStreamReader(System.in));

(new Thread() {
@Override
public void run() {
try {
getLog().info("Running. Hit <ENTER> to finish");
reader.readLine();
} catch (Exception exc) {
} finally {
done.set(true);
}
}
}).start();

DirWatcher dirWatcher = new DirWatcher(Paths.get(inputDirectory
.getPath()));

do {
Boolean result = dirWatcher.processEvents();

if (Boolean.FALSE.equals(result)) {
Thread.sleep(1000);
} else if (Boolean.TRUE.equals(result)) {
getLog().info("Refreshing");

super.execute();
} else if (null == result) {
break;
}
} while (!done.get());
} catch (Exception exc) {
getLog().info("Oops", exc);

throw new MojoExecutionException("Oops", exc);
} finally {
getLog().info("Finishing");

stopServer();
}
}

protected void stopServer() {
}

protected void initServer() throws MojoExecutionException {
}
}
146 changes: 146 additions & 0 deletions src/main/java/br/com/ingenieux/mojo/jbake/util/DirWatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package br.com.ingenieux.mojo.jbake.util;

import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
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.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* Example to watch a directory (or tree) for changes to files.
*/

public class DirWatcher {
private final WatchService watcher;

private final Map<WatchKey, Path> keys;

@SuppressWarnings("unchecked")
static <T> WatchEvent<T> cast(WatchEvent<?> event) {
return (WatchEvent<T>) event;
}

/**
* Register the given directory with the WatchService
*/
private void register(Path dir) throws IOException {
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE,
ENTRY_MODIFY);
// if (trace) {
// Path prev = keys.get(key);
// if (prev == null) {
// System.out.format("register: %s\n", dir);
// } else {
// if (!dir.equals(prev)) {
// System.out.format("update: %s -> %s\n", prev, dir);
// }
// }
// }
keys.put(key, dir);
}

/**
* Register the given directory, and all its sub-directories, with the
* WatchService.
*/
private void registerAll(final Path start) throws IOException {
// register directory and sub-directories
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
register(dir);
return FileVisitResult.CONTINUE;
}
});
}

/**
* Creates a WatchService and registers the given directory
*/
public DirWatcher(Path dir) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService();
this.keys = new HashMap<WatchKey, Path>();

registerAll(dir);
}

/**
* Process all events for keys queued to the watcher
*/
public Boolean processEvents() {
// wait for key to be signalled
WatchKey key;
try {
key = watcher.poll(1L, TimeUnit.SECONDS);
} catch (InterruptedException x) {
return Boolean.FALSE;
}

if (null == key)
return Boolean.FALSE;

Path dir = keys.get(key);
if (dir == null)
throw new IllegalStateException("WatchKey not recognized!!");

for (WatchEvent<?> event : key.pollEvents()) {
Kind<?> kind = event.kind();

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

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

// if directory is created, and watching recursively, then
// register it and its sub-directories
if (kind == ENTRY_CREATE) {
try {
if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
registerAll(child);
}
} catch (IOException x) {
// ignore to keep sample readbale
}
}
}

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

// all directories are inaccessible
if (keys.isEmpty()) {
return null;
}
}

return Boolean.TRUE;
}

static void usage() {
System.err.println("usage: java WatchDir [-r] dir");
System.exit(-1);
}
}

0 comments on commit 76606eb

Please sign in to comment.