This is an automated email from the ASF dual-hosted git repository. rmannibucau pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openwebbeans-meecrowave.git
commit 74fce22d8acd5314e75b20236f5b6c34e7925c56 Author: Romain Manni-Bucau <[email protected]> AuthorDate: Fri Aug 9 21:42:09 2019 +0200 MEECROWAVE-207 basic reload command in run mojo --- integration-tests/beanvalidation/pom.xml | 13 ++ .../main/jbake/content/meecrowave-maven/index.adoc | 8 ++ meecrowave-maven-plugin/pom.xml | 2 +- .../apache/meecrowave/maven/MeecrowaveRunMojo.java | 145 +++++++++++++++------ .../meecrowave/maven/MeecrowaveRunMojoTest.java | 6 +- 5 files changed, 134 insertions(+), 40 deletions(-) diff --git a/integration-tests/beanvalidation/pom.xml b/integration-tests/beanvalidation/pom.xml index 3d0c7a9..1c3323a 100644 --- a/integration-tests/beanvalidation/pom.xml +++ b/integration-tests/beanvalidation/pom.xml @@ -53,6 +53,19 @@ </dependency> </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.meecrowave</groupId> + <artifactId>meecrowave-maven-plugin</artifactId> + <version>${project.version}</version> + <configuration> + <scanningPackageIncludes>org.apache.meecrowave.beanvalidation</scanningPackageIncludes> + </configuration> + </plugin> + </plugins> + </build> + <profiles> <profile> <id>java11</id> diff --git a/meecrowave-doc/src/main/jbake/content/meecrowave-maven/index.adoc b/meecrowave-doc/src/main/jbake/content/meecrowave-maven/index.adoc index f82b7b2..132f99b 100755 --- a/meecrowave-doc/src/main/jbake/content/meecrowave-maven/index.adoc +++ b/meecrowave-doc/src/main/jbake/content/meecrowave-maven/index.adoc @@ -24,6 +24,14 @@ Here are the available options (see core configuration for the details): include::../../../../../target/generated-doc/MavenConfiguration.adoc[] +== Run + +`mvn meecrowave:run` enables you to start a server configured in your `pom.xml`. +Once started, you have a few commands you can use to interact with the server: + +- `quit`/`exit`: shutdown properly the server. +- `reload` (since 1.2.9): optionally relaunch a maven compilation - see configuration - and reload the web context. + == Bundling [source] diff --git a/meecrowave-maven-plugin/pom.xml b/meecrowave-maven-plugin/pom.xml index 73dc2cd..afc7dc8 100644 --- a/meecrowave-maven-plugin/pom.xml +++ b/meecrowave-maven-plugin/pom.xml @@ -30,7 +30,7 @@ <packaging>maven-plugin</packaging> <properties> - <maven.version>3.3.9</maven.version> + <maven.version>3.6.0</maven.version> <meecrowave.build.name>${project.groupId}.maven</meecrowave.build.name> </properties> diff --git a/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java b/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java index 427e2ff..0de0a53 100644 --- a/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java +++ b/meecrowave-maven-plugin/src/main/java/org/apache/meecrowave/maven/MeecrowaveRunMojo.java @@ -18,20 +18,14 @@ */ package org.apache.meecrowave.maven; -import org.apache.logging.log4j.LogManager; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.project.MavenProject; -import org.apache.meecrowave.Meecrowave; +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static java.util.Optional.ofNullable; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; +import static org.apache.maven.plugins.annotations.ResolutionScope.RUNTIME_PLUS_SYSTEM; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import javax.script.SimpleBindings; import java.io.File; import java.io.IOException; import java.io.StringReader; @@ -47,14 +41,25 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Scanner; +import java.util.function.Supplier; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static java.util.Optional.ofNullable; -import static java.util.function.Function.identity; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; -import static org.apache.maven.plugins.annotations.ResolutionScope.RUNTIME_PLUS_SYSTEM; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.script.SimpleBindings; + +import org.apache.catalina.Context; +import org.apache.logging.log4j.LogManager; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.lifecycle.internal.LifecycleStarter; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.meecrowave.Meecrowave; +import org.apache.meecrowave.tomcat.ProvidedLoader; @Mojo(name = "run", requiresDependencyResolution = RUNTIME_PLUS_SYSTEM) public class MeecrowaveRunMojo extends AbstractMojo { @@ -214,6 +219,9 @@ public class MeecrowaveRunMojo extends AbstractMojo { @Parameter(defaultValue = "${project.build.outputDirectory}") private List<File> modules; + @Parameter(defaultValue = "${session}", readonly = true) + private MavenSession session; + @Parameter(defaultValue = "${project}", readonly = true, required = true) private MavenProject project; @@ -299,6 +307,9 @@ public class MeecrowaveRunMojo extends AbstractMojo { @Parameter(property = "meecrowave.jaxws-support", defaultValue = "true") private boolean jaxwsSupportIfAvailable; + @Parameter(property = "meecrowave.reload-goals", defaultValue = "process-classes") + private List<String> reloadGoals; // todo: add watching on project.build.directory? + @Parameter(property = "meecrowave.default-ssl-hostconfig-name") private String defaultSSLHostConfigName; @@ -308,12 +319,17 @@ public class MeecrowaveRunMojo extends AbstractMojo { @Parameter(property = "meecrowave.session-cookie-config") private String webSessionCookieConfig; + @Component + private LifecycleStarter lifecycleStarter; + @Override - public void execute() throws MojoExecutionException, MojoFailureException { + public void execute() { if (skip) { getLog().warn("Mojo skipped"); return; } + logConfigurationErrors(); + final Map<String, String> originalSystemProps; if (systemProperties != null) { originalSystemProps = systemProperties.keySet().stream() @@ -326,8 +342,8 @@ public class MeecrowaveRunMojo extends AbstractMojo { final Thread thread = Thread.currentThread(); final ClassLoader loader = thread.getContextClassLoader(); - final ClassLoader appLoader = createClassLoader(loader); - thread.setContextClassLoader(appLoader); + final Supplier<ClassLoader> appLoaderSupplier = createClassLoader(loader); + thread.setContextClassLoader(appLoaderSupplier.get()); try { final Meecrowave.Builder builder = getConfig(); try (final Meecrowave meecrowave = new Meecrowave(builder) { @@ -344,24 +360,34 @@ public class MeecrowaveRunMojo extends AbstractMojo { jsContextCustomizer == null ? null : ctx -> scriptCustomization( singletonList(jsContextCustomizer), "js", singletonMap("context", ctx))); - if (useClasspathDeployment) { - meecrowave.deployClasspath(deploymentMeta); - } else { - meecrowave.deployWebapp(deploymentMeta); + deploy(meecrowave, deploymentMeta); + final Scanner scanner = new Scanner(System.in); + String cmd; + boolean quit = false; + while (!quit && (cmd = scanner.next()) != null) { + cmd = cmd.trim(); + switch (cmd) { + case "": // normally impossible with a Scanner but we can move to another "reader" + case "q": + case "quit": + case "e": + case "exit": + quit = true; + break; + case "r": + case "reload": + reload(meecrowave, fixedContext, appLoaderSupplier, loader); + break; + default: + getLog().error("Unknown command: '" + cmd + "', use 'quit' or 'exit' or 'reload'"); + } } - new Scanner(System.in).next(); } } finally { if (forceLog4j2Shutdown) { LogManager.shutdown(); } - if (appLoader != loader) { - try { - URLClassLoader.class.cast(appLoader).close(); - } catch (final IOException e) { - getLog().warn(e.getMessage(), e); - } - } + destroyTcclIfNeeded(thread, loader); thread.setContextClassLoader(loader); if (originalSystemProps != null) { systemProperties.keySet().forEach(k -> { @@ -376,6 +402,51 @@ public class MeecrowaveRunMojo extends AbstractMojo { } } + private void destroyTcclIfNeeded(final Thread thread, final ClassLoader loader) { + if (thread.getContextClassLoader() != loader) { + try { + URLClassLoader.class.cast(thread.getContextClassLoader()).close(); + } catch (final IOException e) { + getLog().warn(e.getMessage(), e); + } + } + } + + private void logConfigurationErrors() { + if (watcherBouncing > 0 && reloadGoals != null && !reloadGoals.isEmpty()) { + getLog().warn("You set reloadGoals and watcherBouncing > 1, behavior is undefined"); + } + } + + private void reload(final Meecrowave meecrowave, final String context, + final Supplier<ClassLoader> loaderSupplier, final ClassLoader mojoLoader) { + if (reloadGoals != null && !reloadGoals.isEmpty()) { + final List<String> goals = session.getGoals(); + session.getRequest().setGoals(reloadGoals); + try { + lifecycleStarter.execute(session); + } finally { + session.getRequest().setGoals(goals); + } + } + final Context ctx = Context.class.cast(meecrowave.getTomcat().getHost().findChild(context)); + if (useClasspathDeployment) { + final Thread thread = Thread.currentThread(); + destroyTcclIfNeeded(thread, mojoLoader); + thread.setContextClassLoader(loaderSupplier.get()); + ctx.setLoader(new ProvidedLoader(thread.getContextClassLoader(), meecrowave.getConfiguration().isTomcatWrapLoader())); + } + ctx.reload(); + } + + private void deploy(final Meecrowave meecrowave, final Meecrowave.DeploymentMeta deploymentMeta) { + if (useClasspathDeployment) { + meecrowave.deployClasspath(deploymentMeta); + } else { + meecrowave.deployWebapp(deploymentMeta); + } + } + private void scriptCustomization(final List<String> customizers, final String ext, final Map<String, Object> customBindings) { if (customizers == null || customizers.isEmpty()) { return; @@ -396,7 +467,7 @@ public class MeecrowaveRunMojo extends AbstractMojo { } } - private ClassLoader createClassLoader(final ClassLoader parent) { + private Supplier<ClassLoader> createClassLoader(final ClassLoader parent) { final List<URL> urls = new ArrayList<>(); urls.addAll(project.getArtifacts().stream() .filter(a -> !((applicationScopes == null && !(Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope()))) @@ -416,7 +487,7 @@ public class MeecrowaveRunMojo extends AbstractMojo { throw new IllegalArgumentException(e); } }).collect(toList())); - return urls.isEmpty() ? parent : new URLClassLoader(urls.toArray(new URL[urls.size()]), parent) { + return urls.isEmpty() ? () -> parent : () -> new URLClassLoader(urls.toArray(new URL[0]), parent) { @Override public boolean equals(final Object obj) { return super.equals(obj) || parent.equals(obj); diff --git a/meecrowave-maven-plugin/src/test/java/org/apache/meecrowave/maven/MeecrowaveRunMojoTest.java b/meecrowave-maven-plugin/src/test/java/org/apache/meecrowave/maven/MeecrowaveRunMojoTest.java index 730911f..84b2dc0 100644 --- a/meecrowave-maven-plugin/src/test/java/org/apache/meecrowave/maven/MeecrowaveRunMojoTest.java +++ b/meecrowave-maven-plugin/src/test/java/org/apache/meecrowave/maven/MeecrowaveRunMojoTest.java @@ -34,11 +34,13 @@ import org.eclipse.aether.repository.LocalRepository; import org.junit.Rule; import org.junit.Test; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -76,7 +78,7 @@ public class MeecrowaveRunMojoTest { final InputStream in = System.in; final CountDownLatch latch = new CountDownLatch(1); System.setIn(new InputStream() { - private int val = 2; // just to not return nothing + private final InputStream delegate = new ByteArrayInputStream("quit".getBytes(StandardCharsets.UTF_8)); @Override public int read() throws IOException { @@ -86,7 +88,7 @@ public class MeecrowaveRunMojoTest { Thread.currentThread().interrupt(); fail(e.getMessage()); } - return val--; + return delegate.read(); } }); final Thread runner = new Thread() {
