1 //
2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.maven.plugin;
20
21 import java.io.File;
22 import java.util.List;
23
24 import org.apache.maven.plugin.MojoExecutionException;
25 import org.apache.maven.plugin.MojoFailureException;
26 import org.eclipse.jetty.util.PathWatcher;
27 import org.eclipse.jetty.util.PathWatcher.PathWatchEvent;
28
29 /**
30 *
31 * <p>
32 * This goal is used to assemble your webapp into an exploded war and automatically deploy it to Jetty.
33 * </p>
34 * <p>
35 * Once invoked, the plugin runs continuously, and can be configured to scan for changes in the pom.xml and
36 * to WEB-INF/web.xml, WEB-INF/classes or WEB-INF/lib and hot redeploy when a change is detected.
37 * </p>
38 * <p>
39 * You may also specify the location of a jetty.xml file whose contents will be applied before any plugin configuration.
40 * This can be used, for example, to deploy a static webapp that is not part of your maven build.
41 * </p>
42 *
43 *@goal run-exploded
44 *@requiresDependencyResolution compile+runtime
45 *@execute phase=package
46 */
47 public class JettyRunWarExplodedMojo extends AbstractJettyMojo
48 {
49
50
51
52 /**
53 * The location of the war file.
54 *
55 * @parameter default-value="${project.build.directory}/${project.build.finalName}"
56 * @required
57 */
58 private File war;
59
60
61
62
63
64 /**
65 * @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#execute()
66 */
67 public void execute () throws MojoExecutionException, MojoFailureException
68 {
69 super.execute();
70 }
71
72
73
74 @Override
75 public void finishConfigurationBeforeStart() throws Exception
76 {
77 server.setStopAtShutdown(true); //as we will normally be stopped with a cntrl-c, ensure server stopped
78 super.finishConfigurationBeforeStart();
79 }
80
81
82 /**
83 *
84 * @see AbstractJettyMojo#checkPomConfiguration()
85 */
86 public void checkPomConfiguration() throws MojoExecutionException
87 {
88 return;
89 }
90
91
92
93
94 /**
95 * @see AbstractJettyMojo#configureScanner()
96 */
97 public void configureScanner() throws MojoExecutionException
98 {
99 scanner.watch(project.getFile().toPath());
100 File webInfDir = new File(war,"WEB-INF");
101 scanner.watch(new File(webInfDir, "web.xml").toPath());
102 File jettyWebXmlFile = findJettyWebXmlFile(webInfDir);
103 if (jettyWebXmlFile != null)
104 scanner.watch(jettyWebXmlFile.toPath());
105 File jettyEnvXmlFile = new File(webInfDir, "jetty-env.xml");
106 if (jettyEnvXmlFile.exists())
107 scanner.watch(jettyEnvXmlFile.toPath());
108
109 PathWatcher.Config classesConfig = new PathWatcher.Config(new File(webInfDir, "classes").toPath());
110 classesConfig.setRecurseDepth(PathWatcher.Config.UNLIMITED_DEPTH);
111 scanner.watch(classesConfig);
112
113 PathWatcher.Config libConfig = new PathWatcher.Config(new File(webInfDir, "lib").toPath());
114 libConfig.setRecurseDepth(PathWatcher.Config.UNLIMITED_DEPTH);
115 scanner.watch(libConfig);
116
117 scanner.addListener(new PathWatcher.EventListListener()
118 {
119
120 @Override
121 public void onPathWatchEvents(List<PathWatchEvent> events)
122 {
123 try
124 {
125 boolean reconfigure = false;
126 for (PathWatchEvent e:events)
127 {
128 if (e.getPath().equals(project.getFile().toPath()))
129 {
130 reconfigure = true;
131 break;
132 }
133 }
134 restartWebApp(reconfigure);
135 }
136 catch (Exception e)
137 {
138 getLog().error("Error reconfiguring/restarting webapp after change in watched files",e);
139 }
140 }
141 });
142 }
143
144
145
146
147 /**
148 * @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#restartWebApp(boolean)
149 */
150 public void restartWebApp(boolean reconfigureScanner) throws Exception
151 {
152 getLog().info("Restarting webapp");
153 getLog().debug("Stopping webapp ...");
154 stopScanner();
155 webApp.stop();
156 getLog().debug("Reconfiguring webapp ...");
157
158 checkPomConfiguration();
159
160 // check if we need to reconfigure the scanner,
161 // which is if the pom changes
162 if (reconfigureScanner)
163 {
164 getLog().info("Reconfiguring scanner after change to pom.xml ...");
165 scanner.reset();
166 configureScanner();
167 }
168
169 getLog().debug("Restarting webapp ...");
170 webApp.start();
171 startScanner();
172 getLog().info("Restart completed.");
173 }
174
175
176
177
178 /**
179 * @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#configureWebApplication()
180 */
181 public void configureWebApplication () throws Exception
182 {
183 super.configureWebApplication();
184 webApp.setWar(war.getCanonicalPath());
185 }
186 }