View Javadoc

1   // ========================================================================
2   // Copyright 2003-2005 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // Licensed under the Apache License, Version 2.0 (the "License");
5   // you may not use this file except in compliance with the License.
6   // You may obtain a copy of the License at
7   // http://www.apache.org/licenses/LICENSE-2.0
8   // Unless required by applicable law or agreed to in writing, software
9   // distributed under the License is distributed on an "AS IS" BASIS,
10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  // See the License for the specific language governing permissions and
12  // limitations under the License.
13  // ========================================================================
14  package org.mortbay.jetty.webapp;
15  
16  import java.io.File;
17  import java.io.IOException;
18  import java.net.MalformedURLException;
19  import java.net.URL;
20  import java.util.ArrayList;
21  import java.util.EventListener;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.Map;
25  
26  import javax.servlet.UnavailableException;
27  
28  import org.mortbay.jetty.Handler;
29  import org.mortbay.jetty.handler.ContextHandler;
30  import org.mortbay.jetty.security.Authenticator;
31  import org.mortbay.jetty.security.BasicAuthenticator;
32  import org.mortbay.jetty.security.ClientCertAuthenticator;
33  import org.mortbay.jetty.security.Constraint;
34  import org.mortbay.jetty.security.ConstraintMapping;
35  import org.mortbay.jetty.security.DigestAuthenticator;
36  import org.mortbay.jetty.security.FormAuthenticator;
37  import org.mortbay.jetty.security.UserRealm;
38  import org.mortbay.jetty.servlet.Dispatcher;
39  import org.mortbay.jetty.servlet.ErrorPageErrorHandler;
40  import org.mortbay.jetty.servlet.FilterHolder;
41  import org.mortbay.jetty.servlet.FilterMapping;
42  import org.mortbay.jetty.servlet.ServletHandler;
43  import org.mortbay.jetty.servlet.ServletHolder;
44  import org.mortbay.jetty.servlet.ServletMapping;
45  import org.mortbay.log.Log;
46  import org.mortbay.resource.Resource;
47  import org.mortbay.util.LazyList;
48  import org.mortbay.util.Loader;
49  import org.mortbay.xml.XmlParser;
50  /* ------------------------------------------------------------------------------- */
51  /**
52   * Configure by parsing default web.xml and web.xml
53   * 
54   * @author gregw
55   */
56  public class WebXmlConfiguration implements Configuration
57  {
58      protected WebAppContext _context;
59      protected XmlParser _xmlParser;
60      protected Object _filters;
61      protected Object _filterMappings;
62      protected Object _servlets;
63      protected Object _servletMappings;
64      protected Object _welcomeFiles;
65      protected Object _constraintMappings;
66      protected Object _listeners;
67      protected Map _errorPages;
68      protected boolean _hasJSP;
69      protected String _jspServletName;
70      protected String _jspServletClass;
71      protected boolean _defaultWelcomeFileList;
72      protected ServletHandler _servletHandler;
73      protected int _version;
74  
75      public WebXmlConfiguration()
76      {
77          // Get parser
78          _xmlParser=webXmlParser();
79      }
80  
81      public static XmlParser webXmlParser()
82      {
83          XmlParser xmlParser=new XmlParser();
84          //set up cache of DTDs and schemas locally
85          URL dtd22=WebAppContext.class.getResource("/javax/servlet/resources/web-app_2_2.dtd");
86          URL dtd23=WebAppContext.class.getResource("/javax/servlet/resources/web-app_2_3.dtd");
87          URL jsp20xsd=WebAppContext.class.getResource("/javax/servlet/resources/jsp_2_0.xsd");
88          URL jsp21xsd=WebAppContext.class.getResource("/javax/servlet/resources/jsp_2_1.xsd");
89          URL j2ee14xsd=WebAppContext.class.getResource("/javax/servlet/resources/j2ee_1_4.xsd");
90          URL webapp24xsd=WebAppContext.class.getResource("/javax/servlet/resources/web-app_2_4.xsd");
91          URL webapp25xsd=WebAppContext.class.getResource("/javax/servlet/resources/web-app_2_5.xsd");
92          URL schemadtd=WebAppContext.class.getResource("/javax/servlet/resources/XMLSchema.dtd");
93          URL xmlxsd=WebAppContext.class.getResource("/javax/servlet/resources/xml.xsd");
94          URL webservice11xsd=WebAppContext.class.getResource("/javax/servlet/resources/j2ee_web_services_client_1_1.xsd");
95          URL webservice12xsd=WebAppContext.class.getResource("/javax/servlet/resources/javaee_web_services_client_1_2.xsd");
96          URL datatypesdtd=WebAppContext.class.getResource("/javax/servlet/resources/datatypes.dtd");
97          xmlParser.redirectEntity("web-app_2_2.dtd",dtd22);
98          xmlParser.redirectEntity("-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",dtd22);
99          xmlParser.redirectEntity("web.dtd",dtd23);
100         xmlParser.redirectEntity("web-app_2_3.dtd",dtd23);
101         xmlParser.redirectEntity("-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",dtd23);
102         xmlParser.redirectEntity("XMLSchema.dtd",schemadtd);
103         xmlParser.redirectEntity("http://www.w3.org/2001/XMLSchema.dtd",schemadtd);
104         xmlParser.redirectEntity("-//W3C//DTD XMLSCHEMA 200102//EN",schemadtd);
105         xmlParser.redirectEntity("jsp_2_0.xsd",jsp20xsd);
106         xmlParser.redirectEntity("http://java.sun.com/xml/ns/j2ee/jsp_2_0.xsd",jsp20xsd);
107         xmlParser.redirectEntity("jsp_2_1.xsd",jsp21xsd);
108         xmlParser.redirectEntity("http://java.sun.com/xml/ns/javaee/jsp_2_1.xsd",jsp21xsd);
109         xmlParser.redirectEntity("j2ee_1_4.xsd",j2ee14xsd);
110         xmlParser.redirectEntity("http://java.sun.com/xml/ns/j2ee/j2ee_1_4.xsd",j2ee14xsd);
111         xmlParser.redirectEntity("web-app_2_4.xsd",webapp24xsd);
112         xmlParser.redirectEntity("http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd",webapp24xsd);
113         xmlParser.redirectEntity("web-app_2_5.xsd",webapp25xsd);
114         xmlParser.redirectEntity("http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd",webapp25xsd);
115         xmlParser.redirectEntity("xml.xsd",xmlxsd);
116         xmlParser.redirectEntity("http://www.w3.org/2001/xml.xsd",xmlxsd);
117         xmlParser.redirectEntity("datatypes.dtd",datatypesdtd);
118         xmlParser.redirectEntity("http://www.w3.org/2001/datatypes.dtd",datatypesdtd);
119         xmlParser.redirectEntity("j2ee_web_services_client_1_1.xsd",webservice11xsd);
120         xmlParser.redirectEntity("http://www.ibm.com/webservices/xsd/j2ee_web_services_client_1_1.xsd",webservice11xsd);
121         xmlParser.redirectEntity("javaee_web_services_client_1_2.xsd",webservice12xsd);
122         xmlParser.redirectEntity("http://www.ibm.com/webservices/xsd/javaee_web_services_client_1_2.xsd",webservice12xsd);
123 
124         return xmlParser;
125     }
126 
127     /* ------------------------------------------------------------------------------- */
128     public void setWebAppContext (WebAppContext context)
129     {
130         _context = context;
131     }
132 
133     /* ------------------------------------------------------------------------------- */
134     public WebAppContext getWebAppContext()
135     {
136         return _context;
137     }
138 
139     /* ------------------------------------------------------------------------------- */
140     /** Configure ClassPath.
141      */
142     public  void configureClassLoader()
143     throws Exception
144     {
145     }
146 
147     /* ------------------------------------------------------------------------------- */
148     public void configureDefaults() throws Exception
149     {
150         //cannot configure if the context is already started
151         if (_context.isStarted())
152         {
153             if (Log.isDebugEnabled()){Log.debug("Cannot configure webapp after it is started");}
154             return;
155         }
156         String defaultsDescriptor=getWebAppContext().getDefaultsDescriptor();
157         if(defaultsDescriptor!=null&&defaultsDescriptor.length()>0)
158         {
159             Resource dftResource=Resource.newSystemResource(defaultsDescriptor);
160             if(dftResource==null)
161                 dftResource=Resource.newResource(defaultsDescriptor);
162             configure(dftResource.getURL().toString());
163             _defaultWelcomeFileList=_welcomeFiles!=null;
164         }
165     }
166 
167     /* ------------------------------------------------------------------------------- */
168     public void configureWebApp() throws Exception
169     {
170         //cannot configure if the context is already started
171         if (_context.isStarted())
172         {
173             if (Log.isDebugEnabled())
174                 Log.debug("Cannot configure webapp after it is started");
175             return;
176         }
177 
178         URL webxml=findWebXml();
179         if (webxml!=null)
180             configure(webxml.toString());
181        
182         String overrideDescriptor=getWebAppContext().getOverrideDescriptor();
183         if(overrideDescriptor!=null&&overrideDescriptor.length()>0)
184         {
185             Resource orideResource=Resource.newSystemResource(overrideDescriptor);
186             if(orideResource==null)
187                 orideResource=Resource.newResource(overrideDescriptor);
188             _xmlParser.setValidating(false);
189             configure(orideResource.getURL().toString());
190         }
191     }
192 
193     /* ------------------------------------------------------------------------------- */
194     protected URL findWebXml() throws IOException, MalformedURLException
195     {
196         String descriptor=getWebAppContext().getDescriptor();
197         if (descriptor!=null)
198         {
199             Resource web= Resource.newResource(descriptor);
200             if (web.exists()&& !web.isDirectory())
201                 return web.getURL();
202         }
203 
204         Resource web_inf=getWebAppContext().getWebInf();
205         if(web_inf!=null && web_inf.isDirectory())
206         {
207             // do web.xml file
208             Resource web=web_inf.addPath("web.xml");
209             if(web.exists()) 
210                 return web.getURL();
211             Log.debug("No WEB-INF/web.xml in "+getWebAppContext().getWar()
212                     +". Serving files and default/dynamic servlets only");
213         }
214         return null;
215     }
216     
217     /* ------------------------------------------------------------------------------- */
218     public void configure(String webXml) throws Exception
219     {
220         XmlParser.Node config=null;
221         config=_xmlParser.parse(webXml);
222         initialize(config);
223     }
224 
225     /* ------------------------------------------------------------------------------- */
226     public void deconfigureWebApp() throws Exception
227     {
228         // TODO preserve any configuration that pre-existed.
229 
230         _servletHandler = getWebAppContext().getServletHandler();
231 
232         _servletHandler.setFilters(null);
233         _servletHandler.setFilterMappings(null);
234         _servletHandler.setServlets(null);
235         _servletHandler.setServletMappings(null);
236 
237         getWebAppContext().setEventListeners(null);
238         getWebAppContext().setWelcomeFiles(null);
239         if (getWebAppContext().getSecurityHandler() != null)
240             getWebAppContext().getSecurityHandler().setConstraintMappings(null);
241 
242         if (getWebAppContext().getErrorHandler() instanceof ErrorPageErrorHandler)
243             ((ErrorPageErrorHandler)getWebAppContext().getErrorHandler()).setErrorPages(null);
244 
245         // TODO remove classpaths from classloader
246     }
247 
248     /* ------------------------------------------------------------ */
249     protected void initialize(XmlParser.Node config) throws ClassNotFoundException,UnavailableException
250     {
251         _servletHandler = getWebAppContext().getServletHandler();
252         // Get any existing servlets and mappings.
253         _filters=LazyList.array2List(_servletHandler.getFilters());
254         _filterMappings=LazyList.array2List(_servletHandler.getFilterMappings());
255         _servlets=LazyList.array2List(_servletHandler.getServlets());
256         _servletMappings=LazyList.array2List(_servletHandler.getServletMappings());
257 
258         _listeners = LazyList.array2List(getWebAppContext().getEventListeners());
259         _welcomeFiles = LazyList.array2List(getWebAppContext().getWelcomeFiles());
260         _constraintMappings = LazyList.array2List(getWebAppContext().getSecurityHandler().getConstraintMappings());
261 
262         _errorPages = getWebAppContext().getErrorHandler() instanceof ErrorPageErrorHandler ?
263                         ((ErrorPageErrorHandler)getWebAppContext().getErrorHandler()).getErrorPages():null;
264 
265         String version=config.getAttribute("version","DTD");
266         if ("2.5".equals(version))
267             _version=25;
268         else if ("2.4".equals(version))
269             _version=24;
270         else if ("DTD".equals(version))
271         {
272             _version=23;
273             String dtd=_xmlParser.getDTD();
274             if (dtd!=null && dtd.indexOf("web-app_2_2")>=0)
275                 _version=22;
276         }
277                         
278         Iterator iter=config.iterator();
279         XmlParser.Node node=null;
280         while(iter.hasNext())
281         {
282             try
283             {
284                 Object o=iter.next();
285                 if(!(o instanceof XmlParser.Node))
286                     continue;
287                 node=(XmlParser.Node)o;
288                 String name=node.getTag();
289                 initWebXmlElement(name,node);
290             }
291             catch(ClassNotFoundException e)
292             {
293                 throw e;
294             }
295             catch(Exception e)
296             {
297                 Log.warn("Configuration problem at "+node+": "+e);
298                 Log.debug(e);
299                 throw new UnavailableException("Configuration problem");
300             }
301         }
302         
303         _servletHandler.setFilters((FilterHolder[])LazyList.toArray(_filters,FilterHolder.class));
304         _servletHandler.setFilterMappings((FilterMapping[])LazyList.toArray(_filterMappings,FilterMapping.class));
305         _servletHandler.setServlets((ServletHolder[])LazyList.toArray(_servlets,ServletHolder.class));
306         _servletHandler.setServletMappings((ServletMapping[])LazyList.toArray(_servletMappings,ServletMapping.class));
307 
308         getWebAppContext().setEventListeners((EventListener[])LazyList.toArray(_listeners,EventListener.class));
309         getWebAppContext().setWelcomeFiles((String[])LazyList.toArray(_welcomeFiles,String.class));
310         getWebAppContext().getSecurityHandler().setConstraintMappings((ConstraintMapping[])LazyList.toArray(_constraintMappings, ConstraintMapping.class));
311 
312         if (_errorPages!=null && getWebAppContext().getErrorHandler() instanceof ErrorPageErrorHandler)
313             ((ErrorPageErrorHandler)getWebAppContext().getErrorHandler()).setErrorPages(_errorPages);
314 
315     }
316 
317     /* ------------------------------------------------------------ */
318     /**
319      * Handle web.xml element. This method is called for each top level element within the web.xml
320      * file. It may be specialized by derived WebAppHandlers to provide additional
321      * configuration and handling.
322      *
323      * @param element The element name
324      * @param node The node containing the element.
325      */
326     protected void initWebXmlElement(String element,XmlParser.Node node) throws Exception
327     {
328         if("display-name".equals(element))
329             initDisplayName(node);
330         else if("description".equals(element))
331         {}
332         else if("context-param".equals(element))
333             initContextParam(node);
334         else if("servlet".equals(element))
335             initServlet(node);
336         else if("servlet-mapping".equals(element))
337             initServletMapping(node);
338         else if("session-config".equals(element))
339             initSessionConfig(node);
340         else if("mime-mapping".equals(element))
341             initMimeConfig(node);
342         else if("welcome-file-list".equals(element))
343             initWelcomeFileList(node);
344         else if("locale-encoding-mapping-list".equals(element))
345             initLocaleEncodingList(node);
346         else if("error-page".equals(element))
347             initErrorPage(node);
348         else if("taglib".equals(element))
349             initTagLib(node);
350         else if("jsp-config".equals(element))
351             initJspConfig(node);
352         else if("resource-ref".equals(element))
353         {
354             if(Log.isDebugEnabled())
355                 Log.debug("No implementation: "+node);
356         }
357         else if("security-constraint".equals(element))
358             initSecurityConstraint(node);
359         else if("login-config".equals(element))
360             initLoginConfig(node);
361         else if("security-role".equals(element))
362             initSecurityRole(node);
363         else if("filter".equals(element))
364             initFilter(node);
365         else if("filter-mapping".equals(element))
366             initFilterMapping(node);
367         else if("listener".equals(element))
368             initListener(node);
369         else if("distributable".equals(element))
370             initDistributable(node);
371         else
372         {
373             if(Log.isDebugEnabled())
374             {
375                 Log.debug("Element {} not handled in {}",element,this);
376                 Log.debug(node.toString());
377             }
378         }
379     }
380 
381     /* ------------------------------------------------------------ */
382     protected void initDisplayName(XmlParser.Node node)
383     {
384         getWebAppContext().setDisplayName(node.toString(false,true));
385     }
386 
387     /* ------------------------------------------------------------ */
388     protected void initContextParam(XmlParser.Node node)
389     {
390         String name=node.getString("param-name",false,true);
391         String value=node.getString("param-value",false,true);
392         if(Log.isDebugEnabled())
393             Log.debug("ContextParam: "+name+"="+value);
394         getWebAppContext().getInitParams().put(name, value);
395     }
396 
397     /* ------------------------------------------------------------ */
398     protected void initFilter(XmlParser.Node node)
399     {
400         String name=node.getString("filter-name",false,true);
401         FilterHolder holder= _servletHandler.getFilter(name);
402         if (holder==null)
403         {
404             holder=_servletHandler.newFilterHolder();
405             holder.setName(name);
406             _filters=LazyList.add(_filters,holder);
407         }
408         
409         String filter_class=node.getString("filter-class",false,true);
410         if (filter_class!=null)
411             holder.setClassName(filter_class);
412 
413         Iterator iter=node.iterator("init-param");
414         while(iter.hasNext())
415         {
416             XmlParser.Node paramNode=(XmlParser.Node)iter.next();
417             String pname=paramNode.getString("param-name",false,true);
418             String pvalue=paramNode.getString("param-value",false,true);
419             holder.setInitParameter(pname, pvalue);
420         }
421         
422     }
423 
424     /* ------------------------------------------------------------ */
425     protected void initFilterMapping(XmlParser.Node node)
426     {
427         String filter_name=node.getString("filter-name",false,true);
428 
429 
430 
431         FilterMapping mapping = new FilterMapping();
432 
433         mapping.setFilterName(filter_name);
434 
435         ArrayList paths = new ArrayList();
436         Iterator iter=node.iterator("url-pattern");
437         while(iter.hasNext())
438         {
439             String p=((XmlParser.Node)iter.next()).toString(false,true);
440             p=normalizePattern(p);
441             paths.add(p);
442         }
443         mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
444 
445 
446         ArrayList names = new ArrayList();
447         iter=node.iterator("servlet-name");
448         while(iter.hasNext())
449         {
450             String n=((XmlParser.Node)iter.next()).toString(false,true);
451             names.add(n);
452         }
453         mapping.setServletNames((String[])names.toArray(new String[names.size()]));
454 
455 
456         int dispatcher=Handler.DEFAULT;
457         iter=node.iterator("dispatcher");
458         while(iter.hasNext())
459         {
460             String d=((XmlParser.Node)iter.next()).toString(false,true);
461             dispatcher|=Dispatcher.type(d);
462         }
463         mapping.setDispatches(dispatcher);
464 
465         _filterMappings=LazyList.add(_filterMappings,mapping);
466     }
467 
468     /* ------------------------------------------------------------ */
469     protected String normalizePattern(String p)
470     {
471         if (p!=null && p.length()>0 && !p.startsWith("/") && !p.startsWith("*"))
472             return "/"+p;
473         return p;
474     }
475 
476     /* ------------------------------------------------------------ */
477     protected void initServlet(XmlParser.Node node) 
478     {
479         String id=node.getAttribute("id");
480 
481         // initialize holder
482         String servlet_name=node.getString("servlet-name",false,true);
483         ServletHolder holder = _servletHandler.getServlet(servlet_name);
484         if (holder==null)
485         {
486             holder=_servletHandler.newServletHolder();
487             holder.setName(servlet_name);
488             _servlets=LazyList.add(_servlets,holder);
489         }
490         
491         // init params
492         Iterator iParamsIter=node.iterator("init-param");
493         while(iParamsIter.hasNext())
494         {
495             XmlParser.Node paramNode=(XmlParser.Node)iParamsIter.next();
496             String pname=paramNode.getString("param-name",false,true);
497             String pvalue=paramNode.getString("param-value",false,true);
498             holder.setInitParameter(pname,pvalue);
499         }
500         
501         String servlet_class=node.getString("servlet-class",false,true);
502         
503         // Handle JSP
504         if (id!=null && id.equals("jsp"))
505         {
506             _jspServletName=servlet_name;
507             _jspServletClass=servlet_class;
508             try
509             {
510                 Loader.loadClass(this.getClass(), servlet_class);
511                 _hasJSP=true;
512             }
513             catch(ClassNotFoundException e)
514             {
515                 Log.info("NO JSP Support for {}, did not find {}",_context.getContextPath(),servlet_class);
516                 _hasJSP=false;
517                 _jspServletClass=servlet_class="org.mortbay.servlet.NoJspServlet";
518             }
519             if (holder.getInitParameter("scratchdir")==null)
520             {
521                 File tmp=getWebAppContext().getTempDirectory();
522                 File scratch=new File(tmp,"jsp");
523                 if (!scratch.exists())
524                     scratch.mkdir();
525                 holder.setInitParameter("scratchdir",scratch.getAbsolutePath());
526                 
527                 if ("?".equals(holder.getInitParameter("classpath")))
528                 {
529                     String classpath=getWebAppContext().getClassPath();
530                     Log.debug("classpath="+classpath);
531                     if (classpath!=null)
532                         holder.setInitParameter("classpath",classpath);
533                 }
534             }
535         }
536         if (servlet_class!=null)
537             holder.setClassName(servlet_class);
538         
539         
540         // Handler JSP file
541         String jsp_file=node.getString("jsp-file",false,true);
542         if (jsp_file!=null)
543         {
544             holder.setForcedPath(jsp_file);
545             holder.setClassName(_jspServletClass);
546         }
547 
548         // handle startup
549         XmlParser.Node startup=node.get("load-on-startup");
550         if(startup!=null)
551         {
552             String s=startup.toString(false,true).toLowerCase();
553             if(s.startsWith("t"))
554             {
555                 Log.warn("Deprecated boolean load-on-startup.  Please use integer");
556                 holder.setInitOrder(1);
557             }
558             else
559             {
560                 int order=0;
561                 try
562                 {
563                     if(s!=null&&s.trim().length()>0)
564                         order=Integer.parseInt(s);
565                 }
566                 catch(Exception e)
567                 {
568                     Log.warn("Cannot parse load-on-startup "+s+". Please use integer");
569                     Log.ignore(e);
570                 }
571                 holder.setInitOrder(order);
572             }
573         }
574         
575         Iterator sRefsIter=node.iterator("security-role-ref");
576         while(sRefsIter.hasNext())
577         {
578             XmlParser.Node securityRef=(XmlParser.Node)sRefsIter.next();
579             String roleName=securityRef.getString("role-name",false,true);
580             String roleLink=securityRef.getString("role-link",false,true);
581             if(roleName!=null&&roleName.length()>0&&roleLink!=null&&roleLink.length()>0)
582             {
583                 if(Log.isDebugEnabled())
584                     Log.debug("link role "+roleName+" to "+roleLink+" for "+this);
585                 holder.setUserRoleLink(roleName,roleLink);
586             }
587             else
588             {
589                 Log.warn("Ignored invalid security-role-ref element: "+"servlet-name="+holder.getName()+", "+securityRef);
590             }
591         }
592         
593         XmlParser.Node run_as=node.get("run-as");
594         if(run_as!=null)
595         {
596             String roleName=run_as.getString("role-name",false,true);
597             if(roleName!=null)
598                 holder.setRunAs(roleName);
599         }
600         
601     }
602 
603     /* ------------------------------------------------------------ */
604     protected void initServletMapping(XmlParser.Node node)
605     {
606         String servlet_name = node.getString("servlet-name",false,true);
607         ServletMapping mapping = new ServletMapping();
608         mapping.setServletName(servlet_name);
609 
610         ArrayList paths = new ArrayList();
611         Iterator iter=node.iterator("url-pattern");
612         while(iter.hasNext())
613         {
614             String p=((XmlParser.Node)iter.next()).toString(false,true);
615             p=normalizePattern(p);
616             paths.add(p);
617         }
618         mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
619 
620         _servletMappings=LazyList.add(_servletMappings,mapping);
621     }
622 
623     /* ------------------------------------------------------------ */
624     protected void initListener(XmlParser.Node node)
625     {
626         String className=node.getString("listener-class",false,true);
627         Object listener=null;
628         try
629         {
630             Class listenerClass=getWebAppContext().loadClass(className);
631             listener=newListenerInstance(listenerClass);
632             if(!(listener instanceof EventListener))
633             {
634                 Log.warn("Not an EventListener: "+listener);
635                 return;
636             }
637             _listeners=LazyList.add(_listeners, listener);
638         }
639         catch(Exception e)
640         {
641             Log.warn("Could not instantiate listener "+className,e);
642             return;
643         }
644     }
645     
646     /* ------------------------------------------------------------ */
647     protected Object newListenerInstance(Class clazz) 
648         throws InstantiationException, IllegalAccessException 
649     {
650                      return clazz.newInstance();
651     }
652     
653     /* ------------------------------------------------------------ */
654     protected void initDistributable(XmlParser.Node node)
655     {
656         // the element has no content, so its simple presence
657         // indicates that the webapp is distributable...
658         WebAppContext wac=getWebAppContext();
659         if (!wac.isDistributable())
660             wac.setDistributable(true);
661     }
662 
663     /* ------------------------------------------------------------ */
664     protected void initSessionConfig(XmlParser.Node node)
665     {
666         XmlParser.Node tNode=node.get("session-timeout");
667         if(tNode!=null)
668         {
669             int timeout=Integer.parseInt(tNode.toString(false,true));
670             getWebAppContext().getSessionHandler().getSessionManager().setMaxInactiveInterval(timeout*60);
671         }
672     }
673 
674     /* ------------------------------------------------------------ */
675     protected void initMimeConfig(XmlParser.Node node)
676     {
677         String extension=node.getString("extension",false,true);
678         if(extension!=null&&extension.startsWith("."))
679             extension=extension.substring(1);
680         String mimeType=node.getString("mime-type",false,true);
681         getWebAppContext().getMimeTypes().addMimeMapping(extension, mimeType);
682     }
683 
684     /* ------------------------------------------------------------ */
685     protected void initWelcomeFileList(XmlParser.Node node)
686     {
687         if (_defaultWelcomeFileList)
688             _welcomeFiles=null; // erase welcome files from default web.xml 
689         
690         _defaultWelcomeFileList=false;
691         Iterator iter=node.iterator("welcome-file");
692         while(iter.hasNext())
693         {
694             XmlParser.Node indexNode=(XmlParser.Node)iter.next();
695             String welcome=indexNode.toString(false,true);
696             _welcomeFiles=LazyList.add(_welcomeFiles,welcome);
697         }
698     }
699 
700     /* ------------------------------------------------------------ */
701     protected void initLocaleEncodingList(XmlParser.Node node)
702     {
703         Iterator iter=node.iterator("locale-encoding-mapping");
704         while(iter.hasNext())
705         {
706             XmlParser.Node mapping=(XmlParser.Node)iter.next();
707             String locale=mapping.getString("locale",false,true);
708             String encoding=mapping.getString("encoding",false,true);
709             getWebAppContext().addLocaleEncoding(locale,encoding);
710         }
711     }
712 
713     /* ------------------------------------------------------------ */
714     protected void initErrorPage(XmlParser.Node node)
715     {
716         String error=node.getString("error-code",false,true);
717         if(error==null||error.length()==0)
718             error=node.getString("exception-type",false,true);
719         String location=node.getString("location",false,true);
720 
721         if (_errorPages==null)
722             _errorPages=new HashMap();
723         _errorPages.put(error,location);
724     }
725 
726     /* ------------------------------------------------------------ */
727     protected void initTagLib(XmlParser.Node node)
728     {
729         String uri=node.getString("taglib-uri",false,true);
730         String location=node.getString("taglib-location",false,true);
731 
732         getWebAppContext().setResourceAlias(uri,location);
733     }
734 
735     /* ------------------------------------------------------------ */
736     protected void initJspConfig(XmlParser.Node node)
737     {
738         for (int i=0;i<node.size();i++)
739         {
740             Object o=node.get(i);
741             if (o instanceof XmlParser.Node && "taglib".equals(((XmlParser.Node)o).getTag()))
742                 initTagLib((XmlParser.Node)o);
743         }
744         
745         // Map URLs from jsp property groups to JSP servlet.
746         // this is more JSP stupidness creaping into the servlet spec
747         Iterator iter=node.iterator("jsp-property-group");
748         Object paths=null;
749         while(iter.hasNext())
750         {
751             XmlParser.Node group=(XmlParser.Node)iter.next();
752             Iterator iter2 = group.iterator("url-pattern");
753             while (iter2.hasNext())
754             {
755                 String url = ((XmlParser.Node) iter2.next()).toString(false, true);
756                 url=normalizePattern(url);
757                 paths=LazyList.add(paths,url);
758             }
759         }
760 
761         if (LazyList.size(paths)>0)
762         {
763             String jspName=getJSPServletName();
764             if (jspName!=null)
765             {
766                 ServletMapping mapping = new ServletMapping();
767                 mapping.setServletName(jspName);
768                 mapping.setPathSpecs(LazyList.toStringArray(paths));
769                 _servletMappings=LazyList.add(_servletMappings,mapping);
770             }
771         }
772     }
773 
774     /* ------------------------------------------------------------ */
775     protected void initSecurityConstraint(XmlParser.Node node)
776     {
777         Constraint scBase = new Constraint();
778 
779         try
780         {
781             XmlParser.Node auths = node.get("auth-constraint");
782             
783             if (auths != null)
784             {
785                 scBase.setAuthenticate(true);
786                 // auth-constraint
787                 Iterator iter = auths.iterator("role-name");
788                 Object roles=null;
789                 while (iter.hasNext())
790                 {
791                     String role = ((XmlParser.Node) iter.next()).toString(false, true);
792                     roles=LazyList.add(roles,role);
793                 }
794                 scBase.setRoles(LazyList.toStringArray(roles));
795             }
796             
797             XmlParser.Node data = node.get("user-data-constraint");
798             if (data != null)
799             {
800                 data = data.get("transport-guarantee");
801                 String guarantee = data.toString(false, true).toUpperCase();
802                 if (guarantee == null || guarantee.length() == 0 || "NONE".equals(guarantee))
803                     scBase.setDataConstraint(Constraint.DC_NONE);
804                 else if ("INTEGRAL".equals(guarantee))
805                     scBase.setDataConstraint(Constraint.DC_INTEGRAL);
806                 else if ("CONFIDENTIAL".equals(guarantee))
807                     scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
808                 else
809                 {
810                     Log.warn("Unknown user-data-constraint:" + guarantee);
811                     scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
812                 }
813             }
814             Iterator iter = node.iterator("web-resource-collection");
815             while (iter.hasNext())
816             {
817                 XmlParser.Node collection = (XmlParser.Node) iter.next();
818                 String name = collection.getString("web-resource-name", false, true);
819                 Constraint sc = (Constraint) scBase.clone();
820                 sc.setName(name);
821 
822 
823                 Iterator iter2 = collection.iterator("url-pattern");
824                 while (iter2.hasNext())
825                 {
826                     String url = ((XmlParser.Node) iter2.next()).toString(false, true);
827                     url=normalizePattern(url);
828                     
829                     Iterator iter3 = collection.iterator("http-method");
830                     if (iter3.hasNext())
831                     {
832                         while (iter3.hasNext())
833                         {
834                             String method=((XmlParser.Node) iter3.next()).toString(false, true);
835                             ConstraintMapping mapping = new ConstraintMapping();
836                             mapping.setMethod(method);
837                             mapping.setPathSpec(url);
838                             mapping.setConstraint(sc);
839                             _constraintMappings=LazyList.add(_constraintMappings,mapping);
840                         }
841                     }
842                     else
843                     {
844                         ConstraintMapping mapping = new ConstraintMapping();
845                         mapping.setPathSpec(url);
846                         mapping.setConstraint(sc);
847                         _constraintMappings=LazyList.add(_constraintMappings,mapping);
848                     }
849                 }
850             }
851         }
852         catch (CloneNotSupportedException e)
853         {
854             Log.warn(e);
855         }
856 
857     }
858 
859     /* ------------------------------------------------------------ */
860     protected void initLoginConfig(XmlParser.Node node)
861     {
862         XmlParser.Node method=node.get("auth-method");
863         FormAuthenticator _formAuthenticator=null;
864         if(method!=null)
865         {
866             Authenticator authenticator=null;
867             String m=method.toString(false,true);
868             if(Constraint.__FORM_AUTH.equals(m))
869                 authenticator=_formAuthenticator=new FormAuthenticator();
870             else if(Constraint.__BASIC_AUTH.equals(m))
871                 authenticator=new BasicAuthenticator();
872             else if(Constraint.__DIGEST_AUTH.equals(m))
873                 authenticator=new DigestAuthenticator();
874             else if(Constraint.__CERT_AUTH.equals(m))
875                 authenticator=new ClientCertAuthenticator();
876             else if(Constraint.__CERT_AUTH2.equals(m))
877                 authenticator=new ClientCertAuthenticator();
878             else
879                 Log.warn("UNKNOWN AUTH METHOD: "+m);
880             getWebAppContext().getSecurityHandler().setAuthenticator(authenticator);
881         }
882         XmlParser.Node name=node.get("realm-name");
883 
884         UserRealm[] realms=ContextHandler.getCurrentContext().getContextHandler().getServer().getUserRealms();
885 
886         String realm_name=name==null?"default":name.toString(false,true);
887 
888         UserRealm realm=getWebAppContext().getSecurityHandler().getUserRealm();
889         for (int i=0;realm==null && realms!=null && i<realms.length; i++)
890         {
891             if (realms[i]!=null && realm_name.equals(realms[i].getName()))
892                 realm=realms[i];
893         }
894 
895         if (realm==null)
896         {
897             String msg = "Unknown realm: "+realm_name;
898             Log.warn(msg);
899         }
900         else
901             getWebAppContext().getSecurityHandler().setUserRealm(realm);
902 
903         
904         XmlParser.Node formConfig=node.get("form-login-config");
905         if(formConfig!=null)
906         {
907             if(_formAuthenticator==null)
908                 Log.warn("FORM Authentication miss-configured");
909             else
910             {
911                 XmlParser.Node loginPage=formConfig.get("form-login-page");
912                 if(loginPage!=null)
913                     _formAuthenticator.setLoginPage(loginPage.toString(false,true));
914                 XmlParser.Node errorPage=formConfig.get("form-error-page");
915                 if(errorPage!=null)
916                 {
917                     String ep=errorPage.toString(false,true);
918                     _formAuthenticator.setErrorPage(ep);
919                 }
920             }
921         }
922     }
923 
924     /* ------------------------------------------------------------ */
925     protected void initSecurityRole(XmlParser.Node node)
926     {}
927 
928  
929     
930 
931     /* ------------------------------------------------------------ */
932     protected String getJSPServletName()
933     {
934         if (_jspServletName==null)
935         {
936             Map.Entry entry= _context.getServletHandler().getHolderEntry("test.jsp");
937             if (entry!=null)
938             {
939                 ServletHolder holder=(ServletHolder)entry.getValue();
940                 _jspServletName=holder.getName();
941             }
942         }
943         return _jspServletName;
944     }
945 }