KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > jetty > Server


1 // ========================================================================
2
// $Id: Server.java,v 1.40 2005/10/21 13:52:11 gregwilkins Exp $
3
// Copyright 2002-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 package org.mortbay.jetty;
17
18 import java.io.IOException JavaDoc;
19 import java.lang.reflect.InvocationTargetException JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21 import java.net.URL JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Iterator JavaDoc;
25
26 import org.apache.commons.logging.Log;
27 import org.mortbay.log.LogFactory;
28 import org.mortbay.http.HttpContext;
29 import org.mortbay.http.HttpServer;
30 import org.mortbay.jetty.servlet.ServletHttpContext;
31 import org.mortbay.jetty.servlet.WebApplicationContext;
32 import org.mortbay.util.LogSupport;
33 import org.mortbay.util.Resource;
34 import org.mortbay.xml.XmlConfiguration;
35
36
37 /* ------------------------------------------------------------ */
38 /** The Jetty HttpServer.
39  *
40  * This specialization of org.mortbay.http.HttpServer adds knowledge
41  * about servlets and their specialized contexts. It also included
42  * support for initialization from xml configuration files
43  * that follow the XmlConfiguration dtd.
44  *
45  * HttpContexts created by Server are of the type
46  * org.mortbay.jetty.servlet.ServletHttpContext unless otherwise
47  * specified.
48  *
49  * This class also provides a main() method which starts a server for
50  * each config file passed on the command line. If the system
51  * property JETTY_NO_SHUTDOWN_HOOK is not set to true, then a shutdown
52  * hook is thread is registered to stop these servers.
53  *
54  * @see org.mortbay.xml.XmlConfiguration
55  * @see org.mortbay.jetty.servlet.ServletHttpContext
56  * @version $Revision: 1.40 $
57  * @author Greg Wilkins (gregw)
58  */

