001: //========================================================================
002: //$Id: AbstractJettyRunMojo.java 1182 2006-11-10 15:58:01Z janb $
003: //Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
004: //------------------------------------------------------------------------
005: //Licensed under the Apache License, Version 2.0 (the "License");
006: //you may not use this file except in compliance with the License.
007: //You may obtain a copy of the License at
008: //http://www.apache.org/licenses/LICENSE-2.0
009: //Unless required by applicable law or agreed to in writing, software
010: //distributed under the License is distributed on an "AS IS" BASIS,
011: //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: //See the License for the specific language governing permissions and
013: //limitations under the License.
014: //========================================================================
015:
016: package org.mortbay.jetty.plugin;
017:
018: import java.io.File;
019: import java.io.IOException;
020: import java.util.ArrayList;
021: import java.util.Collections;
022: import java.util.Date;
023: import java.util.Iterator;
024: import java.util.List;
025:
026: import org.apache.maven.artifact.Artifact;
027: import org.apache.maven.plugin.MojoExecutionException;
028: import org.apache.maven.plugin.MojoFailureException;
029: import org.mortbay.jetty.plugin.util.JettyPluginWebApplication;
030: import org.mortbay.jetty.plugin.util.Scanner;
031:
032: /**
033: * AbstractJettyRunMojo
034: *
035: *
036: * Base class for all jetty versions for the "run" mojo.
037: *
038: */
039: public abstract class AbstractJettyRunMojo extends AbstractJettyMojo {
040:
041: /**
042: * If true, the <testOutputDirectory>
043: * and the dependencies of <scope>test<scope>
044: * will be put first on the runtime classpath.
045: * @parameter default-value="false"
046: */
047: private boolean useTestClasspath;
048:
049: /**
050: * The location of a jetty-env.xml file. Optional.
051: * @parameter
052: */
053: private String jettyEnvXml;
054:
055: /**
056: * The location of the web.xml file. If not
057: * set then it is assumed it is in ${basedir}/src/main/webapp/WEB-INF
058: *
059: * @parameter expression="${maven.war.webxml}"
060: */
061: private String webXml;
062:
063: /**
064: * The directory containing generated classes.
065: *
066: * @parameter expression="${project.build.outputDirectory}"
067: * @required
068: *
069: */
070: private File classesDirectory;
071:
072: /**
073: * The directory containing generated test classes.
074: *
075: * @parameter expression="${project.build.testOutputDirectory}"
076: * @required
077: */
078: private File testClassesDirectory;
079:
080: /**
081: * Root directory for all html/jsp etc files
082: *
083: * @parameter expression="${basedir}/src/main/webapp"
084: * @required
085: */
086: private File webAppSourceDirectory;
087:
088: /**
089: * @parameter expression="${plugin.artifacts}"
090: * @readonly
091: */
092: private List pluginArtifacts;
093:
094: /**
095: * List of files or directories to additionally periodically scan for changes. Optional.
096: * @parameter
097: */
098: private File[] scanTargets;
099:
100: /**
101: * web.xml as a File
102: */
103: private File webXmlFile;
104:
105: /**
106: * jetty-env.xml as a File
107: */
108: private File jettyEnvXmlFile;
109:
110: /**
111: * List of files on the classpath for the webapp
112: */
113: private List classPathFiles;
114:
115: /**
116: * Extra scan targets as a list
117: */
118: private List extraScanTargets;
119:
120: public String getWebXml() {
121: return this .webXml;
122: }
123:
124: public String getJettyEnvXml() {
125: return this .jettyEnvXml;
126: }
127:
128: public File getClassesDirectory() {
129: return this .classesDirectory;
130: }
131:
132: public File getWebAppSourceDirectory() {
133: return this .webAppSourceDirectory;
134: }
135:
136: public void setWebXmlFile(File f) {
137: this .webXmlFile = f;
138: }
139:
140: public File getWebXmlFile() {
141: return this .webXmlFile;
142: }
143:
144: public File getJettyEnvXmlFile() {
145: return this .jettyEnvXmlFile;
146: }
147:
148: public void setJettyEnvXmlFile(File f) {
149: this .jettyEnvXmlFile = f;
150: }
151:
152: public void setClassPathFiles(List list) {
153: this .classPathFiles = new ArrayList(list);
154: }
155:
156: public List getClassPathFiles() {
157: return this .classPathFiles;
158: }
159:
160: public List getExtraScanTargets() {
161: return this .extraScanTargets;
162: }
163:
164: public void setExtraScanTargets(List list) {
165: this .extraScanTargets = list;
166: }
167:
168: /**
169: * Run the mojo
170: * @see org.apache.maven.plugin.Mojo#execute()
171: */
172: public void execute() throws MojoExecutionException,
173: MojoFailureException {
174: super .execute();
175: }
176:
177: /**
178: * Verify the configuration given in the pom.
179: *
180: * @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
181: */
182: public void checkPomConfiguration() throws MojoExecutionException {
183: // check the location of the static content/jsps etc
184: try {
185: if ((getWebAppSourceDirectory() == null)
186: || !getWebAppSourceDirectory().exists())
187: throw new MojoExecutionException(
188: "Webapp source directory "
189: + (getWebAppSourceDirectory() == null ? "null"
190: : getWebAppSourceDirectory()
191: .getCanonicalPath())
192: + " does not exist");
193: else
194: getLog().info(
195: "Webapp source directory = "
196: + getWebAppSourceDirectory()
197: .getCanonicalPath());
198: } catch (IOException e) {
199: throw new MojoExecutionException(
200: "Webapp source directory does not exist", e);
201: }
202:
203: // get the web.xml file if one has been provided, otherwise assume it is
204: // in the webapp src directory
205: if (getWebXml() == null || (getWebXml().trim().equals("")))
206: setWebXmlFile(new File(new File(getWebAppSourceDirectory(),
207: "WEB-INF"), "web.xml"));
208: else
209: setWebXmlFile(new File(getWebXml()));
210:
211: try {
212: if (!getWebXmlFile().exists())
213: throw new MojoExecutionException(
214: "web.xml does not exist at location "
215: + webXmlFile.getCanonicalPath());
216: else
217: getLog().info(
218: "web.xml file = "
219: + webXmlFile.getCanonicalPath());
220: } catch (IOException e) {
221: throw new MojoExecutionException("web.xml does not exist",
222: e);
223: }
224:
225: //check if a jetty-env.xml location has been provided, if so, it must exist
226: if (getJettyEnvXml() != null) {
227: setJettyEnvXmlFile(new File(getJettyEnvXml()));
228:
229: try {
230: if (!getJettyEnvXmlFile().exists())
231: throw new MojoExecutionException(
232: "jetty-env.xml file does not exist at location "
233: + jettyEnvXml);
234: else
235: getLog().info(
236: " jetty-env.xml = "
237: + getJettyEnvXmlFile()
238: .getCanonicalPath());
239: } catch (IOException e) {
240: throw new MojoExecutionException(
241: "jetty-env.xml does not exist");
242: }
243: }
244:
245: // check the classes to form a classpath with
246: try {
247: //allow a webapp with no classes in it (just jsps/html)
248: if (getClassesDirectory() != null) {
249: if (!getClassesDirectory().exists())
250: getLog().info(
251: "Classes directory "
252: + getClassesDirectory()
253: .getCanonicalPath()
254: + " does not exist");
255: else
256: getLog().info(
257: "Classes = "
258: + getClassesDirectory()
259: .getCanonicalPath());
260: } else
261: getLog().info("Classes directory not set");
262: } catch (IOException e) {
263: throw new MojoExecutionException(
264: "Location of classesDirectory does not exist");
265: }
266:
267: // check the tmp directory
268: if (getTmpDirectory() != null) {
269: if (!getTmpDirectory().exists()) {
270: if (!getTmpDirectory().mkdirs())
271: throw new MojoExecutionException(
272: "Unable to create tmp directory at "
273: + getTmpDirectory());
274: }
275:
276: }
277:
278: if (scanTargets == null)
279: setExtraScanTargets(Collections.EMPTY_LIST);
280: else {
281: ArrayList list = new ArrayList();
282: for (int i = 0; i < scanTargets.length; i++) {
283: getLog().info(
284: "Added extra scan target:" + scanTargets[i]);
285: list.add(scanTargets[i]);
286: }
287: setExtraScanTargets(list);
288: }
289: }
290:
291: public void configureWebApplication() throws Exception {
292: super .configureWebApplication();
293:
294: JettyPluginWebApplication webapp = getWebApplication();
295: setClassPathFiles(setUpClassPath());
296: webapp.setWebXmlFile(getWebXmlFile());
297: webapp.setJettyEnvXmlFile(getJettyEnvXmlFile());
298: webapp.setClassPathFiles(getClassPathFiles());
299: webapp.setWebAppSrcDir(getWebAppSourceDirectory());
300: getLog()
301: .info(
302: "Webapp directory = "
303: + getWebAppSourceDirectory()
304: .getCanonicalPath());
305:
306: webapp.configure();
307: }
308:
309: public void configureScanner() {
310: // start the scanner thread (if necessary) on the main webapp
311: final ArrayList scanList = new ArrayList();
312: scanList.add(getWebXmlFile());
313: if (getJettyEnvXmlFile() != null)
314: scanList.add(getJettyEnvXmlFile());
315: File jettyWebXmlFile = findJettyWebXmlFile(new File(
316: getWebAppSourceDirectory(), "WEB-INF"));
317: if (jettyWebXmlFile != null)
318: scanList.add(jettyWebXmlFile);
319: scanList.addAll(getExtraScanTargets());
320: scanList.add(getProject().getFile());
321: scanList.addAll(getClassPathFiles());
322: setScanList(scanList);
323: ArrayList listeners = new ArrayList();
324: listeners.add(new Scanner.Listener() {
325: public void changesDetected(Scanner scanner, List changes) {
326: try {
327: getLog().info("restarting " + getWebApplication());
328: getLog().debug("Stopping webapp ...");
329: getWebApplication().stop();
330: getLog().debug("Reconfiguring webapp ...");
331:
332: checkPomConfiguration();
333: configureWebApplication();
334:
335: // check if we need to reconfigure the scanner,
336: // which is if the pom changes
337: if (changes.contains(getProject().getFile()
338: .getCanonicalPath())) {
339: getLog()
340: .info(
341: "Reconfiguring scanner after change to pom.xml ...");
342: scanList.clear();
343: scanList.add(getWebXmlFile());
344: if (getJettyEnvXmlFile() != null)
345: scanList.add(getJettyEnvXmlFile());
346: scanList.addAll(getExtraScanTargets());
347: scanList.add(getProject().getFile());
348: scanList.addAll(getClassPathFiles());
349: scanner.setRoots(scanList);
350: }
351:
352: getLog().debug("Restarting webapp ...");
353: getWebApplication().start();
354: getLog().info(
355: "Restart completed at "
356: + new Date().toString());
357: } catch (Exception e) {
358: getLog()
359: .error(
360: "Error reconfiguring/restarting webapp after change in watched files",
361: e);
362: }
363: }
364: });
365: setScannerListeners(listeners);
366: }
367:
368: private List getDependencyFiles() {
369: List dependencyFiles = new ArrayList();
370: for (Iterator iter = getProject().getArtifacts().iterator(); iter
371: .hasNext();) {
372: Artifact artifact = (Artifact) iter.next();
373:
374: // Include runtime and compile time libraries, and possibly test libs too
375: if ((!Artifact.SCOPE_TEST.equals(artifact.getScope()))
376: || (useTestClasspath && Artifact.SCOPE_TEST
377: .equals(artifact.getScope()))) {
378: dependencyFiles.add(artifact.getFile());
379: getLog().debug(
380: "Adding artifact "
381: + artifact.getFile().getName()
382: + " for WEB-INF/lib ");
383: }
384: }
385: return dependencyFiles;
386: }
387:
388: private List setUpClassPath() {
389: List classPathFiles = new ArrayList();
390:
391: //if using the test classes, make sure they are first
392: //on the list
393: if (useTestClasspath && (testClassesDirectory != null))
394: classPathFiles.add(testClassesDirectory);
395:
396: if (getClassesDirectory() != null)
397: classPathFiles.add(getClassesDirectory());
398:
399: //now add all of the dependencies
400: classPathFiles.addAll(getDependencyFiles());
401:
402: if (getLog().isDebugEnabled()) {
403: for (int i = 0; i < classPathFiles.size(); i++) {
404: getLog().debug(
405: "classpath element: "
406: + ((File) classPathFiles.get(i))
407: .getName());
408: }
409: }
410: return classPathFiles;
411: }
412:
413: }
|