Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mortbay/jetty/Server.java


1   // ========================================================================
2   // Copyright (c) 2002 Mort Bay Consulting (Australia) Pty. Ltd.
3   // $Id: Server.java,v 1.30 2003/10/31 12:17:19 gregwilkins Exp $
4   // ========================================================================
5   
6   package org.mortbay.jetty;
7   
8   import java.io.IOException;
9   import java.lang.reflect.Method;
10  import java.net.URL;
11  import java.util.ArrayList;
12  
13  import org.apache.commons.logging.Log;
14  import org.apache.commons.logging.LogFactory;
15  import org.mortbay.http.HttpContext;
16  import org.mortbay.http.HttpServer;
17  import org.mortbay.jetty.servlet.ServletHttpContext;
18  import org.mortbay.jetty.servlet.WebApplicationContext;
19  import org.mortbay.util.LogSupport;
20  import org.mortbay.util.Resource;
21  import org.mortbay.xml.XmlConfiguration;
22  
23  
24  /* ------------------------------------------------------------ */
25  /** The Jetty HttpServer.
26   *
27   * This specialization of org.mortbay.http.HttpServer adds knowledge
28   * about servlets and their specialized contexts.   It also included
29   * support for initialization from xml configuration files
30   * that follow the XmlConfiguration dtd.
31   *
32   * HttpContexts created by Server are of the type
33   * org.mortbay.jetty.servlet.ServletHttpContext unless otherwise
34   * specified.
35   *
36   * This class also provides a main() method which starts a server for
37   * each config file passed on the command line.  If the system
38   * property JETTY_NO_SHUTDOWN_HOOK is not set to true, then a shutdown
39   * hook is thread is registered to stop these servers.   
40   *
41   * @see org.mortbay.xml.XmlConfiguration
42   * @see org.mortbay.jetty.servlet.ServletHttpContext
43   * @version $Revision: 1.30 $
44   * @author Greg Wilkins (gregw)
45   */
46  public class Server extends HttpServer 
47  {
48      static Log log = LogFactory.getLog(Server.class);
49  
50      private String _configuration;
51      private String _rootWebApp;
52  
53      /* ------------------------------------------------------------ */
54      /** Constructor. 
55       */
56      public Server()
57      {}
58      
59      /* ------------------------------------------------------------ */
60      /** Constructor. 
61       * @param configuration The filename or URL of the XML
62       * configuration file.
63       */
64      public Server(String configuration)
65          throws IOException
66      {
67          this(Resource.newResource(configuration).getURL());
68      }
69      
70      /* ------------------------------------------------------------ */
71      /** Constructor. 
72       * @param configuration The filename or URL of the XML
73       * configuration file.
74       */
75      public Server(Resource configuration)
76          throws IOException
77      {
78          this(configuration.getURL());
79      }
80      
81      /* ------------------------------------------------------------ */
82      /** Constructor. 
83       * @param configuration The filename or URL of the XML
84       * configuration file.
85       */
86      public Server(URL configuration)
87          throws IOException
88      {
89          _configuration=configuration.toString();
90          try
91          {
92              XmlConfiguration config=new XmlConfiguration(configuration);
93              config.configure(this);
94          }
95          catch(IOException e)
96          {
97              throw e;
98          }
99          catch(Exception e)
100         {
101             log.warn(LogSupport.EXCEPTION,e);
102             throw new IOException("Jetty configuration problem: "+e);
103         }
104     }
105 
106     /* ------------------------------------------------------------ */
107     /** Get the root webapp name.
108      * @return The name of the root webapp (eg. "root" for root.war). 
109      */
110     public String getRootWebApp()
111     {
112         return _rootWebApp;
113     }
114     
115     /* ------------------------------------------------------------ */
116     /** Set the root webapp name.
117      * @param rootWebApp The name of the root webapp (eg. "root" for root.war). 
118      */
119     public void setRootWebApp(String rootWebApp)
120     {
121         _rootWebApp = rootWebApp;
122     }
123     
124     /* ------------------------------------------------------------ */
125     /**  Configure the server from an XML file.
126      * @param configuration The filename or URL of the XML
127      * configuration file.
128      */
129     public void configure(String configuration)
130         throws IOException
131     {
132 
133         URL url=Resource.newResource(configuration).getURL();
134         if (_configuration!=null && _configuration.equals(url.toString()))
135             return;
136         if (_configuration!=null)
137             throw new IllegalStateException("Already configured with "+_configuration);
138         try
139         {
140             XmlConfiguration config=new XmlConfiguration(url);
141             _configuration=url.toString();
142             config.configure(this);
143         }
144         catch(IOException e)
145         {
146             throw e;
147         }
148         catch(Exception e)
149         {
150             log.warn(LogSupport.EXCEPTION,e);
151             throw new IOException("Jetty configuration problem: "+e);
152         }
153     }
154     
155     /* ------------------------------------------------------------ */
156     public String getConfiguration()
157     {
158         return _configuration;
159     }
160     
161     /* ------------------------------------------------------------ */
162     /** Create a new ServletHttpContext.
163      * Ths method is called by HttpServer to creat new contexts.  Thus
164      * calls to addContext or getContext that result in a new Context
165      * being created will return an
166      * org.mortbay.jetty.servlet.ServletHttpContext instance.
167      * @return ServletHttpContext
168      */
169     protected HttpContext newHttpContext()
170     {
171         return new ServletHttpContext();
172     }
173     
174     /* ------------------------------------------------------------ */
175     /** Create a new WebApplicationContext.
176      * Ths method is called by Server to creat new contexts for web 
177      * applications.  Thus calls to addWebApplication that result in 
178      * a new Context being created will return an correct class instance.
179      * Derived class can override this method to create instance of its
180      * own class derived from WebApplicationContext in case it needs more
181      * functionality.
182      * @param webApp The Web application directory or WAR file.
183      * @return WebApplicationContext
184      */
185     protected WebApplicationContext newWebApplicationContext(
186        String webApp
187     )
188     {
189         return new WebApplicationContext(webApp);
190     }
191 
192     /* ------------------------------------------------------------ */
193     /** Add Web Application.
194      * @param contextPathSpec The context path spec. Which must be of
195      * the form / or /path/*
196      * @param webApp The Web application directory or WAR file.
197      * @return The WebApplicationContext
198      * @exception IOException 
199      */
200     public WebApplicationContext addWebApplication(String contextPathSpec,
201                                                    String webApp)
202         throws IOException
203     {
204         return addWebApplication(null,contextPathSpec,webApp);
205     }
206     
207     /* ------------------------------------------------------------ */
208     /** Add Web Application.
209      * @param virtualHost Virtual host name or null
210      * @param contextPathSpec The context path spec. Which must be of
211      * the form / or /path/*
212      * @param webApp The Web application directory or WAR file.
213      * @return The WebApplicationContext
214      * @exception IOException 
215      */
216     public WebApplicationContext addWebApplication(String virtualHost,
217                                                    String contextPathSpec,
218                                                    String webApp)
219         throws IOException
220     {
221         WebApplicationContext appContext =
222             newWebApplicationContext(webApp);
223         appContext.setContextPath(contextPathSpec);
224         addContext(virtualHost,appContext);
225         if(log.isDebugEnabled())log.debug("Web Application "+appContext+" added");
226         return appContext;
227     }
228 
229     
230     /* ------------------------------------------------------------ */
231     /**  Add Web Applications.
232      * Add auto webapplications to the server.  The name of the
233      * webapp directory or war is used as the context name. If a
234      * webapp is called "root" it is added at "/".
235      * @param webapps Directory file name or URL to look for auto webapplication.
236      * @exception IOException 
237      */
238     public WebApplicationContext[] addWebApplications(String webapps)
239         throws IOException
240     {
241         return addWebApplications(null,webapps,null,false);
242     }
243     
244     /* ------------------------------------------------------------ */
245     /**  Add Web Applications.
246      * Add auto webapplications to the server.  The name of the
247      * webapp directory or war is used as the context name. If the
248      * webapp matches the rootWebApp it is added as the "/" context.
249      * @param host Virtual host name or null
250      * @param webapps Directory file name or URL to look for auto webapplication.
251      * @exception IOException 
252      */
253     public WebApplicationContext[] addWebApplications(String host,
254                                                       String webapps)
255         throws IOException
256     {
257         return addWebApplications(host,webapps,null,false);
258     }
259         
260     /* ------------------------------------------------------------ */
261     /**  Add Web Applications.
262      * Add auto webapplications to the server.  The name of the
263      * webapp directory or war is used as the context name. If the
264      * webapp matches the rootWebApp it is added as the "/" context.
265      * @param host Virtual host name or null
266      * @param webapps Directory file name or URL to look for auto
267      * webapplication.
268      * @param extract If true, extract war files
269      * @exception IOException 
270      */
271     public WebApplicationContext[] addWebApplications(String host,
272                                                       String webapps,
273                                                       boolean extract)
274         throws IOException
275     {
276         return addWebApplications(host,webapps,null,extract);
277     }
278     
279     /* ------------------------------------------------------------ */
280     /**  Add Web Applications.
281      * Add auto webapplications to the server.  The name of the
282      * webapp directory or war is used as the context name. If the
283      * webapp matches the rootWebApp it is added as the "/" context.
284      * @param host Virtual host name or null
285      * @param webapps Directory file name or URL to look for auto
286      * webapplication.
287      * @param defaults The defaults xml filename or URL which is
288      * loaded before any in the web app. Must respect the web.dtd.
289      * If null the default defaults file is used. If the empty string, then
290      * no defaults file is used.
291      * @param extract If true, extract war files
292      * @exception IOException 
293      */
294     public WebApplicationContext[] addWebApplications(String host,
295                                                       String webapps,
296                                                       String defaults,
297                                                       boolean extract)
298         throws IOException
299     {
300         return addWebApplications(host,webapps,null,extract,true);
301     }
302 
303     /* ------------------------------------------------------------ */
304     /**  Add Web Applications.
305      * Add auto webapplications to the server.  The name of the
306      * webapp directory or war is used as the context name. If the
307      * webapp matches the rootWebApp it is added as the "/" context.
308      * @param host Virtual host name or null
309      * @param webapps Directory file name or URL to look for auto
310      * webapplication.
311      * @param defaults The defaults xml filename or URL which is
312      * loaded before any in the web app. Must respect the web.dtd.
313      * If null the default defaults file is used. If the empty string, then
314      * no defaults file is used.
315      * @param extract If true, extract war files
316      * @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications
317      * @exception IOException 
318      */
319     public WebApplicationContext[] addWebApplications(String host,
320                                                       String webapps,
321                                                       String defaults,
322                                                       boolean extract,
323                   boolean java2CompliantClassLoader)
324         throws IOException
325     {
326         ArrayList wacs = new ArrayList();
327         Resource r=Resource.newResource(webapps);
328         if (!r.exists())
329             throw new IllegalArgumentException("No such webapps resource "+r);
330         
331         if (!r.isDirectory())
332             throw new IllegalArgumentException("Not directory webapps resource "+r);
333         
334         String[] files=r.list();
335         
336         for (int f=0;files!=null && f<files.length;f++)
337         {
338             String context=files[f];
339             
340             if (context.equalsIgnoreCase("CVS/") ||
341                 context.equalsIgnoreCase("CVS") ||
342                 context.startsWith("."))
343                 continue;
344 
345             
346             String app = r.addPath(r.encode(files[f])).toString();
347             if (context.toLowerCase().endsWith(".war") ||
348                 context.toLowerCase().endsWith(".jar"))
349             {
350                 context=context.substring(0,context.length()-4);
351                 Resource unpacked=r.addPath(context);
352                 if (unpacked!=null && unpacked.exists() && unpacked.isDirectory())
353                     continue;
354             }
355             
356             if (_rootWebApp!=null && (context.equals(_rootWebApp)||context.equals(_rootWebApp+"/")))
357                 context="/";
358             else
359                 context="/"+context;
360 
361             WebApplicationContext wac= addWebApplication(host,
362                                                          context,
363                                                          app);
364             wac.setExtractWAR(extract);
365       wac.setClassLoaderJava2Compliant(java2CompliantClassLoader);
366             if (defaults!=null)
367             {
368                 if (defaults.length()==0)
369                     wac.setDefaultsDescriptor(null);
370                 else
371                     wac.setDefaultsDescriptor(defaults);
372             }
373             wacs.add(wac);
374         }
375 
376         return (WebApplicationContext[])wacs.toArray(new WebApplicationContext[wacs.size()]);
377     }
378 
379     
380     /* ------------------------------------------------------------ */
381     /* ------------------------------------------------------------ */
382     /* ------------------------------------------------------------ */
383     public static void main(String[] arg)
384     {
385         String[] dftConfig={"etc/jetty.xml"};
386         
387         if (arg.length==0)
388         {
389             log.info("Using default configuration: etc/jetty.xml");
390             arg=dftConfig;
391         }
392 
393         final Server[] servers=new Server[arg.length];
394 
395         // create and start the servers.
396         for (int i=0;i<arg.length;i++)
397         {
398             try
399             {
400                 servers[i] = new Server(arg[i]);
401                 servers[i].start();
402 
403             }
404             catch(Exception e)
405             {
406                 log.warn(LogSupport.EXCEPTION,e);
407             }
408         }
409 
410         // Create and add a shutdown hook
411         if (!Boolean.getBoolean("JETTY_NO_SHUTDOWN_HOOK"))
412         {
413             try
414             {
415                 Method shutdownHook=
416                     java.lang.Runtime.class
417                     .getMethod("addShutdownHook",new Class[] {java.lang.Thread.class});
418                 Thread hook = 
419                     new Thread() {
420                             public void run()
421                             {
422                                 setName("Shutdown");
423                                 log.info("Shutdown hook executing");
424                                 for (int i=0;i<servers.length;i++)
425                                 {
426             if (servers[i]==null) continue;
427                                     try{servers[i].stop();}
428                                     catch(Exception e){log.warn(LogSupport.EXCEPTION,e);}
429                                 }
430                                 
431                                 // Try to avoid JVM crash
432                                 try{Thread.sleep(1000);}
433                                 catch(Exception e){log.warn(LogSupport.EXCEPTION,e);}
434                             }
435                         };
436                 shutdownHook.invoke(Runtime.getRuntime(),
437                                     new Object[]{hook});
438             }
439             catch(Exception e)
440             {
441                 if(log.isDebugEnabled())log.debug("No shutdown hook in JVM ",e);
442             }
443         }
444 
445         // create and start the servers.
446         for (int i=0;i<arg.length;i++)
447         {
448             try{servers[i].join();}
449             catch (Exception e){LogSupport.ignore(log,e);}
450         }
451     }
452 }
453 
454 
455 
456