~ubuntu-branches/ubuntu/utopic/jetty/utopic-proposed

« back to all changes in this revision

Viewing changes to modules/maven-plugin/src/main/java/org/mortbay/jetty/plugin/AbstractJettyMojo.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2009-08-09 08:48:10 UTC
  • Revision ID: james.westby@ubuntu.com-20090809084810-k522b97ind2robyd
ImportĀ upstreamĀ versionĀ 6.1.19

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//========================================================================
 
2
//$Id: AbstractJettyMojo.java 4648 2009-02-24 08:56:03Z ayao $
 
3
//Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
 
4
//------------------------------------------------------------------------
 
5
//Licensed under the Apache License, Version 2.0 (the "License");
 
6
//you may not use this file except in compliance with the License.
 
7
//You may obtain a copy of the License at
 
8
//http://www.apache.org/licenses/LICENSE-2.0
 
9
//Unless required by applicable law or agreed to in writing, software
 
10
//distributed under the License is distributed on an "AS IS" BASIS,
 
11
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
12
//See the License for the specific language governing permissions and
 
13
//limitations under the License.
 
14
//========================================================================
 
15
 
 
16
 
 
17
package org.mortbay.jetty.plugin;
 
18
 
 
19
 
 
20
import java.io.File;
 
21
import java.io.FileInputStream;
 
22
import java.util.ArrayList;
 
23
import java.util.Enumeration;
 
24
import java.util.Iterator;
 
25
import java.util.List;
 
26
import java.util.Properties;
 
27
 
 
28
import org.apache.maven.plugin.AbstractMojo;
 
29
import org.apache.maven.plugin.MojoExecutionException;
 
30
import org.apache.maven.plugin.MojoFailureException;
 
31
import org.apache.maven.project.MavenProject;
 
32
import org.mortbay.jetty.Server;
 
33
import org.mortbay.jetty.plugin.util.ConsoleScanner;
 
34
import org.mortbay.jetty.plugin.util.JettyPluginServer;
 
35
import org.mortbay.jetty.plugin.util.PluginLog;
 
36
import org.mortbay.jetty.plugin.util.SystemProperties;
 
37
import org.mortbay.jetty.plugin.util.SystemProperty;
 
38
import org.mortbay.util.Scanner;
 
39
 
 
40
 
 
41
 
 
42
/**
 
43
 * AbstractJettyMojo
 
44
 *
 
45
 *
 
46
 */
 
47
public abstract class AbstractJettyMojo extends AbstractMojo
 
