View Javadoc
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         File webXml = new File(webInfDir, "web.xml");
102         if (webXml.exists())
103             scanner.watch(webXml.toPath());
104         File jettyWebXmlFile = findJettyWebXmlFile(webInfDir);
105         if (jettyWebXmlFile != null)
106             scanner.watch(jettyWebXmlFile.toPath());
107         File jettyEnvXmlFile = new File(webInfDir, "jetty-env.xml");
108         if (jettyEnvXmlFile.exists())
109             scanner.watch(jettyEnvXmlFile.toPath());
110 
111         File classes = new File(webInfDir, "classes");
112         if (classes.exists())
113         {
114             PathWatcher.Config classesConfig = new PathWatcher.Config(classes.toPath());
115             classesConfig.setRecurseDepth(PathWatcher.Config.UNLIMITED_DEPTH);
116             scanner.watch(classesConfig);
117         }
118 
119         File lib = new File(webInfDir, "lib");
120         if (lib.exists())
121         {
122             PathWatcher.Config libConfig = new PathWatcher.Config(lib.toPath());
123             libConfig.setRecurseDepth(PathWatcher.Config.UNLIMITED_DEPTH);
124             scanner.watch(libConfig);   
125         }
126 
127         scanner.addListener(new PathWatcher.EventListListener()
128         {
129 
130             @Override
131             public void onPathWatchEvents(List<PathWatchEvent> events)
132             {
133                 try
134                 {
135                     boolean reconfigure = false;
136                     for (PathWatchEvent e:events)
137                     {
138                         if (e.getPath().equals(project.getFile().toPath()))
139                         {
140                             reconfigure = true;
141                             break;
142                         }
143                     }
144                     restartWebApp(reconfigure);
145                 }
146                 catch (Exception e)
147                 {
148                     getLog().error("Error reconfiguring/restarting webapp after change in watched files",e);
149                 }
150             }
151         });
152     }
153 
154     
155     
156     
157     /** 
158      * @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#restartWebApp(boolean)
159      */
160     public void restartWebApp(boolean reconfigureScanner) throws Exception 
161     {
162         getLog().info("Restarting webapp");
163         getLog().debug("Stopping webapp ...");
164         stopScanner();
165         webApp.stop();
166         getLog().debug("Reconfiguring webapp ...");
167 
168         checkPomConfiguration();
169 
170         // check if we need to reconfigure the scanner,
171         // which is if the pom changes
172         if (reconfigureScanner)
173         {
174             getLog().info("Reconfiguring scanner after change to pom.xml ...");
175             scanner.reset();
176             configureScanner();
177         }
178 
179         getLog().debug("Restarting webapp ...");
180         webApp.start();
181         startScanner();
182         getLog().info("Restart completed.");
183     }
184 
185    
186 
187     
188     /** 
189      * @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#configureWebApplication()
190      */
191     public void configureWebApplication () throws Exception
192     {
193         super.configureWebApplication();        
194         webApp.setWar(war.getCanonicalPath());
195     }
196 }