Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
Jan Bartel 2019-07-13 17:36:15 +02:00
parent 60d20c8808
commit 464f3d3e66
10 changed files with 509 additions and 414 deletions

View File

@ -64,6 +64,8 @@ public abstract class AbstractForker extends AbstractLifeCycle
protected File workDir; protected File workDir;
protected abstract ProcessBuilder createCommand();
protected abstract void redeployWebApp() throws Exception;
public File getWorkDir() public File getWorkDir()
{ {
@ -205,8 +207,6 @@ public abstract class AbstractForker extends AbstractLifeCycle
this.tokenFile = tokenFile; this.tokenFile = tokenFile;
} }
public abstract ProcessBuilder createCommand();
public void doStart () public void doStart ()
throws Exception throws Exception

View File

@ -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; protected RunTypes runType;
@ -462,7 +462,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
} }
public void startJetty() protected void startJetty()
throws MojoExecutionException, MojoFailureException throws MojoExecutionException, MojoFailureException
{ {
try 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 throws Exception
{ {
JettyEmbedder jetty = new JettyEmbedder(); JettyEmbedder jetty = new JettyEmbedder();
@ -531,8 +531,8 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
public JettyForker newJettyForker() protected JettyForker newJettyForker()
throws Exception throws Exception
{ {
JettyForker jetty = new JettyForker(); JettyForker jetty = new JettyForker();
@ -564,7 +564,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
} }
public JettyDistroForker newJettyDistroForker() protected JettyDistroForker newJettyDistroForker()
throws Exception throws Exception
{ {
JettyDistroForker jetty = new JettyDistroForker(); JettyDistroForker jetty = new JettyDistroForker();
@ -658,7 +658,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
/** /**
* @return * @return
*/ */
public List<File> getProjectDependencyFiles() private List<File> getProjectDependencyFiles()
{ {
List<File> dependencyFiles = new ArrayList<>(); List<File> dependencyFiles = new ArrayList<>();
for ( Iterator<Artifact> iter = projectArtifacts.iterator(); iter.hasNext(); ) for ( Iterator<Artifact> 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() ) if ( project.getProjectReferences() == null || project.getProjectReferences().isEmpty() )
{ {
@ -710,7 +710,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
return null; return null;
} }
public List<Overlay> getOverlays() protected List<Overlay> getOverlays()
throws Exception throws Exception
{ {
//get copy of a list of war artifacts //get copy of a list of war artifacts
@ -756,7 +756,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
} }
public void unpackOverlays (List<Overlay> overlays) private void unpackOverlays (List<Overlay> overlays)
throws Exception throws Exception
{ {
if (overlays == null || overlays.isEmpty()) 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 throws IOException
{ {
if (overlay.getResource() == null) if (overlay.getResource() == null)
@ -834,7 +834,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
/** /**
* @return * @return
*/ */
public List<Artifact> getWarArtifacts () protected List<Artifact> getWarArtifacts ()
{ {
if (warArtifacts != null) if (warArtifacts != null)
return warArtifacts; return warArtifacts;
@ -859,7 +859,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
return warArtifacts; return warArtifacts;
} }
protected Artifact getArtifactForOverlay (OverlayConfig o, List<Artifact> warArtifacts) private Artifact getArtifactForOverlay (OverlayConfig o, List<Artifact> warArtifacts)
{ {
if (o == null || warArtifacts == null || warArtifacts.isEmpty()) if (o == null || warArtifacts == null || warArtifacts.isEmpty())
return null; 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 // check the location of the static content/jsps etc
try try
@ -930,7 +930,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
} }
public void configureSystemProperties () protected void configureSystemProperties ()
throws MojoExecutionException throws MojoExecutionException
{ {
//Apply the file first //Apply the file first
@ -954,6 +954,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
{ {
for (Map.Entry<String, String> e:systemProperties.entrySet()) for (Map.Entry<String, String> e:systemProperties.entrySet())
{ {
System.err.println(e.getKey() + " " + e.getValue());
System.setProperty(e.getKey(), e.getValue()); System.setProperty(e.getKey(), e.getValue());
} }
} }
@ -965,7 +966,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
* *
* @throws MojoExecutionException * @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 //Filter out ones that will clash with jars that are plugin dependencies, then
//create a new classloader that we setup in the parent chain. //create a new classloader that we setup in the parent chain.
@ -990,7 +991,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
} }
} }
public List<File> getProvidedJars() throws MojoExecutionException protected List<File> getProvidedJars() throws MojoExecutionException
{ {
//if we are configured to include the provided dependencies on the plugin's classpath //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 //(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; return null;
} }
public String getContainerClassPath() throws Exception protected String getContainerClassPath() throws Exception
{ {
//Add in all the plugin artifacts //Add in all the plugin artifacts
StringBuilder classPath = new StringBuilder(); StringBuilder classPath = new StringBuilder();
@ -1053,7 +1054,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
* @param artifact to check * @param artifact to check
* @return true if it is a plugin dependency, false otherwise * @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()) if (pluginArtifacts == null || pluginArtifacts.isEmpty())
return false; return false;
@ -1076,7 +1077,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
* @param goal the goal to check * @param goal the goal to check
* @return true if the goal is excluded, false otherwise * @return true if the goal is excluded, false otherwise
*/ */
public boolean isExcludedGoal (String goal) protected boolean isExcludedGoal (String goal)
{ {
if (excludedGoals == null || goal == null) if (excludedGoals == null || goal == null)
return false; return false;
@ -1096,7 +1097,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
} }
public void configureWebApp () protected void configureWebApp ()
throws Exception throws Exception
{ {
if (webApp == null) if (webApp == null)
@ -1207,7 +1208,7 @@ public abstract class AbstractWebAppMojo extends AbstractMojo
* @param webInfDir the web inf directory * @param webInfDir the web inf directory
* @return the jetty web xml file * @return the jetty web xml file
*/ */
public File findJettyWebXmlFile (File webInfDir) protected File findJettyWebXmlFile (File webInfDir)
{ {
if (webInfDir == null) if (webInfDir == null)
return null; return null;

View File

@ -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<ConsoleReader.Listener> 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 <enter> to redeploy:");
if (line != null)
signalEvent(line);
}
}
public void signalEvent(String line)
{
for (ConsoleReader.Listener l:listeners)
l.consoleEvent(line);
}
}

View File

@ -46,6 +46,9 @@ import org.eclipse.jetty.util.resource.Resource;
/** /**
* JettyDistroForker * JettyDistroForker
* *
* Unpacks a jetty distribution and configures it with a base that allows it
* to run an unassembled webapp.
*
*/ */
public class JettyDistroForker extends AbstractForker public class JettyDistroForker extends AbstractForker
{ {
@ -59,7 +62,6 @@ public class JettyDistroForker extends AbstractForker
*/ */
protected File jettyHome; protected File jettyHome;
/** /**
* Zip of jetty distro * Zip of jetty distro
*/ */
@ -68,25 +70,17 @@ public class JettyDistroForker extends AbstractForker
/** /**
* Location of existing jetty base directory * Location of existing jetty base directory
*/ */
protected File jettyBase; protected File jettyBase;
protected File baseDir; protected File baseDir;
/** /**
* Optional list of other modules to * Optional list of other modules to
* activate. * activate.
*/ */
protected String[] modules; protected String[] modules;
protected List<File> libExtJarFiles; protected List<File> libExtJarFiles;
protected Path modulesPath; protected Path modulesPath;
protected Path etcPath; protected Path etcPath;
protected Path libPath; protected Path libPath;
@ -155,31 +149,6 @@ public class JettyDistroForker extends AbstractForker
this.jettyDistro = jettyDistro; 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-<VERSION>
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() public JettyWebAppContext getWebApp()
{ {
return webApp; return webApp;
@ -204,7 +173,7 @@ public class JettyDistroForker extends AbstractForker
* @see org.eclipse.jetty.maven.plugin.AbstractForker#createCommand() * @see org.eclipse.jetty.maven.plugin.AbstractForker#createCommand()
*/ */
@Override @Override
public ProcessBuilder createCommand() protected ProcessBuilder createCommand()
{ {
List<String> cmd = new ArrayList<>(); List<String> cmd = new ArrayList<>();
cmd.add("java"); cmd.add("java");
@ -288,12 +257,23 @@ public class JettyDistroForker extends AbstractForker
configureJettyBase(); configureJettyBase();
//convert the webapp to properties //convert the webapp to properties
WebAppPropertyConverter.toProperties(webApp, etcPath.resolve("maven.props").toFile(), contextXmlFile.getAbsolutePath()); generateWebAppPropertiesFile();
super.doStart(); 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());
}
/** /**
@ -301,7 +281,7 @@ public class JettyDistroForker extends AbstractForker
* *
* @throws Exception * @throws Exception
*/ */
public void configureJettyBase() throws Exception private void configureJettyBase() throws Exception
{ {
if (jettyBase != null && !jettyBase.exists()) if (jettyBase != null && !jettyBase.exists())
throw new IllegalStateException(jettyBase.getAbsolutePath() +" does not exist"); throw new IllegalStateException(jettyBase.getAbsolutePath() +" does not exist");
@ -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-<VERSION>
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);
}
}
} }

View File

@ -82,175 +82,137 @@ public class JettyEmbedder extends AbstractLifeCycle
return contextHandlers; return contextHandlers;
} }
public void setContextHandlers(ContextHandler[] contextHandlers) public void setContextHandlers(ContextHandler[] contextHandlers)
{ {
this.contextHandlers = contextHandlers; this.contextHandlers = contextHandlers;
} }
public LoginService[] getLoginServices() public LoginService[] getLoginServices()
{ {
return loginServices; return loginServices;
} }
public void setLoginServices(LoginService[] loginServices) public void setLoginServices(LoginService[] loginServices)
{ {
this.loginServices = loginServices; this.loginServices = loginServices;
} }
public RequestLog getRequestLog() public RequestLog getRequestLog()
{ {
return requestLog; return requestLog;
} }
public void setRequestLog(RequestLog requestLog) public void setRequestLog(RequestLog requestLog)
{ {
this.requestLog = requestLog; this.requestLog = requestLog;
} }
public MavenServerConnector getHttpConnector() public MavenServerConnector getHttpConnector()
{ {
return httpConnector; return httpConnector;
} }
public void setHttpConnector(MavenServerConnector httpConnector) public void setHttpConnector(MavenServerConnector httpConnector)
{ {
this.httpConnector = httpConnector; this.httpConnector = httpConnector;
} }
public Server getServer() public Server getServer()
{ {
return server; return server;
} }
public void setServer(Server server) public void setServer(Server server)
{ {
this.server = server; this.server = server;
} }
public JettyWebAppContext getWebApp() public JettyWebAppContext getWebApp()
{ {
return webApp; return webApp;
} }
public boolean isExitVm() public boolean isExitVm()
{ {
return exitVm; return exitVm;
} }
public void setExitVm(boolean exitVm) public void setExitVm(boolean exitVm)
{ {
this.exitVm = exitVm; this.exitVm = exitVm;
} }
public boolean isStopAtShutdown() public boolean isStopAtShutdown()
{ {
return stopAtShutdown; return stopAtShutdown;
} }
public void setStopAtShutdown(boolean stopAtShutdown) public void setStopAtShutdown(boolean stopAtShutdown)
{ {
this.stopAtShutdown = stopAtShutdown; this.stopAtShutdown = stopAtShutdown;
} }
public List<File> getJettyXmlFiles() public List<File> getJettyXmlFiles()
{ {
return jettyXmlFiles; return jettyXmlFiles;
} }
public void setJettyXmlFiles(List<File> jettyXmlFiles) public void setJettyXmlFiles(List<File> jettyXmlFiles)
{ {
this.jettyXmlFiles = jettyXmlFiles; this.jettyXmlFiles = jettyXmlFiles;
} }
public Map<String, String> getJettyProperties() public Map<String, String> getJettyProperties()
{ {
return jettyProperties; return jettyProperties;
} }
public void setJettyProperties(Map<String, String> jettyProperties) public void setJettyProperties(Map<String, String> jettyProperties)
{ {
this.jettyProperties = jettyProperties; this.jettyProperties = jettyProperties;
} }
public ShutdownMonitor getShutdownMonitor() public ShutdownMonitor getShutdownMonitor()
{ {
return shutdownMonitor; return shutdownMonitor;
} }
public void setShutdownMonitor(ShutdownMonitor shutdownMonitor) public void setShutdownMonitor(ShutdownMonitor shutdownMonitor)
{ {
this.shutdownMonitor = shutdownMonitor; this.shutdownMonitor = shutdownMonitor;
} }
public int getStopPort() public int getStopPort()
{ {
return stopPort; return stopPort;
} }
public void setStopPort(int stopPort) public void setStopPort(int stopPort)
{ {
this.stopPort = stopPort; this.stopPort = stopPort;
} }
public String getStopKey() public String getStopKey()
{ {
return stopKey; return stopKey;
} }
public void setStopKey(String stopKey) public void setStopKey(String stopKey)
{ {
this.stopKey = stopKey; this.stopKey = stopKey;
} }
public Properties getWebAppProperties() public Properties getWebAppProperties()
{ {
return webAppProperties; return webAppProperties;
} }
public void setWebApp (JettyWebAppContext app, Properties properties)
throws Exception
{
webApp = app;
webAppProperties = properties;
}
public void doStart() public void doStart()
throws Exception throws Exception
@ -266,14 +228,22 @@ public class JettyEmbedder extends AbstractLifeCycle
server.start(); server.start();
} }
public void join() protected void redeployWebApp()
throws Exception
{
webApp.stop();
//regenerate config properties
applyWebAppProperties();
webApp.start();
}
protected void join()
throws InterruptedException throws InterruptedException
{ {
server.join(); server.join();
} }
/** /**
* Configure the server and the webapp * Configure the server and the webapp
* @throws Exception * @throws Exception
@ -309,8 +279,7 @@ public class JettyEmbedder extends AbstractLifeCycle
if (webApp == null) if (webApp == null)
webApp = new JettyWebAppContext(); webApp = new JettyWebAppContext();
//apply properties to the webapp if there are any applyWebAppProperties();
WebAppPropertyConverter.fromProperties(webApp, webAppProperties, server, jettyProperties);
//TODO- this might be duplicating WebAppPropertyConverter. make it a quickstart if the quickstart-web.xml file exists //TODO- this might be duplicating WebAppPropertyConverter. make it a quickstart if the quickstart-web.xml file exists
if (webApp.getTempDirectory() != null) if (webApp.getTempDirectory() != null)
@ -326,15 +295,12 @@ public class JettyEmbedder extends AbstractLifeCycle
System.err.println("ADDED WEBAPP TO SERVER"); System.err.println("ADDED WEBAPP TO SERVER");
} }
private void applyWebAppProperties () throws Exception
public void setWebApp (JettyWebAppContext app, Properties properties)
throws Exception
{ {
webApp = app; //apply properties to the webapp if there are any
webAppProperties = properties; WebAppPropertyConverter.fromProperties(webApp, webAppProperties, server, jettyProperties);
} }
private void configureShutdownMonitor () private void configureShutdownMonitor ()
{ {
if(stopPort>0 && stopKey!=null) if(stopPort>0 && stopKey!=null)

View File

@ -21,14 +21,21 @@ package org.eclipse.jetty.maven.plugin;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Properties; 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.StringUtil;
import org.eclipse.jetty.util.component.AbstractLifeCycle; 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; import org.eclipse.jetty.util.resource.Resource;
/** /**
@ -39,8 +46,12 @@ import org.eclipse.jetty.util.resource.Resource;
*/ */
public class JettyForkedChild extends AbstractLifeCycle public class JettyForkedChild extends AbstractLifeCycle
{ {
private static final Logger LOG = Log.getLogger(JettyForkedChild.class);
protected JettyEmbedder jetty; protected JettyEmbedder jetty;
protected File tokenFile; protected File tokenFile;
protected PathWatcher scanner;
protected File webAppPropsFile;
public JettyForkedChild (String[] args) public JettyForkedChild (String[] args)
throws Exception throws Exception
@ -89,10 +100,8 @@ public class JettyForkedChild extends AbstractLifeCycle
//--webprops //--webprops
if ("--webprops".equals(args[i])) if ("--webprops".equals(args[i]))
{ {
File webAppPropsFile = new File(args[++i].trim()); webAppPropsFile = new File(args[++i].trim());
Properties props = new Properties(); jetty.setWebApp(null, loadWebAppProps());
props.load(new FileInputStream(webAppPropsFile));
jetty.setWebApp(null, props);
System.err.println("WEBPROPS="+webAppPropsFile); System.err.println("WEBPROPS="+webAppPropsFile);
continue; continue;
} }
@ -119,6 +128,14 @@ public class JettyForkedChild extends AbstractLifeCycle
jetty.setExitVm(true); 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() public void doStart()
throws Exception throws Exception
{ {
@ -131,13 +148,49 @@ public class JettyForkedChild extends AbstractLifeCycle
Resource r = Resource.newResource(tokenFile); Resource r = Resource.newResource(tokenFile);
r.getFile().createNewFile(); r.getFile().createNewFile();
//TODO start a PathWatcher for the webapp props file and/or the quickstart.xml file //Start a watcher on a file that will change if the
// when differences are seen, get the webapp from the jettyembedder: //webapp is regenerated; stop the webapp, apply the
// stop webapp //properties and restart it.
// reconfigure the properties on it scanner = new PathWatcher();
// (name of quickstart file can't change, but contents can, but we don't need to do anything here) scanner.setNotifyExistingOnStart(false);
// start webapp scanner.addListener(new PathWatcher.EventListListener()
{
@Override
public void onPathWatchEvents(List<PathWatchEvent> 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 //wait for jetty to finish
jetty.join(); jetty.join();

View File

@ -43,6 +43,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
/** /**
* JettyForker * JettyForker
* *
* Uses quickstart to generate a webapp and forks a process to run it.
*/ */
public class JettyForker extends AbstractForker public class JettyForker extends AbstractForker
{ {
@ -121,20 +122,14 @@ public class JettyForker extends AbstractForker
throws Exception throws Exception
{ {
//Run the webapp to create the quickstart file and properties file //Run the webapp to create the quickstart file and properties file
generateQuickStart(); prepareWebApp();
super.doStart(); super.doStart();
} }
protected void generateQuickStart() private void prepareWebApp()
throws Exception throws Exception
{ {
if (forkWebXml == null)
throw new IllegalStateException ("No forkWebXml");
if (webAppPropsFile == null)
throw new IllegalStateException ("no webAppsPropsFile");
if (server == null) if (server == null)
server = new Server(); server = new Server();
@ -164,25 +159,51 @@ public class JettyForker extends AbstractForker
//add webapp to our fake server instance //add webapp to our fake server instance
ServerSupport.addWebApplication(server, webApp); ServerSupport.addWebApplication(server, webApp);
//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 //leave everything unpacked for the forked process to use
webApp.setPersistTempDirectory(true); webApp.setPersistTempDirectory(true);
webApp.start(); //just enough to generate the quickstart generateQuickStart();
}
//save config of the webapp BEFORE we stop protected void redeployWebApp ()
WebAppPropertyConverter.toProperties(webApp, webAppPropsFile, webAppProperties.getProperty("context.xml")); throws Exception
{
//regenerating the quickstart will be noticed by the JettyForkedChild process
//which will redeploy the webapp
generateQuickStart();
}
webApp.stop(); private void generateQuickStart()
if (tpool != null) throws Exception
tpool.stop(); {
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);
try
{
if (tpool != null)
tpool.start();
else
webApp.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE.toString());
webApp.start(); //just enough to generate the quickstart
//save config of the webapp BEFORE we stop
WebAppPropertyConverter.toProperties(webApp, webAppPropsFile, webAppProperties.getProperty("context.xml"));
}
finally
{
webApp.stop();
if (tpool != null)
tpool.stop();
}
} }

View File

@ -19,13 +19,9 @@
package org.eclipse.jetty.maven.plugin; package org.eclipse.jetty.maven.plugin;
import java.io.Console;
import java.io.File; import java.io.File;
import java.util.Date; import java.util.Date;
import java.util.EventListener;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException; 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.Mojo;
import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope; 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;
import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; import org.eclipse.jetty.util.PathWatcher.PathWatchEvent;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
@ -59,8 +56,6 @@ import org.eclipse.jetty.webapp.WebAppContext;
@Execute (phase = LifecyclePhase.TEST_COMPILE) @Execute (phase = LifecyclePhase.TEST_COMPILE)
public class NewJettyRunMojo extends AbstractWebAppMojo public class NewJettyRunMojo extends AbstractWebAppMojo
{ {
//Start of parameters only valid for runType=inprocess //Start of parameters only valid for runType=inprocess
/** /**
* The interval in seconds to pause before checking if changes * The interval in seconds to pause before checking if changes
@ -76,104 +71,33 @@ public class NewJettyRunMojo extends AbstractWebAppMojo
*/ */
protected PathWatcher scanner; 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<Listener> 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 <enter> to redeploy:");
if (line != null)
signalEvent(line);
}
}
public void signalEvent(String line)
{
for (Listener l:listeners)
l.consoleEvent(line);
}
}
@Override @Override
public void execute() throws MojoExecutionException, MojoFailureException public void execute() throws MojoExecutionException, MojoFailureException
{ {
super.execute(); super.execute();
} }
@Override @Override
public void startJettyEmbedded() throws MojoExecutionException public void startJettyEmbedded() throws MojoExecutionException
{ {
try try
{ {
//start jetty //start jetty
JettyEmbedder jetty = newJettyEmbedder(); embedder = newJettyEmbedder();
jetty.setExitVm(true); embedder.setExitVm(true);
jetty.setStopAtShutdown(true); embedder.setStopAtShutdown(true);
jetty.start(); embedder.start();
startScanner();
// start scanning for changes, or wait for linefeed on stdin embedder.join();
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();
} }
catch (Exception e) catch (Exception e)
{ {
@ -181,20 +105,19 @@ public class NewJettyRunMojo extends AbstractWebAppMojo
} }
} }
@Override @Override
public void startJettyForked() throws MojoExecutionException public void startJettyForked() throws MojoExecutionException
{ {
try try
{ {
JettyForker jetty = newJettyForker(); forker = newJettyForker();
jetty.setWaitForChild(true); //we run at the command line, echo child output and wait for it forker.setWaitForChild(true); //we run at the command line, echo child output and wait for it
jetty.start(); //forks jetty instance
startScanner();
//TODO is it ok to start the scanner before we start jetty?
forker.start(); //forks jetty instance
} }
catch (Exception e) catch (Exception e)
@ -203,18 +126,17 @@ public class NewJettyRunMojo extends AbstractWebAppMojo
} }
} }
@Override @Override
public void startJettyDistro() throws MojoExecutionException public void startJettyDistro() throws MojoExecutionException
{ {
try try
{ {
JettyDistroForker jetty = newJettyDistroForker(); distroForker = newJettyDistroForker();
jetty.setWaitForChild(true); //we always run at the command line, echo child output and wait for it distroForker.setWaitForChild(true); //we always run at the command line, echo child output and wait for it
jetty.start(); //forks a jetty distro startScanner();
distroForker.start(); //forks a jetty distro
//TODO is it ok to start the scanner before we start jetty?
} }
catch (Exception e) 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();
}
}
protected void configureScanner ()
public void configureScanner ()
throws MojoExecutionException throws MojoExecutionException
{ {
try try
@ -238,7 +193,6 @@ public class NewJettyRunMojo extends AbstractWebAppMojo
scanner.addListener(new PathWatcher.EventListListener() scanner.addListener(new PathWatcher.EventListListener()
{ {
@Override @Override
public void onPathWatchEvents(List<PathWatchEvent> events) public void onPathWatchEvents(List<PathWatchEvent> events)
{ {
@ -382,7 +336,7 @@ public class NewJettyRunMojo extends AbstractWebAppMojo
/** /**
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#restartWebApp(boolean) * @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().info("Restarting "+webApp);
getLog().debug("Stopping webapp ..."); getLog().debug("Stopping webapp ...");
@ -393,15 +347,12 @@ public class NewJettyRunMojo extends AbstractWebAppMojo
{ {
case EMBED: case EMBED:
{ {
webApp.stop();
getLog().debug("Reconfiguring webapp ..."); getLog().debug("Reconfiguring webapp ...");
verifyPomConfiguration(); verifyPomConfiguration();
configureWebApp();
// check if we need to reconfigure the scanner, // check if we need to reconfigure the scanner,
// which is if the pom changes // which is if the pom changes
if (reconfigureScanner) if (reconfigure)
{ {
getLog().info("Reconfiguring scanner after change to pom.xml ..."); getLog().info("Reconfiguring scanner after change to pom.xml ...");
scanner.reset(); scanner.reset();
@ -409,28 +360,27 @@ public class NewJettyRunMojo extends AbstractWebAppMojo
configureScanner(); configureScanner();
} }
webApp.start(); configureWebApp();
embedder.redeployWebApp();
scanner.start(); scanner.start();
getLog().info("Restart completed at "+new Date().toString()); getLog().info("Restart completed at "+new Date().toString());
break; break;
} }
case FORK: case FORK:
{ {
verifyPomConfiguration(); verifyPomConfiguration();
if (reconfigure)
//TODO regenerate the webapp configuration!!!!!!
if (reconfigureScanner)
{ {
getLog().info("Reconfiguring scanner after change to pom.xml ..."); getLog().info("Reconfiguring scanner after change to pom.xml ...");
scanner.reset(); 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(); 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 //restart scanner
scanner.start(); scanner.start();
@ -439,19 +389,17 @@ public class NewJettyRunMojo extends AbstractWebAppMojo
case DISTRO: case DISTRO:
{ {
verifyPomConfiguration(); verifyPomConfiguration();
if (reconfigure)
//TODO regenerate the webapp configuration!!!!!!
if (reconfigureScanner)
{ {
getLog().info("Reconfiguring scanner after change to pom.xml ..."); getLog().info("Reconfiguring scanner after change to pom.xml ...");
scanner.reset(); 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(); configureScanner();
} }
configureWebApp();
//TODO signal to distro to restart webapp (done by regenerating webapp???!) //regenerate the webapp and redeploy it
distroForker.redeployWebApp();
//restart scanner //restart scanner
scanner.start(); scanner.start();

View File

@ -19,18 +19,15 @@
package org.eclipse.jetty.maven.plugin; package org.eclipse.jetty.maven.plugin;
import java.io.Console;
import java.io.File; import java.io.File;
import java.util.EventListener; import java.util.Date;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Execute; 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.Mojo;
import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.plugins.annotations.ResolutionScope;
import org.eclipse.jetty.util.PathWatcher; import org.eclipse.jetty.util.PathWatcher;
import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; import org.eclipse.jetty.util.PathWatcher.PathWatchEvent;
@ -48,7 +45,7 @@ import org.eclipse.jetty.util.PathWatcher.PathWatchEvent;
* </p> * </p>
* Runs jetty on a war file * 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) @Execute(phase = LifecyclePhase.PACKAGE)
public class NewJettyRunWarMojo extends AbstractWebAppMojo public class NewJettyRunWarMojo extends AbstractWebAppMojo
{ {
@ -74,52 +71,9 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo
* Scanner to check for files changes to cause redeploy * Scanner to check for files changes to cause redeploy
*/ */
protected PathWatcher scanner; protected PathWatcher scanner;
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<Listener> 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 <enter> to redeploy:");
if (line != null)
signalEvent(line);
}
}
public void signalEvent(String line)
{
for (Listener l:listeners)
l.consoleEvent(line);
}
}
/** /**
@ -132,8 +86,6 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo
return null; return null;
} }
@Override @Override
public void configureWebApp() throws Exception public void configureWebApp() throws Exception
{ {
@ -141,9 +93,7 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo
webApp.setWar(war.getCanonicalPath()); webApp.setWar(war.getCanonicalPath());
} }
/**
/* (non-Javadoc)
* *
*/ */
@Override @Override
@ -152,42 +102,14 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo
try try
{ {
//start jetty //start jetty
JettyEmbedder jetty = newJettyEmbedder(); embedder = newJettyEmbedder();
jetty.setExitVm(true); embedder.setExitVm(true);
jetty.setStopAtShutdown(true); embedder.setStopAtShutdown(true);
jetty.start(); embedder.start();
// start scanning for changes, or wait for linefeed on stdin
if (scan > 0)
{ embedder.join();
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();
} }
catch (Exception e) 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 @Override
public void startJettyForked() throws MojoExecutionException 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 @Override
public void startJettyDistro() throws MojoExecutionException 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 public void configureScanner() throws MojoExecutionException
@ -222,7 +205,6 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo
scanner.addListener(new PathWatcher.EventListListener() scanner.addListener(new PathWatcher.EventListListener()
{ {
@Override @Override
public void onPathWatchEvents(List<PathWatchEvent> events) public void onPathWatchEvents(List<PathWatchEvent> events)
{ {
@ -247,31 +229,80 @@ public class NewJettyRunWarMojo extends AbstractWebAppMojo
}); });
} }
public void restartWebApp(boolean reconfigureScanner) throws Exception public void restartWebApp(boolean reconfigure) throws Exception
{ {
getLog().info("Restarting webapp ..."); getLog().info("Restarting webapp ...");
getLog().debug("Stopping webapp ..."); getLog().debug("Stopping scanner ...");
if (scanner != null) if (scanner != null)
scanner.stop(); scanner.stop();
webApp.stop();
getLog().debug("Reconfiguring webapp ...");
verifyPomConfiguration(); switch (runType)
configureWebApp();
// check if we need to reconfigure the scanner,
// which is if the pom changes
if (reconfigureScanner)
{ {
getLog().info("Reconfiguring scanner after change to pom.xml ..."); case EMBED:
scanner.reset(); {
warArtifacts = null; //?????????? TODO getLog().debug("Reconfiguring webapp ...");
configureScanner();
}
getLog().debug("Restarting webapp ..."); verifyPomConfiguration();
webApp.start(); // check if we need to reconfigure the scanner,
scanner.start(); // 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();
break;
}
default:
{
throw new IllegalStateException("Unrecognized run type "+runType);
}
}
getLog().info("Restart completed."); getLog().info("Restart completed.");
} }

View File

@ -165,6 +165,9 @@ public class WebAppPropertyConverter
if (webApp == null) if (webApp == null)
throw new IllegalArgumentException("No webapp"); throw new IllegalArgumentException("No webapp");
if (webAppProperties == null)
return;
String str = webAppProperties.getProperty("context.path"); String str = webAppProperties.getProperty("context.path");
if (!StringUtil.isBlank(str)) if (!StringUtil.isBlank(str))
webApp.setContextPath(str); webApp.setContextPath(str);