/** * Copyright (C) 2012-2015 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 io.mangoo.maven; import java.io.File; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import io.mangoo.build.Runner; import io.mangoo.build.Trigger; import io.mangoo.build.Watcher; import io.mangoo.core.Application; import io.mangoo.utils.MinificationUtils; /** * This is a refactored version of * NinjaRunMojo.java from the Ninja Web Framework * * Original source code can be found here: * https://github.com/ninjaframework/ninja/blob/develop/ninja-maven-plugin/src/main/java/ninja/maven/NinjaRunMojo.java * * @author svenkubiak * */ @Mojo(name = "run", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, defaultPhase = LifecyclePhase.NONE, threadSafe = true) public class MangooMojo extends AbstractMojo { private static final String [] DEFAULT_EXCLUDE_PATTERNS = { "(.*)" + Pattern.quote(File.separator) + "templates" + Pattern.quote(File.separator) + "(.*)ftl", "(.*)less", "(.*)sass", "(.*)" + Pattern.quote(File.separator) + "assets" + Pattern.quote(File.separator) + "(.*)" }; @Parameter(defaultValue = "${project}", readonly = true) protected MavenProject project; @Parameter(property = "mangoo.skip", defaultValue="false", required = true) private boolean skip; @Parameter(property = "mangoo.jpdaPort", defaultValue="8000", required = true) private int jpdaPort; @Parameter(property = "mangoo.jvmArgs", required = false) private String jvmArgs; @Parameter(property = "mangoo.outputDirectory", defaultValue = "${project.build.outputDirectory}", required = true) private String buildOutputDirectory; @Parameter(property = "mangoo.watchDirs", required = false) private File[] watchDirs; @Parameter(property = "mangoo.watchAllClassPathDirs", defaultValue = "false", required = true) private boolean watchAllClassPathDirs; @Parameter(property = "mangoo.watchAllClassPathJars", defaultValue = "false", required = true) private boolean watchAllClassPathJars; @Parameter(property = "mangoo.includes", required = false) protected List<String> includes; @Parameter(property = "mangoo.excludes", required = false) private List<String> excludes; @Parameter(property = "mangoo.useDefaultExcludes", defaultValue = "true", required = true) protected boolean useDefaultExcludes; @Parameter(property = "mangoo.settleDownMillis", defaultValue="500", required = false) private Long settleDownMillis; @Override public void execute() throws MojoExecutionException { if (skip) { getLog().info("Skip flag is on. Will not execute."); return; } initMojo(); checkClasses(buildOutputDirectory); MinificationUtils.setBasePath(project.getBasedir().getAbsolutePath()); List<String> classpathItems = new ArrayList<>(); classpathItems.add(buildOutputDirectory); for (Artifact artifact: project.getArtifacts()) { classpathItems.add(artifact.getFile().toString()); } Set<String> includesSet = new LinkedHashSet<>(includes); Set<String> excludesSet = new LinkedHashSet<>(excludes); Set<Path> watchDirectories = new LinkedHashSet<>(); FileSystem fileSystem = FileSystems.getDefault(); watchDirectories.add(fileSystem.getPath(buildOutputDirectory).toAbsolutePath()); if (this.watchDirs != null) { for (File watchDir: this.watchDirs) { watchDirectories.add(watchDir.toPath().toAbsolutePath()); } } getArtifacts(includesSet, excludesSet, watchDirectories); startRunner(classpathItems, includesSet, excludesSet, watchDirectories); IOUtils.closeQuietly(fileSystem); } private void startRunner(List<String> classpathItems, Set<String> includesSet, Set<String> excludesSet, Set<Path> watchDirectories) { try { Runner machine = new Runner( Application.class.getName(), StringUtils.join(classpathItems, File.pathSeparator), project.getBasedir(), jpdaPort, jvmArgs); Trigger restartTrigger = new Trigger(machine); restartTrigger.setSettleDownMillis(settleDownMillis); restartTrigger.start(); Watcher watcher = new Watcher( watchDirectories, includesSet, excludesSet, restartTrigger); machine.restart(); watcher.run(); //NOSONAR } catch (IOException e) { getLog().error(e); } } private void getArtifacts(Set<String> includesSet, Set<String> excludesSet, Set<Path> watchDirectories) { for (Artifact artifact : project.getArtifacts()) { File file = artifact.getFile(); if (this.watchAllClassPathDirs && file.isDirectory()) { watchDirectories.add(file.toPath().toAbsolutePath()); } else if (file.getName().endsWith(".jar") && this.watchAllClassPathJars) { File parentDir = file.getParentFile(); Path parentPath = parentDir.toPath().toAbsolutePath(); String rulePrefix = parentDir.getAbsolutePath() + File.separator; rulePrefix = rulePrefix.replace("\\", "\\\\"); if (!watchDirectories.contains(parentPath)) { excludesSet.add(rulePrefix + "(.*)$"); } includesSet.add(rulePrefix + file.getName() + "$"); watchDirectories.add(parentPath); } } } private void initMojo() { if (useDefaultExcludes) { excludes.addAll(Arrays.asList(DEFAULT_EXCLUDE_PATTERNS)); } } @SuppressWarnings("all") public void checkClasses(String classesDirectory) { if (!new File(classesDirectory).exists()) { getLog().error("Directory with classes does not exist: " + classesDirectory); System.exit(1); //NOSONAR } } }