59 public class Server extends HttpServer
60 {
61     static Log log = LogFactory.getLog(Server.class);
62     private String JavaDoc[] _webAppConfigurationClassNames =
63         new String JavaDoc[]{"org.mortbay.jetty.servlet.XMLConfiguration", "org.mortbay.jetty.servlet.JettyWebConfiguration"};
64     private String JavaDoc _configuration;
65     private String JavaDoc _rootWebApp;
66     private static ShutdownHookThread hookThread = new ShutdownHookThread();
67     
68     /* ------------------------------------------------------------ */
69     /** Constructor.
70      */

71     public Server()
72     {
73     }
74     
75     /* ------------------------------------------------------------ */
76     /** Constructor.
77      * @param configuration The filename or URL of the XML
78      * configuration file.
79      */

80     public Server(String JavaDoc configuration)
81         throws IOException JavaDoc
82     {
83         this(Resource.newResource(configuration).getURL());
84     }
85     
86     /* ------------------------------------------------------------ */
87     /** Constructor.
88      * @param configuration The filename or URL of the XML
89      * configuration file.
90      */

91     public Server(Resource configuration)
92         throws IOException JavaDoc
93     {
94         this(configuration.getURL());
95     }
96     
97     /* ------------------------------------------------------------ */
98     /** Constructor.
99      * @param configuration The filename or URL of the XML
100      * configuration file.
101      */

102     public Server(URL JavaDoc configuration)
103         throws IOException JavaDoc
104     {
105         _configuration=configuration.toString();
106         Server.hookThread.add(this);
107         try
108         {
109             XmlConfiguration config=new XmlConfiguration(configuration);
110             config.configure(this);
111         }
112         catch(IOException JavaDoc e)
113         {
114             throw e;
115         }
116         catch(InvocationTargetException JavaDoc e)
117         {
118             log.warn(LogSupport.EXCEPTION,e.getTargetException());
119             throw new IOException JavaDoc("Jetty configuration problem: "+e.getTargetException());
120         }
121         catch(Exception JavaDoc e)
122         {
123             log.warn(LogSupport.EXCEPTION,e);
124             throw new IOException JavaDoc("Jetty configuration problem: "+e);
125         }
126     }
127
128     /* ------------------------------------------------------------ */
129     public boolean getStopAtShutdown()
130     {
131         return hookThread.contains(this);
132     }
133     
134     /* ------------------------------------------------------------ */
135     public void setStopAtShutdown(boolean stop)
136     {
137         if (stop)
138             hookThread.add(this);
139         else
140             hookThread.remove(this);
141     }
142
143     /* ------------------------------------------------------------ */
144     /** Get the root webapp name.
145      * @return The name of the root webapp (eg. "root" for root.war).
146      */

147     public String JavaDoc getRootWebApp()
148     {
149         return _rootWebApp;
150     }
151     
152     /* ------------------------------------------------------------ */
153     /** Set the root webapp name.
154      * @param rootWebApp The name of the root webapp (eg. "root" for root.war).
155      */

156     public void setRootWebApp(String JavaDoc rootWebApp)
157     {
158         _rootWebApp = rootWebApp;
159     }
160     
161     /* ------------------------------------------------------------ */
162     /** Configure the server from an XML file.
163      * @param configuration The filename or URL of the XML
164      * configuration file.
165      */

166     public void configure(String JavaDoc configuration)
167         throws IOException JavaDoc
168     {
169
170         URL JavaDoc url=Resource.newResource(configuration).getURL();
171         if (_configuration!=null && _configuration.equals(url.toString()))
172             return;
173         if (_configuration!=null)
174             throw new IllegalStateException JavaDoc("Already configured with "+_configuration);
175         try
176         {
177             XmlConfiguration config=new XmlConfiguration(url);
178             _configuration=url.toString();
179             config.configure(this);
180         }
181         catch(IOException JavaDoc e)
182         {
183             throw e;
184         }
185         catch(Exception JavaDoc e)
186         {
187             log.warn(LogSupport.EXCEPTION,e);
188             throw new IOException JavaDoc("Jetty configuration problem: "+e);
189         }
190     }
191     
192     /* ------------------------------------------------------------ */
193     public String JavaDoc getConfiguration()
194     {
195         return _configuration;
196     }
197     
198     /* ------------------------------------------------------------ */
199     /** Create a new ServletHttpContext.
200      * Ths method is called by HttpServer to creat new contexts. Thus
201      * calls to addContext or getContext that result in a new Context
202      * being created will return an
203      * org.mortbay.jetty.servlet.ServletHttpContext instance.
204      * @return ServletHttpContext
205      */

206     protected HttpContext newHttpContext()
207     {
208         return new ServletHttpContext();
209     }
210     
211     /* ------------------------------------------------------------ */
212     /** Create a new WebApplicationContext.
213      * Ths method is called by Server to creat new contexts for web
214      * applications. Thus calls to addWebApplication that result in
215      * a new Context being created will return an correct class instance.
216      * Derived class can override this method to create instance of its
217      * own class derived from WebApplicationContext in case it needs more
218      * functionality.
219      * @param webApp The Web application directory or WAR file.
220      * @return WebApplicationContext
221      */

222     protected WebApplicationContext newWebApplicationContext(
223        String JavaDoc webApp
224     )
225     {
226         return new WebApplicationContext(webApp);
227     }
228
229     /* ------------------------------------------------------------ */
230     /** Add Web Application.
231      * @param contextPathSpec The context path spec. Which must be of
232      * the form / or /path/*
233      * @param webApp The Web application directory or WAR file.
234      * @return The WebApplicationContext
235      * @exception IOException
236      */

237     public WebApplicationContext addWebApplication(String JavaDoc contextPathSpec,
238                                                    String JavaDoc webApp)
239         throws IOException JavaDoc
240     {
241         return addWebApplication(null,contextPathSpec,webApp);
242     }
243     
244     /* ------------------------------------------------------------ */
245     /** Add Web Application.
246      * @param virtualHost Virtual host name or null
247      * @param contextPathSpec The context path spec. Which must be of
248      * the form / or /path/*
249      * @param webApp The Web application directory or WAR file.
250      * @return The WebApplicationContext
251      * @exception IOException
252      */

253     public WebApplicationContext addWebApplication(String JavaDoc virtualHost,
254                                                    String JavaDoc contextPathSpec,
255                                                    String JavaDoc webApp)
256         throws IOException JavaDoc
257     {
258         WebApplicationContext appContext =
259             newWebApplicationContext(webApp);
260         appContext.setContextPath(contextPathSpec);
261         addContext(virtualHost,appContext);
262         if(log.isDebugEnabled())log.debug("Web Application "+appContext+" added");
263         return appContext;
264     }
265
266     
267     /* ------------------------------------------------------------ */
268     /** Add Web Applications.
269      * Add auto webapplications to the server. The name of the
270      * webapp directory or war is used as the context name. If a
271      * webapp is called "root" it is added at "/".
272      * @param webapps Directory file name or URL to look for auto webapplication.
273      * @exception IOException
274      */

275     public WebApplicationContext[] addWebApplications(String JavaDoc webapps)
276         throws IOException JavaDoc
277     {
278         return addWebApplications(null,webapps,null,false);
279     }
280     
281     /* ------------------------------------------------------------ */
282     /** Add Web Applications.
283      * Add auto webapplications to the server. The name of the
284      * webapp directory or war is used as the context name. If the
285      * webapp matches the rootWebApp it is added as the "/" context.
286      * @param host Virtual host name or null
287      * @param webapps Directory file name or URL to look for auto webapplication.
288      * @exception IOException
289      */

290     public WebApplicationContext[] addWebApplications(String JavaDoc host,
291                                                       String JavaDoc webapps)
292         throws IOException JavaDoc
293     {
294         return addWebApplications(host,webapps,null,false);
295     }
296         
297     /* ------------------------------------------------------------ */
298     /** Add Web Applications.
299      * Add auto webapplications to the server. The name of the
300      * webapp directory or war is used as the context name. If the
301      * webapp matches the rootWebApp it is added as the "/" context.
302      * @param host Virtual host name or null
303      * @param webapps Directory file name or URL to look for auto
304      * webapplication.
305      * @param extract If true, extract war files
306      * @exception IOException
307      */

308     public WebApplicationContext[] addWebApplications(String JavaDoc host,
309                                                       String JavaDoc webapps,
310                                                       boolean extract)
311         throws IOException JavaDoc
312     {
313         return addWebApplications(host,webapps,null,extract);
314     }
315     
316     /* ------------------------------------------------------------ */
317     /** Add Web Applications.
318      * Add auto webapplications to the server. The name of the
319      * webapp directory or war is used as the context name. If the
320      * webapp matches the rootWebApp it is added as the "/" context.
321      * @param host Virtual host name or null
322      * @param webapps Directory file name or URL to look for auto
323      * webapplication.
324      * @param defaults The defaults xml filename or URL which is
325      * loaded before any in the web app. Must respect the web.dtd.
326      * If null the default defaults file is used. If the empty string, then
327      * no defaults file is used.
328      * @param extract If true, extract war files
329      * @exception IOException
330      */

331     public WebApplicationContext[] addWebApplications(String JavaDoc host,
332                                                       String JavaDoc webapps,
333                                                       String JavaDoc defaults,
334                                                       boolean extract)
335         throws IOException JavaDoc
336     {
337         return addWebApplications(host,webapps,defaults,extract,true);
338     }
339
340     /* ------------------------------------------------------------ */
341     /** Add Web Applications.
342      * Add auto webapplications to the server. The name of the
343      * webapp directory or war is used as the context name. If the
344      * webapp matches the rootWebApp it is added as the "/" context.
345      * @param host Virtual host name or null
346      * @param webapps Directory file name or URL to look for auto
347      * webapplication.
348      * @param defaults The defaults xml filename or URL which is
349      * loaded before any in the web app. Must respect the web.dtd.
350      * If null the default defaults file is used. If the empty string, then
351      * no defaults file is used.
352      * @param extract If true, extract war files
353      * @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications
354      * @exception IOException
355      */

356     public WebApplicationContext[] addWebApplications(String JavaDoc host,
357                                                       String JavaDoc webapps,
358                                                       String JavaDoc defaults,
359                                                       boolean extract,
360                               boolean java2CompliantClassLoader)
361         throws IOException JavaDoc
362     {
363         ArrayList JavaDoc wacs = new ArrayList JavaDoc();
364         Resource r=Resource.newResource(webapps);
365         if (!r.exists())
366             throw new IllegalArgumentException JavaDoc("No such webapps resource "+r);
367         
368         if (!r.isDirectory())
369             throw new IllegalArgumentException JavaDoc("Not directory webapps resource "+r);
370         
371         String JavaDoc[] files=r.list();
372         
373         for (int f=0;files!=null && f<files.length;f++)
374         {
375             String JavaDoc context=files[f];
376             
377             if (context.equalsIgnoreCase("CVS/") ||
378                 context.equalsIgnoreCase("CVS") ||
379                 context.startsWith("."))
380                 continue;
381
382             
383             String JavaDoc app = r.addPath(r.encode(files[f])).toString();
384             if (context.toLowerCase().endsWith(".war") ||
385                 context.toLowerCase().endsWith(".jar"))
386             {
387                 context=context.substring(0,context.length()-4);
388                 Resource unpacked=r.addPath(context);
389                 if (unpacked!=null && unpacked.exists() && unpacked.isDirectory())
390                     continue;
391             }
392             
393             if (_rootWebApp!=null && (context.equals(_rootWebApp)||context.equals(_rootWebApp+"/")))
394                 context="/";
395             else
396                 context="/"+context;
397
398             WebApplicationContext wac= addWebApplication(host,
399                                                          context,
400                                                          app);
401             wac.setExtractWAR(extract);
402         wac.setClassLoaderJava2Compliant(java2CompliantClassLoader);
403             if (defaults!=null)
404             {
405                 if (defaults.length()==0)
406                     wac.setDefaultsDescriptor(null);
407                 else
408                     wac.setDefaultsDescriptor(defaults);
409             }
410             wacs.add(wac);
411         }
412
413         return (WebApplicationContext[])wacs.toArray(new WebApplicationContext[wacs.size()]);
414     }
415
416     
417     /* ------------------------------------------------------------ */
418     /** setWebApplicationConfigurationClasses
419      * Set up the list of classnames of WebApplicationContext.Configuration
420      * implementations that will be applied to configure every webapp.
421      * The list can be overridden by individual WebApplicationContexts.
422      * @param configurationClasses
423      */

424     public void setWebApplicationConfigurationClassNames (String JavaDoc[] configurationClassNames)
425     {
426         if (configurationClassNames != null)
427         {
428             _webAppConfigurationClassNames = new String JavaDoc[configurationClassNames.length];
429             System.arraycopy(configurationClassNames, 0, _webAppConfigurationClassNames, 0, configurationClassNames.length);
430         }
431     }
432     
433     public String JavaDoc[] getWebApplicationConfigurationClassNames ()
434     {
435         return _webAppConfigurationClassNames;
436     }
437     
438     /* ------------------------------------------------------------ */
439     /* ------------------------------------------------------------ */
440     /* ------------------------------------------------------------ */
441     public static void main(String JavaDoc[] arg)
442     {
443         String JavaDoc[] dftConfig={"etc/jetty.xml"};
444         
445         if (arg.length==0)
446         {
447             log.info("Using default configuration: etc/jetty.xml");
448             arg=dftConfig;
449         }
450
451         final Server[] servers=new Server[arg.length];
452
453         // create and start the servers.
454
for (int i=0;i<arg.length;i++)
455         {
456             try
457             {
458                 servers[i] = new Server(arg[i]);
459                 servers[i].setStopAtShutdown(true);
460                 servers[i].start();
461
462             }
463             catch(Exception JavaDoc e)
464             {
465                 log.warn(LogSupport.EXCEPTION,e);
466             }
467         }
468         
469         // create and start the servers.
470
for (int i=0;i<arg.length;i++)
471         {
472             try{servers[i].join();}
473             catch (Exception JavaDoc e){LogSupport.ignore(log,e);}
474         }
475     }
476     
477    /**
478     * ShutdownHook thread for stopping all servers.
479     *
480     * Thread is hooked first time list of servers is changed.
481     */

482   private static class ShutdownHookThread extends Thread JavaDoc {
483     private boolean hooked = false;
484     private ArrayList JavaDoc servers = new ArrayList JavaDoc();
485
486     /**
487      * Hooks this thread for shutdown.
488      * @see java.lang.Runtime#addShutdownHook(java.lang.Thread)
489      */

490     private void createShutdownHook() {
491       if (!Boolean.getBoolean("JETTY_NO_SHUTDOWN_HOOK") && !hooked) {
492         try {
493           Method JavaDoc shutdownHook = java.lang.Runtime JavaDoc.class.getMethod("addShutdownHook",
494               new Class JavaDoc[] { java.lang.Thread JavaDoc.class });
495           shutdownHook.invoke(Runtime.getRuntime(), new Object JavaDoc[] { this });
496           this.hooked = true;
497         } catch (Exception JavaDoc e) {
498           if (log.isDebugEnabled()) log.debug("No shutdown hook in JVM ", e);
499         }
500       }
501     }
502
503     /**
504      * Add Server to servers list.
505      */

506     public boolean add(Server server) {
507       createShutdownHook();
508       return this.servers.add(server);
509     }
510     
511     /**
512      * Contains Server in servers list?
513      */

514     public boolean contains(Server server) {
515       return this.servers.contains(server);
516     }
517
518     /**
519      * Append all Servers from Collection
520      */

521     public boolean addAll(Collection JavaDoc c) {
522       createShutdownHook();
523       return this.servers.addAll(c);
524     }
525
526     /**
527      * Clear list of Servers.
528      */

529     public void clear() {
530       createShutdownHook();
531       this.servers.clear();
532     }
533
534     /**
535      * Remove Server from list.
536      */

537     public boolean remove(Server server) {
538       createShutdownHook();
539       return this.servers.remove(server);
540     }
541
542     /**
543      * Remove all Servers in Collection from list.
544      */

545     public boolean removeAll(Collection JavaDoc c) {
546       createShutdownHook();
547       return this.servers.removeAll(c);
548     }
549
550     /**
551      * Stop all Servers in list.
552      */

553     public void run() {
554       setName("Shutdown");
555       log.info("Shutdown hook executing");
556       Iterator JavaDoc it = servers.iterator();
557       while (it.hasNext()) {
558         Server svr = (Server) it.next();
559         if (svr == null) continue;
560         try {
561           svr.stop();
562         } catch (Exception JavaDoc e) {
563           log.warn(LogSupport.EXCEPTION, e);
564         }
565         log.info("Shutdown hook complete");
566
567         // Try to avoid JVM crash
568
try {
569           Thread.sleep(1000);
570         } catch (Exception JavaDoc e) {
571           log.warn(LogSupport.EXCEPTION, e);
572         }
573       }
574     }
575   }
576 }
577
578
579
580
581
Popular Tags