001: //========================================================================
002: //$Id: AbstractJettyMojo.java 1246 2006-11-18 10:40:27Z 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.util.ArrayList;
020:
021: import org.apache.maven.plugin.AbstractMojo;
022: import org.apache.maven.plugin.MojoExecutionException;
023: import org.apache.maven.plugin.MojoFailureException;
024: import org.apache.maven.project.MavenProject;
025: import org.mortbay.jetty.plugin.util.JettyPluginServer;
026: import org.mortbay.jetty.plugin.util.JettyPluginWebApplication;
027: import org.mortbay.jetty.plugin.util.PluginLog;
028: import org.mortbay.jetty.plugin.util.Scanner;
029: import org.mortbay.jetty.plugin.util.SystemProperty;
030:
031: /**
032: * AbstractJettyMojo
033: *
034: *
035: */
036: public abstract class AbstractJettyMojo extends AbstractMojo {
037: /**
038: * The "virtual" webapp created by the plugin
039: */
040: private JettyPluginWebApplication webapp;
041:
042: /**
043: * The proxy for the Server object
044: */
045: private JettyPluginServer server;
046:
047: /**
048: * The maven project.
049: *
050: * @parameter expression="${project}"
051: * @required
052: * @readonly
053: */
054: private MavenProject project;
055:
056: /**
057: * The context path for the webapp. Defaults to the
058: * name of the webapp's artifact.
059: *
060: * @parameter expression="/${project.artifactId}"
061: * @required
062: */
063: private String contextPath;
064:
065: /**
066: * The temporary directory to use for the webapp.
067: * Defaults to target/jetty-tmp
068: *
069: * @parameter expression="${project.build.directory}/work"
070: * @required
071: */
072: private File tmpDirectory;
073:
074: /**
075: * A webdefault.xml file to use instead
076: * of the default for the webapp. Optional.
077: *
078: * @parameter
079: */
080: private File webDefaultXml;
081:
082: /**
083: * A web.xml file to be applied AFTER
084: * the webapp's web.xml file. Useful for
085: * applying different build profiles, eg
086: * test, production etc. Optional.
087: * @parameter
088: */
089: private File overrideWebXml;
090:
091: /**
092: * The interval in seconds to scan the webapp for changes
093: * and restart the context if necessary. Disabled by default.
094: *
095: * @parameter expression="0"
096: * @required
097: */
098: private int scanIntervalSeconds;
099:
100: /**
101: * System properties to set before execution.
102: * Note that these properties will NOT override System properties
103: * that have been set on the command line or by the JVM. Optional.
104: * @parameter
105: */
106: private SystemProperty[] systemProperties;
107:
108: /**
109: * Location of a jetty xml configuration file whose contents
110: * will be applied before any plugin configuration. Optional.
111: * @parameter
112: */
113: private String jettyConfig;
114:
115: /**
116: * List of files and directories to scan
117: */
118: private ArrayList scanList;
119:
120: /**
121: * List of Listeners for the scanner
122: */
123: private ArrayList scannerListeners;
124:
125: public String PORT_SYSPROPERTY = "jetty.port";
126:
127: /**
128: * @return Returns the realms configured in the pom
129: */
130: public abstract Object[] getConfiguredUserRealms();
131:
132: /**
133: * @return Returns the connectors configured in the pom
134: */
135: public abstract Object[] getConfiguredConnectors();
136:
137: public abstract Object getConfiguredRequestLog();
138:
139: public abstract void checkPomConfiguration()
140: throws MojoExecutionException;
141:
142: public abstract void configureScanner()
143: throws MojoExecutionException;
144:
145: public abstract void applyJettyXml() throws Exception;
146:
147: /**
148: * create a proxy that wraps a particular jetty version Server object
149: * @return
150: */
151: public abstract JettyPluginServer createServer() throws Exception;
152:
153: public abstract void finishConfigurationBeforeStart()
154: throws Exception;
155:
156: public MavenProject getProject() {
157: return this .project;
158: }
159:
160: public File getTmpDirectory() {
161: return this .tmpDirectory;
162: }
163:
164: public File getWebDefaultXml() {
165: return this .webDefaultXml;
166: }
167:
168: public File getOverrideWebXml() {
169: return this .overrideWebXml;
170: }
171:
172: /**
173: * @return Returns the contextPath.
174: */
175: public String getContextPath() {
176: return this .contextPath;
177: }
178:
179: /**
180: * @return Returns the scanIntervalSeconds.
181: */
182: public int getScanIntervalSeconds() {
183: return this .scanIntervalSeconds;
184: }
185:
186: public SystemProperty[] getSystemProperties() {
187: return this .systemProperties;
188: }
189:
190: public String getJettyXmlFileName() {
191: return this .jettyConfig;
192: }
193:
194: public JettyPluginWebApplication getWebApplication() {
195: return this .webapp;
196: }
197:
198: public void setWebApplication(JettyPluginWebApplication webapp) {
199: this .webapp = webapp;
200: }
201:
202: public JettyPluginServer getServer() {
203: return this .server;
204: }
205:
206: public void setServer(JettyPluginServer server) {
207: this .server = server;
208: }
209:
210: public void setScanList(ArrayList list) {
211: this .scanList = new ArrayList(list);
212: }
213:
214: public ArrayList getScanList() {
215: return this .scanList;
216: }
217:
218: public void setScannerListeners(ArrayList listeners) {
219: this .scannerListeners = new ArrayList(listeners);
220: }
221:
222: public ArrayList getScannerListeners() {
223: return this .scannerListeners;
224: }
225:
226: public void execute() throws MojoExecutionException,
227: MojoFailureException {
228: getLog().info(
229: "Configuring Jetty for project: "
230: + getProject().getName());
231: PluginLog.setLog(getLog());
232: checkPomConfiguration();
233: startJetty();
234: }
235:
236: public void startJetty() throws MojoExecutionException {
237: try {
238: getLog().debug("Starting Jetty Server ...");
239:
240: configureSystemProperties();
241: setServer(createServer());
242:
243: //apply any config from a jetty.xml file first which is able to
244: //be overwritten by config in the pom.xml
245: applyJettyXml();
246:
247: JettyPluginServer plugin = getServer();
248:
249: // if the user hasn't configured their project's pom to use a
250: // different set of connectors,
251: // use the default
252: Object[] configuredConnectors = getConfiguredConnectors();
253: if (configuredConnectors == null
254: || configuredConnectors.length == 0) {
255: //if a SystemProperty -Djetty.port=<portnum> has been supplied, use that as the default port
256: configuredConnectors = new Object[] { plugin
257: .createDefaultConnector(System.getProperty(
258: PORT_SYSPROPERTY, null)) };
259: }
260:
261: plugin.setConnectors(configuredConnectors);
262:
263: //set up a RequestLog if one is provided
264: if (getConfiguredRequestLog() != null)
265: getServer().setRequestLog(getConfiguredRequestLog());
266:
267: //set up the webapp and any context provided
268: getServer().configureHandlers();
269: setWebApplication(getServer().createWebApplication());
270: configureWebApplication();
271: getServer().addWebApplication(getWebApplication());
272:
273: // set up security realms
274: Object[] configuredRealms = getConfiguredUserRealms();
275: for (int i = 0; (configuredRealms != null)
276: && i < configuredRealms.length; i++)
277: getLog().debug(
278: configuredRealms[i].getClass().getName() + ": "
279: + configuredRealms[i].toString());
280:
281: plugin.setUserRealms(configuredRealms);
282:
283: //do any other configuration required by the
284: //particular Jetty version
285: finishConfigurationBeforeStart();
286:
287: // start Jetty
288: server.start();
289:
290: getLog().info("Started Jetty Server");
291:
292: // start the scanner thread (if necessary) on the main webapp
293: configureScanner();
294: startScanner();
295:
296: // keep the thread going
297: server.join();
298: } catch (Exception e) {
299: throw new MojoExecutionException("Failure", e);
300: } finally {
301: getLog().info("Jetty server exiting.");
302: }
303:
304: }
305:
306: /**
307: * Subclasses should invoke this to setup basic info
308: * on the webapp
309: *
310: * @throws MojoExecutionException
311: */
312: public void configureWebApplication() throws Exception {
313: if (getWebApplication() == null)
314: return;
315:
316: JettyPluginWebApplication webapp = getWebApplication();
317: webapp.setTempDirectory(getTmpDirectory());
318: webapp.setWebDefaultXmlFile(getWebDefaultXml());
319: String contextPath = getContextPath();
320: webapp
321: .setContextPath((contextPath.startsWith("/") ? contextPath
322: : "/" + contextPath));
323: webapp.setOverrideWebXmlFile(getOverrideWebXml());
324: getLog().info("Context path = " + webapp.getContextPath());
325: getLog().info(
326: "Tmp directory = "
327: + (getTmpDirectory() == null ? " jetty default"
328: : getTmpDirectory().toString()));
329: getLog()
330: .info(
331: "Web defaults = "
332: + (getWebDefaultXml() == null ? " jetty default"
333: : getWebDefaultXml().toString()));
334: getLog().info(
335: "Web overrides = "
336: + (getOverrideWebXml() == null ? " none"
337: : getOverrideWebXml().toString()));
338:
339: }
340:
341: /**
342: * Run a scanner thread on the given list of files and directories, calling
343: * stop/start on the given list of LifeCycle objects if any of the watched
344: * files change.
345: *
346: */
347: private void startScanner() {
348: // check if scanning is enabled
349: if (getScanIntervalSeconds() <= 0)
350: return;
351:
352: Scanner scanner = new Scanner();
353: scanner.setScanInterval(getScanIntervalSeconds());
354: scanner.setRoots(getScanList());
355: scanner.setListeners(getScannerListeners());
356: getLog().info(
357: "Starting scanner at interval of "
358: + getScanIntervalSeconds() + " seconds.");
359: scanner.start();
360: }
361:
362: private void configureSystemProperties() {
363: // get the system properties set up
364: for (int i = 0; (getSystemProperties() != null)
365: && i < getSystemProperties().length; i++) {
366: boolean result = getSystemProperties()[i]
367: .setIfNotSetAlready();
368: getLog().info(
369: "Property " + getSystemProperties()[i].getName()
370: + "=" + getSystemProperties()[i].getValue()
371: + " was " + (result ? "set" : "skipped"));
372: }
373: }
374:
375: /**
376: * Try and find a jetty-web.xml file, using some
377: * historical naming conventions if necessary.
378: * @param webInfDir
379: * @return
380: */
381: public File findJettyWebXmlFile(File webInfDir) {
382: if (webInfDir == null)
383: return null;
384: if (!webInfDir.exists())
385: return null;
386:
387: File f = new File(webInfDir, "jetty-web.xml");
388: if (f.exists())
389: return f;
390:
391: //try some historical alternatives
392: f = new File(webInfDir, "web-jetty.xml");
393: if (f.exists())
394: return f;
395: f = new File(webInfDir, "jetty6-web.xml");
396: if (f.exists())
397: return f;
398:
399: return null;
400: }
401: }
|