diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractForker.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractForker.java index 09313e7e3a9..28d1e4ebb64 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractForker.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractForker.java @@ -64,7 +64,9 @@ public abstract class AbstractForker extends AbstractLifeCycle protected File workDir; - + protected abstract ProcessBuilder createCommand(); + protected abstract void redeployWebApp() throws Exception; + public File getWorkDir() { return workDir; @@ -204,8 +206,6 @@ public abstract class AbstractForker extends AbstractLifeCycle { this.tokenFile = tokenFile; } - - public abstract ProcessBuilder createCommand(); public void doStart () diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractWebAppMojo.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractWebAppMojo.java index 8fa21e1b4a7..84617a0722c 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractWebAppMojo.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractWebAppMojo.java @@ -274,7 +274,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo * * */ - @Parameter (property="jetty.runType", defaultValue="INPROCESS") + @Parameter (property="jetty.runType", defaultValue="EMBED") protected RunTypes runType; @@ -462,7 +462,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo } - public void startJetty() + protected void startJetty() throws MojoExecutionException, MojoFailureException { try @@ -498,15 +498,15 @@ public abstract class AbstractWebAppMojo extends AbstractMojo } - public abstract void startJettyEmbedded() throws MojoExecutionException; + protected abstract void startJettyEmbedded() throws MojoExecutionException; - public abstract void startJettyForked() throws MojoExecutionException; + protected abstract void startJettyForked() throws MojoExecutionException; - public abstract void startJettyDistro() throws MojoExecutionException; + protected abstract void startJettyDistro() throws MojoExecutionException; - public JettyEmbedder newJettyEmbedder() + protected JettyEmbedder newJettyEmbedder() throws Exception { JettyEmbedder jetty = new JettyEmbedder(); @@ -531,8 +531,8 @@ public abstract class AbstractWebAppMojo extends AbstractMojo - public JettyForker newJettyForker() - throws Exception + protected JettyForker newJettyForker() + throws Exception { JettyForker jetty = new JettyForker(); @@ -564,7 +564,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo } - public JettyDistroForker newJettyDistroForker() + protected JettyDistroForker newJettyDistroForker() throws Exception { JettyDistroForker jetty = new JettyDistroForker(); @@ -605,10 +605,10 @@ public abstract class AbstractWebAppMojo extends AbstractMojo jetty.setLibExtJarFiles(libExtJars); } - jetty.setWebApp(webApp); + jetty.setWebApp(webApp); jetty.setContextXmlFile(new File(contextXml)); - if (jettyHome == null) + if (jettyHome == null) jetty.setJettyDistro(resolve(JETTY_HOME_GROUPID, JETTY_HOME_ARTIFACTID, plugin.getVersion(), "zip")); jetty.setJettyHome(jettyHome); @@ -658,7 +658,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo /** * @return */ - public List getProjectDependencyFiles() + private List getProjectDependencyFiles() { List dependencyFiles = new ArrayList<>(); for ( Iterator iter = projectArtifacts.iterator(); iter.hasNext(); ) @@ -693,7 +693,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo } - public MavenProject getProjectReferences( Artifact artifact, MavenProject project ) + private MavenProject getProjectReferences( Artifact artifact, MavenProject project ) { if ( project.getProjectReferences() == null || project.getProjectReferences().isEmpty() ) { @@ -710,7 +710,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo return null; } - public List getOverlays() + protected List getOverlays() throws Exception { //get copy of a list of war artifacts @@ -756,7 +756,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo } - public void unpackOverlays (List overlays) + private void unpackOverlays (List overlays) throws Exception { if (overlays == null || overlays.isEmpty()) @@ -795,7 +795,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo - public Resource unpackOverlay (Overlay overlay) + private Resource unpackOverlay (Overlay overlay) throws IOException { if (overlay.getResource() == null) @@ -834,7 +834,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo /** * @return */ - public List getWarArtifacts () + protected List getWarArtifacts () { if (warArtifacts != null) return warArtifacts; @@ -859,7 +859,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo return warArtifacts; } - protected Artifact getArtifactForOverlay (OverlayConfig o, List warArtifacts) + private Artifact getArtifactForOverlay (OverlayConfig o, List warArtifacts) { if (o == null || warArtifacts == null || warArtifacts.isEmpty()) return null; @@ -881,7 +881,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo * * */ - public void verifyPomConfiguration () throws MojoExecutionException + protected void verifyPomConfiguration () throws MojoExecutionException { // check the location of the static content/jsps etc try @@ -930,7 +930,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo } - public void configureSystemProperties () + protected void configureSystemProperties () throws MojoExecutionException { //Apply the file first @@ -954,6 +954,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo { for (Map.Entry e:systemProperties.entrySet()) { + System.err.println(e.getKey() + " " + e.getValue()); System.setProperty(e.getKey(), e.getValue()); } } @@ -965,7 +966,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo * * @throws MojoExecutionException */ - public void augmentPluginClasspath() throws MojoExecutionException + protected void augmentPluginClasspath() throws MojoExecutionException { //Filter out ones that will clash with jars that are plugin dependencies, then //create a new classloader that we setup in the parent chain. @@ -990,7 +991,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo } } - public List getProvidedJars() throws MojoExecutionException + protected List getProvidedJars() throws MojoExecutionException { //if we are configured to include the provided dependencies on the plugin's classpath //(which mimics being on jetty's classpath vs being on the webapp's classpath), we first @@ -1011,7 +1012,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo return null; } - public String getContainerClassPath() throws Exception + protected String getContainerClassPath() throws Exception { //Add in all the plugin artifacts StringBuilder classPath = new StringBuilder(); @@ -1053,7 +1054,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo * @param artifact to check * @return true if it is a plugin dependency, false otherwise */ - public boolean isPluginArtifact(Artifact artifact) + protected boolean isPluginArtifact(Artifact artifact) { if (pluginArtifacts == null || pluginArtifacts.isEmpty()) return false; @@ -1076,7 +1077,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo * @param goal the goal to check * @return true if the goal is excluded, false otherwise */ - public boolean isExcludedGoal (String goal) + protected boolean isExcludedGoal (String goal) { if (excludedGoals == null || goal == null) return false; @@ -1096,7 +1097,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo } - public void configureWebApp () + protected void configureWebApp () throws Exception { if (webApp == null) @@ -1207,7 +1208,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo * @param webInfDir the web inf directory * @return the jetty web xml file */ - public File findJettyWebXmlFile (File webInfDir) + protected File findJettyWebXmlFile (File webInfDir) { if (webInfDir == null) return null; diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/ConsoleReader.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/ConsoleReader.java new file mode 100644 index 00000000000..d3800ebb069 --- /dev/null +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/ConsoleReader.java @@ -0,0 +1,69 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + + +package org.eclipse.jetty.maven.plugin; + +import java.io.Console; +import java.util.EventListener; +import java.util.HashSet; +import java.util.Set; + + +public class ConsoleReader implements Runnable +{ + + public interface Listener extends EventListener + { + public void consoleEvent (String line); + } + + public Set listeners = new HashSet<>(); + + public void addListener(ConsoleReader.Listener listener) + { + listeners.add(listener); + } + + public void removeListener(ConsoleReader.Listener listener) + { + listeners.remove(listener); + } + + public void run() + { + Console console = System.console(); + if (console == null) + return; + + String line =""; + while (true && line != null) + { + line = console.readLine("Hit to redeploy:"); + if (line != null) + signalEvent(line); + } + } + + + public void signalEvent(String line) + { + for (ConsoleReader.Listener l:listeners) + l.consoleEvent(line); + } +} \ No newline at end of file diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyDistroForker.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyDistroForker.java index 167c85e30da..83311b7bf36 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyDistroForker.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyDistroForker.java @@ -45,6 +45,9 @@ import org.eclipse.jetty.util.resource.Resource; /** * JettyDistroForker + * + * Unpacks a jetty distribution and configures it with a base that allows it + * to run an unassembled webapp. * */ public class JettyDistroForker extends AbstractForker @@ -59,7 +62,6 @@ public class JettyDistroForker extends AbstractForker */ protected File jettyHome; - /** * Zip of jetty distro */ @@ -68,25 +70,17 @@ public class JettyDistroForker extends AbstractForker /** * Location of existing jetty base directory */ - protected File jettyBase; - - - - + protected File baseDir; - /** * Optional list of other modules to * activate. */ - protected String[] modules; - - protected List libExtJarFiles; - + protected List libExtJarFiles; protected Path modulesPath; protected Path etcPath; protected Path libPath; @@ -155,31 +149,6 @@ public class JettyDistroForker extends AbstractForker this.jettyDistro = jettyDistro; } - public void configureJettyHome () - throws Exception - { - if (jettyHome == null && jettyDistro == null) - throw new IllegalStateException ("No jettyDistro"); - - if (baseDir == null) - throw new IllegalStateException ("No baseDir"); - - if (jettyHome == null) - { - JarResource res = (JarResource) JarResource.newJarResource(Resource.newResource(jettyDistro)); - res.copyTo(baseDir); - //zip will unpack to target/jetty-home- - String name = jettyDistro.getName(); - int i = name.lastIndexOf('.'); - name = (i>0?name.substring(0, i):"distro"); - jettyHome = new File (baseDir, name); - - System.err.println("JETTY HOME = "+jettyHome); - } - } - - - public JettyWebAppContext getWebApp() { return webApp; @@ -204,7 +173,7 @@ public class JettyDistroForker extends AbstractForker * @see org.eclipse.jetty.maven.plugin.AbstractForker#createCommand() */ @Override - public ProcessBuilder createCommand() + protected ProcessBuilder createCommand() { List cmd = new ArrayList<>(); cmd.add("java"); @@ -288,20 +257,31 @@ public class JettyDistroForker extends AbstractForker configureJettyBase(); //convert the webapp to properties - WebAppPropertyConverter.toProperties(webApp, etcPath.resolve("maven.props").toFile(), contextXmlFile.getAbsolutePath()); + generateWebAppPropertiesFile(); super.doStart(); } - - - + + protected void redeployWebApp() + throws Exception + { + generateWebAppPropertiesFile(); + webappPath.resolve("maven.xml").toFile().setLastModified(System.currentTimeMillis()); + } + + private void generateWebAppPropertiesFile() + throws Exception + { + WebAppPropertyConverter.toProperties(webApp, etcPath.resolve("maven.props").toFile(), contextXmlFile.getAbsolutePath()); + } + /** * Create or configure a jetty base. * * @throws Exception */ - public void configureJettyBase() throws Exception + private void configureJettyBase() throws Exception { if (jettyBase != null && !jettyBase.exists()) throw new IllegalStateException(jettyBase.getAbsolutePath() +" does not exist"); @@ -315,7 +295,7 @@ public class JettyDistroForker extends AbstractForker //jetty-base will be the working directory for the forked command workDir = targetJettyBase; - + //if there is an existing jetty base, copy parts of it if (jettyBase != null) { @@ -413,4 +393,27 @@ public class JettyDistroForker extends AbstractForker } } } + + private void configureJettyHome () + throws Exception + { + if (jettyHome == null && jettyDistro == null) + throw new IllegalStateException ("No jettyDistro"); + + if (baseDir == null) + throw new IllegalStateException ("No baseDir"); + + if (jettyHome == null) + { + JarResource res = (JarResource) JarResource.newJarResource(Resource.newResource(jettyDistro)); + res.copyTo(baseDir); + //zip will unpack to target/jetty-home- + String name = jettyDistro.getName(); + int i = name.lastIndexOf('.'); + name = (i>0?name.substring(0, i):"distro"); + jettyHome = new File (baseDir, name); + + System.err.println("JETTY HOME = "+jettyHome); + } + } } diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEmbedder.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEmbedder.java index 0c13cef7c35..f394af62c60 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEmbedder.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEmbedder.java @@ -82,175 +82,137 @@ public class JettyEmbedder extends AbstractLifeCycle return contextHandlers; } - public void setContextHandlers(ContextHandler[] contextHandlers) { this.contextHandlers = contextHandlers; } - public LoginService[] getLoginServices() { return loginServices; } - public void setLoginServices(LoginService[] loginServices) { this.loginServices = loginServices; } - public RequestLog getRequestLog() { return requestLog; } - public void setRequestLog(RequestLog requestLog) { this.requestLog = requestLog; } - public MavenServerConnector getHttpConnector() { return httpConnector; } - public void setHttpConnector(MavenServerConnector httpConnector) { this.httpConnector = httpConnector; } - public Server getServer() { return server; } - public void setServer(Server server) { this.server = server; } - public JettyWebAppContext getWebApp() { return webApp; } - public boolean isExitVm() { return exitVm; } - public void setExitVm(boolean exitVm) { this.exitVm = exitVm; } - public boolean isStopAtShutdown() { return stopAtShutdown; } - public void setStopAtShutdown(boolean stopAtShutdown) { this.stopAtShutdown = stopAtShutdown; } - public List getJettyXmlFiles() { return jettyXmlFiles; } - public void setJettyXmlFiles(List jettyXmlFiles) { this.jettyXmlFiles = jettyXmlFiles; } - - - public Map getJettyProperties() { return jettyProperties; } - - - public void setJettyProperties(Map jettyProperties) { this.jettyProperties = jettyProperties; } - - - public ShutdownMonitor getShutdownMonitor() { return shutdownMonitor; } - - - public void setShutdownMonitor(ShutdownMonitor shutdownMonitor) { this.shutdownMonitor = shutdownMonitor; } - - - public int getStopPort() { return stopPort; } - - - public void setStopPort(int stopPort) { this.stopPort = stopPort; } - - - public String getStopKey() { return stopKey; } - - - public void setStopKey(String stopKey) { this.stopKey = stopKey; } - - - public Properties getWebAppProperties() { return webAppProperties; } - - + + public void setWebApp (JettyWebAppContext app, Properties properties) + throws Exception + { + webApp = app; + webAppProperties = properties; + } public void doStart() throws Exception @@ -266,14 +228,22 @@ public class JettyEmbedder extends AbstractLifeCycle server.start(); } - public void join() + protected void redeployWebApp() + throws Exception + { + webApp.stop(); + //regenerate config properties + applyWebAppProperties(); + webApp.start(); + } + + protected void join() throws InterruptedException { server.join(); } - /** * Configure the server and the webapp * @throws Exception @@ -304,14 +274,13 @@ public class JettyEmbedder extends AbstractLifeCycle // set up security realms ServerSupport.configureLoginServices(server, loginServices); - + /* Configure the webapp */ if (webApp == null) webApp = new JettyWebAppContext(); - - //apply properties to the webapp if there are any - WebAppPropertyConverter.fromProperties(webApp, webAppProperties, server, jettyProperties); - + + applyWebAppProperties(); + //TODO- this might be duplicating WebAppPropertyConverter. make it a quickstart if the quickstart-web.xml file exists if (webApp.getTempDirectory() != null) { @@ -319,22 +288,19 @@ public class JettyEmbedder extends AbstractLifeCycle if (qs.exists() && qs.isFile()) webApp.setQuickStartWebDescriptor(Resource.newResource(qs)); } - + //add the webapp to the server ServerSupport.addWebApplication(server, webApp); System.err.println("ADDED WEBAPP TO SERVER"); } - - public void setWebApp (JettyWebAppContext app, Properties properties) - throws Exception + private void applyWebAppProperties () throws Exception { - webApp = app; - webAppProperties = properties; + //apply properties to the webapp if there are any + WebAppPropertyConverter.fromProperties(webApp, webAppProperties, server, jettyProperties); } - - + private void configureShutdownMonitor () { if(stopPort>0 && stopKey!=null) diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyForkedChild.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyForkedChild.java index cce39cd9871..14fb3ac22ad 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyForkedChild.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyForkedChild.java @@ -21,14 +21,21 @@ package org.eclipse.jetty.maven.plugin; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Properties; +import org.eclipse.jetty.util.PathWatcher; +import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; /** @@ -39,8 +46,12 @@ import org.eclipse.jetty.util.resource.Resource; */ public class JettyForkedChild extends AbstractLifeCycle { + private static final Logger LOG = Log.getLogger(JettyForkedChild.class); + protected JettyEmbedder jetty; protected File tokenFile; + protected PathWatcher scanner; + protected File webAppPropsFile; public JettyForkedChild (String[] args) throws Exception @@ -89,10 +100,8 @@ public class JettyForkedChild extends AbstractLifeCycle //--webprops if ("--webprops".equals(args[i])) { - File webAppPropsFile = new File(args[++i].trim()); - Properties props = new Properties(); - props.load(new FileInputStream(webAppPropsFile)); - jetty.setWebApp(null, props); + webAppPropsFile = new File(args[++i].trim()); + jetty.setWebApp(null, loadWebAppProps()); System.err.println("WEBPROPS="+webAppPropsFile); continue; } @@ -114,10 +123,18 @@ public class JettyForkedChild extends AbstractLifeCycle jettyProperties.put(tmp[0], tmp[1]); } } - + jetty.setJettyProperties(jettyProperties); jetty.setExitVm(true); } + + private Properties loadWebAppProps () throws FileNotFoundException, IOException + { + Properties props = new Properties(); + if (Objects.nonNull(webAppPropsFile)) + props.load(new FileInputStream(webAppPropsFile)); + return props; + } public void doStart() throws Exception @@ -131,13 +148,49 @@ public class JettyForkedChild extends AbstractLifeCycle Resource r = Resource.newResource(tokenFile); r.getFile().createNewFile(); - //TODO start a PathWatcher for the webapp props file and/or the quickstart.xml file - // when differences are seen, get the webapp from the jettyembedder: - // stop webapp - // reconfigure the properties on it - // (name of quickstart file can't change, but contents can, but we don't need to do anything here) - // start webapp + //Start a watcher on a file that will change if the + //webapp is regenerated; stop the webapp, apply the + //properties and restart it. + scanner = new PathWatcher(); + scanner.setNotifyExistingOnStart(false); + scanner.addListener(new PathWatcher.EventListListener() + { + @Override + public void onPathWatchEvents(List events) + { + if (!Objects.isNull(scanner)) + { + try + { + scanner.stop(); + if (!Objects.isNull(jetty.getWebApp())) + { + //stop the webapp + jetty.getWebApp().stop(); + //reload the props + jetty.setWebApp(jetty.getWebApp(), loadWebAppProps()); + + //restart the webapp + jetty.getWebApp().start(); + + //restart the scanner + scanner.start(); + } + } + catch (Exception e) + { + LOG.warn("Error restarting webapp", e); + } + } + } + }); + + if (!Objects.isNull(webAppPropsFile)) + scanner.watch(webAppPropsFile.toPath()); + + + scanner.start(); //wait for jetty to finish jetty.join(); diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyForker.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyForker.java index 356c0eaf63a..ab60655fb6c 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyForker.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyForker.java @@ -43,6 +43,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool; /** * JettyForker * + * Uses quickstart to generate a webapp and forks a process to run it. */ public class JettyForker extends AbstractForker { @@ -121,20 +122,14 @@ public class JettyForker extends AbstractForker throws Exception { //Run the webapp to create the quickstart file and properties file - generateQuickStart(); + prepareWebApp(); super.doStart(); } - protected void generateQuickStart() + private void prepareWebApp() throws Exception { - if (forkWebXml == null) - throw new IllegalStateException ("No forkWebXml"); - - if (webAppPropsFile == null) - throw new IllegalStateException ("no webAppsPropsFile"); - if (server == null) server = new Server(); @@ -163,26 +158,52 @@ public class JettyForker extends AbstractForker //add webapp to our fake server instance ServerSupport.addWebApplication(server, webApp); + + //leave everything unpacked for the forked process to use + webApp.setPersistTempDirectory(true); + + generateQuickStart(); + } + + protected void redeployWebApp () + throws Exception + { + //regenerating the quickstart will be noticed by the JettyForkedChild process + //which will redeploy the webapp + generateQuickStart(); + } + + private void generateQuickStart() + throws Exception + { + if (forkWebXml == null) + throw new IllegalStateException ("No forkWebXml"); + + if (webAppPropsFile == null) + throw new IllegalStateException ("no webAppsPropsFile"); //if our server has a thread pool associated we can do annotation scanning multithreaded, //otherwise scanning will be single threaded QueuedThreadPool tpool = server.getBean(QueuedThreadPool.class); - if (tpool != null) - tpool.start(); - else - webApp.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE.toString()); - //leave everything unpacked for the forked process to use - webApp.setPersistTempDirectory(true); + try + { + if (tpool != null) + tpool.start(); + else + webApp.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE.toString()); - webApp.start(); //just enough to generate the quickstart + webApp.start(); //just enough to generate the quickstart - //save config of the webapp BEFORE we stop - WebAppPropertyConverter.toProperties(webApp, webAppPropsFile, webAppProperties.getProperty("context.xml")); - - webApp.stop(); - if (tpool != null) - tpool.stop(); + //save config of the webapp BEFORE we stop + WebAppPropertyConverter.toProperties(webApp, webAppPropsFile, webAppProperties.getProperty("context.xml")); + } + finally + { + webApp.stop(); + if (tpool != null) + tpool.stop(); + } } diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/NewJettyRunMojo.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/NewJettyRunMojo.java index 0c23c8a35eb..a24ca2bdf75 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/NewJettyRunMojo.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/NewJettyRunMojo.java @@ -19,13 +19,9 @@ package org.eclipse.jetty.maven.plugin; -import java.io.Console; import java.io.File; import java.util.Date; -import java.util.EventListener; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; @@ -35,6 +31,7 @@ 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.eclipse.jetty.maven.plugin.ConsoleReader; import org.eclipse.jetty.util.PathWatcher; import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; import org.eclipse.jetty.util.resource.Resource; @@ -59,8 +56,6 @@ import org.eclipse.jetty.webapp.WebAppContext; @Execute (phase = LifecyclePhase.TEST_COMPILE) public class NewJettyRunMojo extends AbstractWebAppMojo { - - //Start of parameters only valid for runType=inprocess /** * The interval in seconds to pause before checking if changes @@ -75,105 +70,34 @@ public class NewJettyRunMojo extends AbstractWebAppMojo * Scanner to check for files changes to cause redeploy */ protected PathWatcher scanner; + + /** + * Only one of the following will be used, depending the mode + * the mojo is started in: EMBED, FORK, DISTRO + */ + protected JettyEmbedder embedder; + protected JettyForker forker; + protected JettyDistroForker distroForker; - - - public static class ConsoleReader implements Runnable - { - - public interface Listener extends EventListener - { - public void consoleEvent (String line); - } - - public Set listeners = new HashSet<>(); - - public void addListener(Listener listener) - { - listeners.add(listener); - } - - public void removeListener(Listener listener) - { - listeners.remove(listener); - } - - public void run() - { - Console console = System.console(); - if (console == null) - return; - - String line =""; - while (true && line != null) - { - line = console.readLine("Hit to redeploy:"); - if (line != null) - signalEvent(line); - } - } - - - public void signalEvent(String line) - { - for (Listener l:listeners) - l.consoleEvent(line); - } - } - @Override public void execute() throws MojoExecutionException, MojoFailureException { super.execute(); } - - - - @Override public void startJettyEmbedded() throws MojoExecutionException { try { //start jetty - JettyEmbedder jetty = newJettyEmbedder(); - jetty.setExitVm(true); - jetty.setStopAtShutdown(true); - jetty.start(); - - // start scanning for changes, or wait for linefeed on stdin - if (scan > 0) - { - scanner = new PathWatcher(); - configureScanner (); - scanner.setNotifyExistingOnStart(false); - scanner.start(); - } - else - { - ConsoleReader creader = new ConsoleReader(); - creader.addListener(new ConsoleReader.Listener() - { - @Override - public void consoleEvent(String line) - { - try - { - restartWebApp(false); - } - catch (Exception e) - { - getLog().debug(e); - } - } - }); - Thread cthread = new Thread(creader, "ConsoleReader"); - cthread.setDaemon(true); - cthread.start(); - } - jetty.join(); + embedder = newJettyEmbedder(); + embedder.setExitVm(true); + embedder.setStopAtShutdown(true); + embedder.start(); + startScanner(); + embedder.join(); } catch (Exception e) { @@ -181,20 +105,19 @@ public class NewJettyRunMojo extends AbstractWebAppMojo } } - - - - - - @Override public void startJettyForked() throws MojoExecutionException { try { - JettyForker jetty = newJettyForker(); - jetty.setWaitForChild(true); //we run at the command line, echo child output and wait for it - jetty.start(); //forks jetty instance + forker = newJettyForker(); + forker.setWaitForChild(true); //we run at the command line, echo child output and wait for it + + startScanner(); + + //TODO is it ok to start the scanner before we start jetty? + + forker.start(); //forks jetty instance } catch (Exception e) @@ -203,18 +126,17 @@ public class NewJettyRunMojo extends AbstractWebAppMojo } } - - - - @Override public void startJettyDistro() throws MojoExecutionException { try { - JettyDistroForker jetty = newJettyDistroForker(); - jetty.setWaitForChild(true); //we always run at the command line, echo child output and wait for it - jetty.start(); //forks a jetty distro + distroForker = newJettyDistroForker(); + distroForker.setWaitForChild(true); //we always run at the command line, echo child output and wait for it + startScanner(); + distroForker.start(); //forks a jetty distro + + //TODO is it ok to start the scanner before we start jetty? } catch (Exception e) { @@ -222,9 +144,42 @@ public class NewJettyRunMojo extends AbstractWebAppMojo } } + private void startScanner () + throws Exception + { + // start scanning for changes, or wait for linefeed on stdin + if (scan > 0) + { + scanner = new PathWatcher(); + configureScanner (); + scanner.setNotifyExistingOnStart(false); + scanner.start(); + } + else + { + ConsoleReader creader = new ConsoleReader(); + creader.addListener(new ConsoleReader.Listener() + { + @Override + public void consoleEvent(String line) + { + try + { + restartWebApp(false); + } + catch (Exception e) + { + getLog().debug(e); + } + } + }); + Thread cthread = new Thread(creader, "ConsoleReader"); + cthread.setDaemon(true); + cthread.start(); + } + } - - public void configureScanner () + protected void configureScanner () throws MojoExecutionException { try @@ -238,7 +193,6 @@ public class NewJettyRunMojo extends AbstractWebAppMojo scanner.addListener(new PathWatcher.EventListListener() { - @Override public void onPathWatchEvents(List events) { @@ -382,7 +336,7 @@ public class NewJettyRunMojo extends AbstractWebAppMojo /** * @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#restartWebApp(boolean) */ - public void restartWebApp(boolean reconfigureScanner) throws Exception + public void restartWebApp(boolean reconfigure) throws Exception { getLog().info("Restarting "+webApp); getLog().debug("Stopping webapp ..."); @@ -393,15 +347,12 @@ public class NewJettyRunMojo extends AbstractWebAppMojo { case EMBED: { - webApp.stop(); - getLog().debug("Reconfiguring webapp ..."); verifyPomConfiguration(); - configureWebApp(); // check if we need to reconfigure the scanner, // which is if the pom changes - if (reconfigureScanner) + if (reconfigure) { getLog().info("Reconfiguring scanner after change to pom.xml ..."); scanner.reset(); @@ -409,28 +360,27 @@ public class NewJettyRunMojo extends AbstractWebAppMojo configureScanner(); } - webApp.start(); + configureWebApp(); + embedder.redeployWebApp(); scanner.start(); getLog().info("Restart completed at "+new Date().toString()); + break; } case FORK: { verifyPomConfiguration(); - - //TODO regenerate the webapp configuration!!!!!! - - - if (reconfigureScanner) + if (reconfigure) { getLog().info("Reconfiguring scanner after change to pom.xml ..."); scanner.reset(); - warArtifacts = null; + warArtifacts = null; ///TODO if the pom changes for the forked case, how would we get the forked process to stop and restart? configureScanner(); } - //TODO signal to forked child to restart webapp (done by regenerating webapp - + configureWebApp(); + //regenerate with new config and restart the webapp + forker.redeployWebApp(); //restart scanner scanner.start(); @@ -439,19 +389,17 @@ public class NewJettyRunMojo extends AbstractWebAppMojo case DISTRO: { verifyPomConfiguration(); - - //TODO regenerate the webapp configuration!!!!!! - - if (reconfigureScanner) + if (reconfigure) { getLog().info("Reconfiguring scanner after change to pom.xml ..."); scanner.reset(); - warArtifacts = null; //??? + warArtifacts = null; //TODO if there are any changes to the pom, then we would have to tell the + //existing forked distro process to stop, then rerun the configuration and then refork - too complicated??! configureScanner(); } - - //TODO signal to distro to restart webapp (done by regenerating webapp???!) - + configureWebApp(); + //regenerate the webapp and redeploy it + distroForker.redeployWebApp(); //restart scanner scanner.start(); diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/NewJettyRunWarMojo.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/NewJettyRunWarMojo.java index 7638d257f7d..7a7362f7150 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/NewJettyRunWarMojo.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/NewJettyRunWarMojo.java @@ -19,18 +19,15 @@ package org.eclipse.jetty.maven.plugin; -import java.io.Console; import java.io.File; -import java.util.EventListener; -import java.util.HashSet; +import java.util.Date; import java.util.List; -import java.util.Set; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Execute; +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.LifecyclePhase; import org.apache.maven.plugins.annotations.ResolutionScope; import org.eclipse.jetty.util.PathWatcher; import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; @@ -48,7 +45,7 @@ import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; *

* Runs jetty on a war file */ -@Mojo( name = "run-war", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) +@Mojo( name = "newrun-war", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) @Execute(phase = LifecyclePhase.PACKAGE) public class NewJettyRunWarMojo extends AbstractWebAppMojo { @@ -74,52 +71,9 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo * Scanner to check for files changes to cause redeploy */ protected PathWatcher scanner; - - - - - public static class ConsoleReader implements Runnable - { - - public interface Listener extends EventListener - { - public void consoleEvent (String line); - } - - public Set listeners = new HashSet<>(); - - public void addListener(Listener listener) - { - listeners.add(listener); - } - - public void removeListener(Listener listener) - { - listeners.remove(listener); - } - - public void run() - { - Console console = System.console(); - if (console == null) - return; - - String line =""; - while (true && line != null) - { - line = console.readLine("Hit to redeploy:"); - if (line != null) - signalEvent(line); - } - } - - - public void signalEvent(String line) - { - for (Listener l:listeners) - l.consoleEvent(line); - } - } + protected JettyEmbedder embedder; + protected JettyForker forker; + protected JettyDistroForker distroForker; /** @@ -131,8 +85,6 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo { return null; } - - @Override public void configureWebApp() throws Exception @@ -141,9 +93,7 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo webApp.setWar(war.getCanonicalPath()); } - - - /* (non-Javadoc) + /** * */ @Override @@ -152,42 +102,14 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo try { //start jetty - JettyEmbedder jetty = newJettyEmbedder(); - jetty.setExitVm(true); - jetty.setStopAtShutdown(true); - jetty.start(); + embedder = newJettyEmbedder(); + embedder.setExitVm(true); + embedder.setStopAtShutdown(true); + embedder.start(); - // start scanning for changes, or wait for linefeed on stdin - if (scan > 0) - { - scanner = new PathWatcher(); - configureScanner (); - scanner.setNotifyExistingOnStart(false); - scanner.start(); - } - else - { - ConsoleReader creader = new ConsoleReader(); - creader.addListener(new ConsoleReader.Listener() - { - @Override - public void consoleEvent(String line) - { - try - { - restartWebApp(false); - } - catch (Exception e) - { - getLog().debug(e); - } - } - }); - Thread cthread = new Thread(creader, "ConsoleReader"); - cthread.setDaemon(true); - cthread.start(); - } - jetty.join(); + + + embedder.join(); } catch (Exception e) { @@ -195,24 +117,85 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo } } - /* (non-Javadoc) - * + public void startScanner() + throws Exception + { + // start scanning for changes, or wait for linefeed on stdin + if (scan > 0) + { + scanner = new PathWatcher(); + configureScanner (); + scanner.setNotifyExistingOnStart(false); + scanner.start(); + } + else + { + ConsoleReader creader = new ConsoleReader(); + creader.addListener(new ConsoleReader.Listener() + { + @Override + public void consoleEvent(String line) + { + try + { + restartWebApp(false); + } + catch (Exception e) + { + getLog().debug(e); + } + } + }); + Thread cthread = new Thread(creader, "ConsoleReader"); + cthread.setDaemon(true); + cthread.start(); + } + } + + /** + * Fork a jetty instance to run the war */ @Override public void startJettyForked() throws MojoExecutionException { - // TODO Auto-generated method stub + try + { + forker = newJettyForker(); + forker.setWaitForChild(true); //we run at the command line, echo child output and wait for it + startScanner(); + + //TODO is it ok to start the scanner before we start jetty? + + forker.start(); //forks jetty instance + + } + catch (Exception e) + { + throw new MojoExecutionException("Error starting jetty", e); + } } - /* (non-Javadoc) + /** * */ @Override public void startJettyDistro() throws MojoExecutionException { - // TODO Auto-generated method stub + try + { + distroForker = newJettyDistroForker(); + distroForker.setWaitForChild(true); //we always run at the command line, echo child output and wait for it + startScanner(); + distroForker.start(); //forks a jetty distro + + //TODO is it ok to start the scanner before we start jetty? + } + catch (Exception e) + { + throw new MojoExecutionException("Error starting jetty", e); + } } public void configureScanner() throws MojoExecutionException @@ -222,7 +205,6 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo scanner.addListener(new PathWatcher.EventListListener() { - @Override public void onPathWatchEvents(List events) { @@ -247,32 +229,81 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo }); } - public void restartWebApp(boolean reconfigureScanner) throws Exception + public void restartWebApp(boolean reconfigure) throws Exception { getLog().info("Restarting webapp ..."); - getLog().debug("Stopping webapp ..."); + getLog().debug("Stopping scanner ..."); if (scanner != null) scanner.stop(); - webApp.stop(); - getLog().debug("Reconfiguring webapp ..."); - - verifyPomConfiguration(); - configureWebApp(); - // check if we need to reconfigure the scanner, - // which is if the pom changes - if (reconfigureScanner) + switch (runType) { - getLog().info("Reconfiguring scanner after change to pom.xml ..."); - scanner.reset(); - warArtifacts = null; //?????????? TODO - configureScanner(); - } + case EMBED: + { + getLog().debug("Reconfiguring webapp ..."); + + verifyPomConfiguration(); + // check if we need to reconfigure the scanner, + // which is if the pom changes + if (reconfigure) + { + getLog().info("Reconfiguring scanner after change to pom.xml ..."); + scanner.reset(); + warArtifacts = null; + configureScanner(); + } + + configureWebApp(); + embedder.redeployWebApp(); + scanner.start(); + getLog().info("Restart completed at "+new Date().toString()); + + break; + } + case FORK: + { + verifyPomConfiguration(); + if (reconfigure) + { + getLog().info("Reconfiguring scanner after change to pom.xml ..."); + scanner.reset(); + warArtifacts = null; ///TODO if the pom changes for the forked case, how would we get the forked process to stop and restart? + configureScanner(); + } + + configureWebApp(); + //regenerate with new config and restart the webapp + forker.redeployWebApp(); + //restart scanner + scanner.start(); + + break; + } + case DISTRO: + { + verifyPomConfiguration(); + if (reconfigure) + { + getLog().info("Reconfiguring scanner after change to pom.xml ..."); + scanner.reset(); + warArtifacts = null; //TODO if there are any changes to the pom, then we would have to tell the + //existing forked distro process to stop, then rerun the configuration and then refork - too complicated??! + configureScanner(); + } + configureWebApp(); + //regenerate the webapp and redeploy it + distroForker.redeployWebApp(); + //restart scanner + scanner.start(); - getLog().debug("Restarting webapp ..."); - webApp.start(); - scanner.start(); + break; + } + default: + { + throw new IllegalStateException("Unrecognized run type "+runType); + } + } getLog().info("Restart completed."); } - + } diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/WebAppPropertyConverter.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/WebAppPropertyConverter.java index 7753901ce16..4672fff8f03 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/WebAppPropertyConverter.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/WebAppPropertyConverter.java @@ -164,6 +164,9 @@ public class WebAppPropertyConverter { if (webApp == null) throw new IllegalArgumentException("No webapp"); + + if (webAppProperties == null) + return; String str = webAppProperties.getProperty("context.path"); if (!StringUtil.isBlank(str))