View Javadoc

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