48
{
 
49
    /**
 
50
     * The proxy for the Server object
 
51
     */
 
52
    protected JettyPluginServer server;
 
53
 
 
54
 
 
55
    /**
 
56
     * The "virtual" webapp created by the plugin
 
57
     * @parameter
 
58
     */
 
59
    protected Jetty6PluginWebAppContext webAppConfig;
 
60
 
 
61
 
 
62
 
 
63
    /**
 
64
     * The maven project.
 
65
     *
 
66
     * @parameter expression="${executedProject}"
 
67
     * @required
 
68
     * @readonly
 
69
     */
 
70
    protected MavenProject project;
 
71
 
 
72
 
 
73
 
 
74
    /**
 
75
     * The context path for the webapp. Defaults to the
 
76
     * name of the webapp's artifact.
 
77
     *
 
78
     * @parameter expression="/${project.artifactId}"
 
79
     * @required
 
80
     */
 
81
    protected String contextPath;
 
82
 
 
83
 
 
84
    /**
 
85
     * The temporary directory to use for the webapp.
 
86
     * Defaults to target/jetty-tmp
 
87
     *
 
88
     * @parameter expression="${project.build.directory}/work"
 
89
     * @required
 
90
     */
 
91
    protected File tmpDirectory;
 
92
 
 
93
 
 
94
 
 
95
    /**
 
96
     * A webdefault.xml file to use instead
 
97
     * of the default for the webapp. Optional.
 
98
     *
 
99
     * @parameter
 
100
     */
 
101
    protected File webDefaultXml;
 
102
 
 
103
 
 
104
    /**
 
105
     * A web.xml file to be applied AFTER
 
106
     * the webapp's web.xml file. Useful for
 
107
     * applying different build profiles, eg
 
108
     * test, production etc. Optional.
 
109
     * @parameter
 
110
     */
 
111
    protected File overrideWebXml;
 
112
    
 
113
    /**
 
114
     * The interval in seconds to scan the webapp for changes 
 
115
     * and restart the context if necessary. Ignored if reload
 
116
     * is enabled. Disabled by default.
 
117
     * 
 
118
     * @parameter expression="${jetty.scanIntervalSeconds}" default-value="0"
 
119
     * @required
 
120
     */
 
121
    protected int scanIntervalSeconds;
 
122
    
 
123
    
 
124
    /**
 
125
     * reload can be set to either 'automatic' or 'manual'
 
126
     *
 
127
     * if 'manual' then the context can be reloaded by a linefeed in the console
 
128
     * if 'automatic' then traditional reloading on changed files is enabled.
 
129
     * 
 
130
     * @parameter expression="${jetty.reload}" default-value="automatic"
 
131
     */
 
132
    protected String reload;
 
133
    
 
134
    /**
 
135
     * File containing system properties to be set before execution
 
136
     * 
 
137
     * Note that these properties will NOT override System properties
 
138
     * that have been set on the command line, by the JVM, or directly 
 
139
     * in the POM via systemProperties. Optional.
 
140
     * 
 
141
     * @parameter expression="${jetty.systemPropertiesFile}"
 
142
     */
 
143
    protected File systemPropertiesFile;
 
144
 
 
145
    /**
 
146
     * System properties to set before execution. 
 
147
     * Note that these properties will NOT override System properties 
 
148
     * that have been set on the command line or by the JVM. They WILL 
 
149
     * override System properties that have been set via systemPropertiesFile.
 
150
     * Optional.
 
151
     * @parameter
 
152
     */
 
153
    protected SystemProperties systemProperties;
 
154
    
 
155
    
 
156
    
 
157
    /**
 
158
     * Location of a jetty xml configuration file whose contents 
 
159
     * will be applied before any plugin configuration. Optional.
 
160
     * @parameter
 
161
     */
 
162
    protected File jettyConfig;
 
163
    
 
164
    /**
 
165
     * Port to listen to stop jetty on executing -DSTOP.PORT=<stopPort> 
 
166
     * -DSTOP.KEY=<stopKey> -jar start.jar --stop
 
167
     * @parameter
 
168
     */
 
169
    protected int stopPort;
 
170
    
 
171
    /**
 
172
     * Key to provide when stopping jetty on executing java -DSTOP.KEY=<stopKey> 
 
173
     * -DSTOP.PORT=<stopPort> -jar start.jar --stop
 
174
     * @parameter
 
175
     */
 
176
    protected String stopKey;
 
177
 
 
178
    /**
 
179
         * <p>
 
180
         * Determines whether or not the server blocks when started. The default
 
181
         * behavior (daemon = false) will cause the server to pause other processes
 
182
         * while it continues to handle web requests. This is useful when starting the
 
183
         * server with the intent to work with it interactively.
 
184
         * </p><p>
 
185
         * Often, it is desirable to let the server start and continue running subsequent
 
186
         * processes in an automated build environment. This can be facilitated by setting
 
187
         * daemon to true.
 
188
         * </p>
 
189
         * @parameter expression="${jetty.daemon}" default-value="false"
 
190
         */
 
191
        protected boolean daemon;
 
192
    
 
193
    /**
 
194
     * A scanner to check for changes to the webapp
 
195
     */
 
196
    protected Scanner scanner;
 
197
    
 
198
    /**
 
199
     *  List of files and directories to scan
 
200
     */
 
201
    protected ArrayList scanList;
 
202
    
 
203
    /**
 
204
     * List of Listeners for the scanner
 
205
     */
 
206
    protected ArrayList scannerListeners;
 
207
    
 
208
    
 
209
    /**
 
210
     * A scanner to check ENTER hits on the console
 
211
     */
 
212
    protected Thread consoleScanner;
 
213
 
 
214
    
 
215
    public String PORT_SYSPROPERTY = "jetty.port";
 
216
    
 
217
    /**
 
218
     * @return Returns the realms configured in the pom
 
219
     */
 
220
    public abstract Object[] getConfiguredUserRealms();
 
221
    
 
222
    /**
 
223
     * @return Returns the connectors configured in the pom
 
224
     */
 
225
    public abstract Object[] getConfiguredConnectors();
 
226
 
 
227
    public abstract Object getConfiguredRequestLog();
 
228
    
 
229
 
 
230
    public abstract void checkPomConfiguration() throws MojoExecutionException;
 
231
    
 
232
    
 
233
    
 
234
    public abstract void configureScanner () throws MojoExecutionException;
 
235
    
 
236
    
 
237
    public abstract void applyJettyXml () throws Exception;
 
238
    
 
239
    
 
240
    /**
 
241
     * create a proxy that wraps a particular jetty version Server object
 
242
     * @return
 
243
     */
 
244
    public abstract JettyPluginServer createServer() throws Exception;
 
245
    
 
246
    
 
247
    public abstract void finishConfigurationBeforeStart() throws Exception;
 
248
    
 
249
    
 
250
    public MavenProject getProject()
 
251
    {
 
252
        return this.project;
 
253
    }
 
254
    
 
255
    public File getTmpDirectory()
 
256
    {
 
257
        return this.tmpDirectory;
 
258
    }
 
259
 
 
260
    
 
261
    public File getWebDefaultXml()
 
262
    {
 
263
        return this.webDefaultXml;
 
264
    }
 
265
    
 
266
    public File getOverrideWebXml()
 
267
    {
 
268
        return this.overrideWebXml;
 
269
    }
 
270
    
 
271
    /**
 
272
     * @return Returns the contextPath.
 
273
     */
 
274
    public String getContextPath()
 
275
    {
 
276
        return this.contextPath;
 
277
    }
 
278
 
 
279
    /**
 
280
     * @return Returns the scanIntervalSeconds.
 
281
     */
 
282
    public int getScanIntervalSeconds()
 
283
    {
 
284
        return this.scanIntervalSeconds;
 
285
    }
 
286
 
 
287
    /**
 
288
     * @return returns the path to the systemPropertiesFile
 
289
     */
 
290
    public File getSystemPropertiesFile()
 
291
    {
 
292
        return this.systemPropertiesFile;
 
293
    }
 
294
    
 
295
    public void setSystemPropertiesFile(File file) throws Exception
 
296
    {
 
297
        this.systemPropertiesFile = file;
 
298
        FileInputStream propFile = new FileInputStream(systemPropertiesFile);
 
299
        Properties properties = new Properties();
 
300
        properties.load(propFile);
 
301
        
 
302
        if (this.systemProperties == null )
 
303
            this.systemProperties = new SystemProperties();
 
304
        
 
305
        for (Enumeration keys = properties.keys(); keys.hasMoreElements();  )
 
306
        {
 
307
            String key = (String)keys.nextElement();
 
308
            if ( ! systemProperties.containsSystemProperty(key) )
 
309
            {
 
310
                SystemProperty prop = new SystemProperty();
 
311
                prop.setKey(key);
 
312
                prop.setValue(properties.getProperty(key));
 
313
                
 
314
                this.systemProperties.setSystemProperty(prop);
 
315
            }
 
316
        }
 
317
        
 
318
    }
 
319
    
 
320
    public void setSystemProperties(SystemProperties systemProperties)
 
321
    {
 
322
        if (this.systemProperties == null)
 
323
            this.systemProperties = systemProperties;
 
324
        else
 
325
        {
 
326
            Iterator itor = systemProperties.getSystemProperties().iterator();
 
327
            while (itor.hasNext())
 
328
            {
 
329
                SystemProperty prop = (SystemProperty)itor.next();
 
330
                this.systemProperties.setSystemProperty(prop);
 
331
            }   
 
332
        }
 
333
    }
 
334
 
 
335
    public File getJettyXmlFile ()
 
336
    {
 
337
        return this.jettyConfig;
 
338
    }
 
339
 
 
340
 
 
341
    public JettyPluginServer getServer ()
 
342
    {
 
343
        return this.server;
 
344
    }
 
345
 
 
346
    public void setServer (JettyPluginServer server)
 
347
    {
 
348
        this.server = server;
 
349
    }
 
350
 
 
351
 
 
352
    public void setScanList (ArrayList list)
 
353
    {
 
354
        this.scanList = new ArrayList(list);
 
355
    }
 
356
 
 
357
    public ArrayList getScanList ()
 
358
    {
 
359
        return this.scanList;
 
360
    }
 
361
 
 
362
 
 
363
    public void setScannerListeners (ArrayList listeners)
 
364
    {
 
365
        this.scannerListeners = new ArrayList(listeners);
 
366
    }
 
367
 
 
368
    public ArrayList getScannerListeners ()
 
369
    {
 
370
        return this.scannerListeners;
 
371
    }
 
372
 
 
373
    public Scanner getScanner ()
 
374
    {
 
375
        return scanner;
 
376
    }
 
377
 
 
378
    public void execute() throws MojoExecutionException, MojoFailureException
 
379
    {
 
380
        getLog().info("Configuring Jetty for project: " + getProject().getName());
 
381
        PluginLog.setLog(getLog());
 
382
        checkPomConfiguration();
 
383
        startJetty();
 
384
    }
 
385
 
 
386
 
 
387
    public void startJetty () throws MojoExecutionException
 
388
    {
 
389
        try
 
390
        {
 
391
            getLog().debug("Starting Jetty Server ...");
 
392
 
 
393
            printSystemProperties();
 
394
            setServer(createServer());
 
395
 
 
396
            //apply any config from a jetty.xml file first which is able to
 
397
            //be overwritten by config in the pom.xml
 
398
            applyJettyXml ();
 
399
 
 
400
            JettyPluginServer plugin=getServer();
 
401
 
 
402
 
 
403
            // if the user hasn't configured their project's pom to use a
 
404
            // different set of connectors,
 
405
            // use the default
 
406
            Object[] configuredConnectors = getConfiguredConnectors();
 
407
 
 
408
            plugin.setConnectors(configuredConnectors);
 
409
            Object[] connectors = plugin.getConnectors();
 
410
 
 
411
            if (connectors == null|| connectors.length == 0)
 
412
            {
 
413
                //if a SystemProperty -Djetty.port=<portnum> has been supplied, use that as the default port
 
414
                configuredConnectors = new Object[] { plugin.createDefaultConnector(System.getProperty(PORT_SYSPROPERTY, null)) };
 
415
                plugin.setConnectors(configuredConnectors);
 
416
            }
 
417
 
 
418
 
 
419
            //set up a RequestLog if one is provided
 
420
            if (getConfiguredRequestLog() != null)
 
421
                getServer().setRequestLog(getConfiguredRequestLog());
 
422
 
 
423
            //set up the webapp and any context provided
 
424
            getServer().configureHandlers();
 
425
            configureWebApplication();
 
426
            getServer().addWebApplication(webAppConfig);
 
427
 
 
428
 
 
429
            // set up security realms
 
430
            Object[] configuredRealms = getConfiguredUserRealms();
 
431
            for (int i = 0; (configuredRealms != null) && i < configuredRealms.length; i++)
 
432
                getLog().debug(configuredRealms[i].getClass().getName() + ": "+ configuredRealms[i].toString());
 
433
 
 
434
            plugin.setUserRealms(configuredRealms);
 
435
 
 
436
            //do any other configuration required by the
 
437
            //particular Jetty version
 
438
            finishConfigurationBeforeStart();
 
439
 
 
440
            // start Jetty
 
441
            server.start();
 
442
 
 
443
            getLog().info("Started Jetty Server");
 
444
            
 
445
            if(stopPort>0 && stopKey!=null)
 
446
            {
 
447
                org.mortbay.jetty.plugin.util.Monitor monitor = new org.mortbay.jetty.plugin.util.Monitor(stopPort, stopKey, new Server[]{(Server)server.getProxiedObject()}, !daemon);
 
448
                monitor.start();
 
449
            }
 
450
            
 
451
            // start the scanner thread (if necessary) on the main webapp
 
452
            configureScanner ();
 
453
            startScanner();
 
454
            
 
455
            // start the new line scanner thread if necessary
 
456
            startConsoleScanner();
 
457
 
 
458
            // keep the thread going if not in daemon mode
 
459
            if (!daemon)
 
460
            {
 
461
                server.join();
 
462
            }
 
463
        }
 
464
        catch (Exception e)
 
465
        {
 
466
            throw new MojoExecutionException("Failure", e);
 
467
        }
 
468
        finally
 
469
        {
 
470
            if (!daemon)
 
471
            {
 
472
                getLog().info("Jetty server exiting.");
 
473
            }            
 
474
        }
 
475
        
 
476
    }
 
477
    
 
478
    
 
479
    public abstract void restartWebApp(boolean reconfigureScanner) throws Exception;
 
480
 
 
481
    /**
 
482
     * Subclasses should invoke this to setup basic info
 
483
     * on the webapp
 
484
     * 
 
485
     * @throws MojoExecutionException
 
486
     */
 
487
    public void configureWebApplication () throws Exception
 
488
    {
 
489
        //use EITHER a <webAppConfig> element or the now deprecated <contextPath>, <tmpDirectory>, <webDefaultXml>, <overrideWebXml>
 
490
        //way of doing things
 
491
        if (webAppConfig == null)
 
492
        {
 
493
            webAppConfig = new Jetty6PluginWebAppContext();
 
494
            webAppConfig.setContextPath((getContextPath().startsWith("/") ? getContextPath() : "/"+ getContextPath()));
 
495
            if (getTmpDirectory() != null)
 
496
                webAppConfig.setTempDirectory(getTmpDirectory());
 
497
            if (getWebDefaultXml() != null)
 
498
                webAppConfig.setDefaultsDescriptor(getWebDefaultXml().getCanonicalPath());
 
499
            if (getOverrideWebXml() != null)
 
500
                webAppConfig.setOverrideDescriptor(getOverrideWebXml().getCanonicalPath());
 
501
        }
 
502
 
 
503
 
 
504
        getLog().info("Context path = " + webAppConfig.getContextPath());
 
505
        getLog().info("Tmp directory = "+ " determined at runtime");
 
506
        getLog().info("Web defaults = "+(webAppConfig.getDefaultsDescriptor()==null?" jetty default":webAppConfig.getDefaultsDescriptor()));
 
507
        getLog().info("Web overrides = "+(webAppConfig.getOverrideDescriptor()==null?" none":webAppConfig.getOverrideDescriptor()));
 
508
 
 
509
    }
 
510
 
 
511
    /**
 
512
     * Run a scanner thread on the given list of files and directories, calling
 
513
     * stop/start on the given list of LifeCycle objects if any of the watched
 
514
     * files change.
 
515
     *
 
516
     */
 
517
    private void startScanner()
 
518
    {
 
519
 
 
520
        // check if scanning is enabled
 
521
        if (getScanIntervalSeconds() <= 0) return;
 
522
 
 
523
        // check if reload is manual. It disables file scanning
 
524
        if ( "manual".equalsIgnoreCase( reload ) )
 
525
        {
 
526
            // issue a warning if both scanIntervalSeconds and reload
 
527
            // are enabled
 
528
            getLog().warn("scanIntervalSeconds is set to " + scanIntervalSeconds + " but will be IGNORED due to manual reloading");
 
529
            return;
 
530
        }
 
531
 
 
532
        scanner = new Scanner();
 
533
        scanner.setReportExistingFilesOnStartup(false);
 
534
        scanner.setScanInterval(getScanIntervalSeconds());
 
535
        scanner.setScanDirs(getScanList());
 
536
        scanner.setRecursive(true);
 
537
        List listeners = getScannerListeners();
 
538
        Iterator itor = (listeners==null?null:listeners.iterator());
 
539
        while (itor!=null && itor.hasNext())
 
540
            scanner.addListener((Scanner.Listener)itor.next());
 
541
        getLog().info("Starting scanner at interval of " + getScanIntervalSeconds()+ " seconds.");
 
542
        scanner.start();
 
543
    }
 
544
    
 
545
    /**
 
546
     * Run a thread that monitors the console input to detect ENTER hits.
 
547
     */
 
548
    protected void startConsoleScanner() 
 
549
    {
 
550
        if ( "manual".equalsIgnoreCase( reload ) )
 
551
        {
 
552
            getLog().info("Console reloading is ENABLED. Hit ENTER on the console to restart the context.");
 
553
            consoleScanner = new ConsoleScanner(this);
 
554
            consoleScanner.start();
 
555
        }
 
556
        
 
557
    }
 
558
 
 
559
    private void printSystemProperties ()
 
560
    {
 
561
        // print out which system properties were set up
 
562
        if (getLog().isDebugEnabled())
 
563
        {
 
564
            if (systemProperties != null)
 
565
            {
 
566
                Iterator itor = systemProperties.getSystemProperties().iterator();
 
567
                while (itor.hasNext())
 
568
                {
 
569
                    SystemProperty prop = (SystemProperty)itor.next();
 
570
                    getLog().debug("Property "+prop.getName()+"="+prop.getValue()+" was "+ (prop.isSet() ? "set" : "skipped"));
 
571
                }
 
572
            }
 
573
        }
 
574
    }
 
575
 
 
576
    /**
 
577
     * Try and find a jetty-web.xml file, using some
 
578
     * historical naming conventions if necessary.
 
579
     * @param webInfDir
 
580
     * @return
 
581
     */
 
582
    public File findJettyWebXmlFile (File webInfDir)
 
583
    {
 
584
        if (webInfDir == null)
 
585
            return null;
 
586
        if (!webInfDir.exists())
 
587
            return null;
 
588
 
 
589
        File f = new File (webInfDir, "jetty-web.xml");
 
590
        if (f.exists())
 
591
            return f;
 
592
 
 
593
        //try some historical alternatives
 
594
        f = new File (webInfDir, "web-jetty.xml");
 
595
        if (f.exists())
 
596
            return f;
 
597
        f = new File (webInfDir, "jetty6-web.xml");
 
598
        if (f.exists())
 
599
            return f;
 
600
        
 
601
        return null;
 
602
    }
 
603
}