//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.webapp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.DispatcherType;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
import javax.servlet.SessionTrackingMode;

import org.eclipse.jetty.security.ConstraintAware;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.servlet.BaseHolder.Source;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ListenerHolder;
import org.eclipse.jetty.servlet.ServletContextHandler.JspConfig;
import org.eclipse.jetty.servlet.ServletContextHandler.JspPropertyGroup;
import org.eclipse.jetty.servlet.ServletContextHandler.TagLib;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.xml.XmlParser;
import org.eclipse.jetty.xml.XmlParser.Node;

/**
 * StandardDescriptorProcessor
 *
 * Process a web.xml, web-defaults.xml, web-overrides.xml, web-fragment.xml.
 */
public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
    private static final Logger LOG = Log.getLogger(StandardDescriptorProcessor.class);

    public static final String STANDARD_PROCESSOR = "org.eclipse.jetty.standardDescriptorProcessor";

    final Map<String,FilterHolder> _filterHolderMap = new HashMap<>();
    final List<FilterHolder> _filterHolders = new ArrayList<>();
    final List<FilterMapping> _filterMappings = new ArrayList<>();
    final Map<String,ServletHolder> _servletHolderMap = new HashMap<>();
    final List<ServletHolder> _servletHolders = new ArrayList<>();
    final List<ServletMapping> _servletMappings = new ArrayList<>();

    public StandardDescriptorProcessor ()
    {
        try
        {
            registerVisitor("context-param", this.getClass().getMethod("visitContextParam", __signature));
            registerVisitor("display-name", this.getClass().getMethod("visitDisplayName", __signature));
            registerVisitor("servlet", this.getClass().getMethod("visitServlet",  __signature));
            registerVisitor("servlet-mapping", this.getClass().getMethod("visitServletMapping",  __signature));
            registerVisitor("session-config", this.getClass().getMethod("visitSessionConfig",  __signature));
            registerVisitor("mime-mapping", this.getClass().getMethod("visitMimeMapping",  __signature));
            registerVisitor("welcome-file-list", this.getClass().getMethod("visitWelcomeFileList",  __signature));
            registerVisitor("locale-encoding-mapping-list", this.getClass().getMethod("visitLocaleEncodingList",  __signature));
            registerVisitor("error-page", this.getClass().getMethod("visitErrorPage",  __signature));
            registerVisitor("taglib", this.getClass().getMethod("visitTagLib",  __signature));
            registerVisitor("jsp-config", this.getClass().getMethod("visitJspConfig",  __signature));
            registerVisitor("security-constraint", this.getClass().getMethod("visitSecurityConstraint",  __signature));
            registerVisitor("login-config", this.getClass().getMethod("visitLoginConfig",  __signature));
            registerVisitor("security-role", this.getClass().getMethod("visitSecurityRole",  __signature));
            registerVisitor("filter", this.getClass().getMethod("visitFilter",  __signature));
            registerVisitor("filter-mapping", this.getClass().getMethod("visitFilterMapping",  __signature));
            registerVisitor("listener", this.getClass().getMethod("visitListener",  __signature));
            registerVisitor("distributable", this.getClass().getMethod("visitDistributable",  __signature));
            registerVisitor("deny-uncovered-http-methods", this.getClass().getMethod("visitDenyUncoveredHttpMethods", __signature));
        }
        catch (Exception e)
        {
            throw new IllegalStateException(e);
        }
    }



    /**
     * {@inheritDoc}
     */
    public void start(WebAppContext context, Descriptor descriptor)
    {
        for (FilterHolder h : context.getServletHandler().getFilters())
        {
            _filterHolderMap.put(h.getName(),h);
            _filterHolders.add(h);
        }
        if (context.getServletHandler().getFilterMappings()!=null)
            _filterMappings.addAll(Arrays.asList(context.getServletHandler().getFilterMappings()));
        for (ServletHolder h : context.getServletHandler().getServlets())
        {
            _servletHolderMap.put(h.getName(),h);
            _servletHolders.add(h);
        }
        if (context.getServletHandler().getServletMappings()!=null)
            _servletMappings.addAll(Arrays.asList(context.getServletHandler().getServletMappings()));
    }


    /**
     * {@inheritDoc}
     */
    public void end(WebAppContext context, Descriptor descriptor)
    {
        context.getServletHandler().setFilters(_filterHolders.toArray(new FilterHolder[_filterHolderMap.size()]));
        context.getServletHandler().setServlets(_servletHolders.toArray(new ServletHolder[_servletHolderMap.size()]));

        context.getServletHandler().setFilterMappings(_filterMappings.toArray(new FilterMapping[_filterMappings.size()]));
        context.getServletHandler().setServletMappings(_servletMappings.toArray(new ServletMapping[_servletMappings.size()]));

        _filterHolderMap.clear();
        _filterHolders.clear();
        _filterMappings.clear();
        _servletHolderMap.clear();
        _servletHolders.clear();
        _servletMappings.clear();
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitContextParam (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        String name = node.getString("param-name", false, true);
        String value = node.getString("param-value", false, true);
        switch (context.getMetaData().getOrigin("context-param."+name))
        {
            case NotSet:
            {
                //just set it
                context.getInitParams().put(name, value);
                context.getMetaData().setOrigin("context-param."+name, descriptor);
                break;
            }
            case WebXml:
            case WebDefaults:
            case WebOverride:
            {
                //previously set by a web xml, allow other web xml files to override
                if (!(descriptor instanceof FragmentDescriptor))
                {
                    context.getInitParams().put(name, value);
                    context.getMetaData().setOrigin("context-param."+name, descriptor);
                }
                break;
            }
            case WebFragment:
            {
                //previously set by a web-fragment, this fragment's value must be the same
                if (descriptor instanceof FragmentDescriptor)
                {
                    if (!((String)context.getInitParams().get(name)).equals(value))
                        throw new IllegalStateException("Conflicting context-param "+name+"="+value+" in "+descriptor.getResource());
                }
                break;
            }
            default:
                LOG.warn(new Throwable()); // TODO throw ISE?
        }
        if (LOG.isDebugEnabled())
            LOG.debug("ContextParam: " + name + "=" + value);

    }


    /* ------------------------------------------------------------ */
    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitDisplayName(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        //Servlet Spec 3.0 p. 74 Ignore from web-fragments
        if (!(descriptor instanceof FragmentDescriptor))
        {
            context.setDisplayName(node.toString(false, true));
            context.getMetaData().setOrigin("display-name", descriptor);
        }
    }


    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitServlet(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        String id = node.getAttribute("id");

        // initialize holder
        String name = node.getString("servlet-name", false, true);
        ServletHolder holder = _servletHolderMap.get(name);

        //If servlet of that name does not already exist, create it.
        if (holder == null)
        {
            holder = context.getServletHandler().newServletHolder(Source.DESCRIPTOR);
            holder.setName(name);
            _servletHolderMap.put(name,holder);
            _servletHolders.add(holder);
        }

        // init params
        Iterator<?> iParamsIter = node.iterator("init-param");
        while (iParamsIter.hasNext())
        {
            XmlParser.Node paramNode = (XmlParser.Node) iParamsIter.next();
            String pname = paramNode.getString("param-name", false, true);
            String pvalue = paramNode.getString("param-value", false, true);
            String originName = name+".servlet.init-param."+pname;

            Descriptor originDescriptor = context.getMetaData().getOriginDescriptor(originName);
            switch (context.getMetaData().getOrigin(originName))
            {
                case NotSet:
                {
                    //init-param not already set, so set it
                    holder.setInitParameter(pname, pvalue);
                    context.getMetaData().setOrigin(originName, descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //previously set by a web xml descriptor, if we're parsing another web xml descriptor allow override as long as it is from a different descriptor
                    //ie ignore setting more than once within the same descriptor
                    //otherwise just ignore it
                    if (!(descriptor instanceof FragmentDescriptor) && (descriptor!=originDescriptor))
                    {
                        holder.setInitParameter(pname, pvalue);
                        context.getMetaData().setOrigin(originName, descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //previously set by a web-fragment, make sure that the value matches, otherwise its an error
                    if ((descriptor != originDescriptor) && !holder.getInitParameter(pname).equals(pvalue))
                        throw new IllegalStateException("Mismatching init-param "+pname+"="+pvalue+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }

        String servlet_class = node.getString("servlet-class", false, true);
        if ("".equals(servlet_class))
            servlet_class = null;

        //Handle the default jsp servlet instance
        if (id != null && id.equals("jsp") && servlet_class != null)
        {
            try
            {
                Loader.loadClass(this.getClass(), servlet_class);
            }
            catch (ClassNotFoundException e)
            {
                LOG.info("NO JSP Support for {}, did not find {}", context.getContextPath(), servlet_class);
                servlet_class = "org.eclipse.jetty.servlet.NoJspServlet";
            }
        }


        //Set the servlet-class
        if (servlet_class != null)
        {
            ((WebDescriptor)descriptor).addClassName(servlet_class);
            switch (context.getMetaData().getOrigin(name+".servlet.servlet-class"))
            {
                case NotSet:
                {
                    //the class of the servlet has not previously been set, so set it
                    holder.setClassName(servlet_class);
                    context.getMetaData().setOrigin(name+".servlet.servlet-class", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //the class of the servlet was set by a web xml file, only allow web-override/web-default to change it
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        holder.setClassName(servlet_class);
                        context.getMetaData().setOrigin(name+".servlet.servlet-class", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //the class was set by another fragment, ensure this fragment's value is the same
                    if (!servlet_class.equals(holder.getClassName()))
                        throw new IllegalStateException("Conflicting servlet-class "+servlet_class+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }

        // Handle JSP file
        String jsp_file = node.getString("jsp-file", false, true);
        if (jsp_file != null)
            holder.setForcedPath(jsp_file);

        // handle load-on-startup
        XmlParser.Node startup = node.get("load-on-startup");
        if (startup != null)
        {
            String s = startup.toString(false, true).toLowerCase(Locale.ENGLISH);
            int order = 0;
            if (s.startsWith("t"))
            {
                LOG.warn("Deprecated boolean load-on-startup.  Please use integer");
                order = 1;
            }
            else
            {
                try
                {
                    if (s != null && s.trim().length() > 0) order = Integer.parseInt(s);
                }
                catch (Exception e)
                {
                    LOG.warn("Cannot parse load-on-startup " + s + ". Please use integer");
                    LOG.ignore(e);
                }
            }

            switch (context.getMetaData().getOrigin(name+".servlet.load-on-startup"))
            {
                case NotSet:
                {
                    //not already set, so set it now
                    holder.setInitOrder(order);
                    context.getMetaData().setOrigin(name+".servlet.load-on-startup", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //if it was already set by a web xml descriptor and we're parsing another web xml descriptor, then override it
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        holder.setInitOrder(order);
                        context.getMetaData().setOrigin(name+".servlet.load-on-startup", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //it was already set by another fragment, if we're parsing a fragment, the values must match
                    if (order != holder.getInitOrder())
                        throw new IllegalStateException("Conflicting load-on-startup value in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }

        Iterator<Node> sRefsIter = node.iterator("security-role-ref");
        while (sRefsIter.hasNext())
        {
            XmlParser.Node securityRef = (XmlParser.Node) sRefsIter.next();
            String roleName = securityRef.getString("role-name", false, true);
            String roleLink = securityRef.getString("role-link", false, true);
            if (roleName != null && roleName.length() > 0 && roleLink != null && roleLink.length() > 0)
            {
                if (LOG.isDebugEnabled()) LOG.debug("link role " + roleName + " to " + roleLink + " for " + this);
                switch (context.getMetaData().getOrigin(name+".servlet.role-name."+roleName))
                {
                    case NotSet:
                    {
                        //set it
                        holder.setUserRoleLink(roleName, roleLink);
                        context.getMetaData().setOrigin(name+".servlet.role-name."+roleName, descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //only another web xml descriptor (web-default,web-override web.xml) can override an already set value
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            holder.setUserRoleLink(roleName, roleLink);
                            context.getMetaData().setOrigin(name+".servlet.role-name."+roleName, descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        if (!holder.getUserRoleLink(roleName).equals(roleLink))
                            throw new IllegalStateException("Conflicting role-link for role-name "+roleName+" for servlet "+name+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }
            else
            {
                LOG.warn("Ignored invalid security-role-ref element: " + "servlet-name=" + holder.getName() + ", " + securityRef);
            }
        }


        XmlParser.Node run_as = node.get("run-as");
        if (run_as != null)
        {
            String roleName = run_as.getString("role-name", false, true);

            if (roleName != null)
            {
                switch (context.getMetaData().getOrigin(name+".servlet.run-as"))
                {
                    case NotSet:
                    {
                        //run-as not set, so set it
                        holder.setRunAsRole(roleName);
                        context.getMetaData().setOrigin(name+".servlet.run-as", descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //run-as was set by a web xml, only allow it to be changed if we're currently parsing another web xml(override/default)
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            holder.setRunAsRole(roleName);
                            context.getMetaData().setOrigin(name+".servlet.run-as", descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //run-as was set by another fragment, this fragment must show the same value
                        if (!holder.getRunAsRole().equals(roleName))
                            throw new IllegalStateException("Conflicting run-as role "+roleName+" for servlet "+name+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }
        }

        String async=node.getString("async-supported",false,true);
        if (async!=null)
        {
            boolean val = async.length()==0||Boolean.valueOf(async);
            switch (context.getMetaData().getOrigin(name+".servlet.async-supported"))
            {
                case NotSet:
                {
                    //set it
                    holder.setAsyncSupported(val);
                    context.getMetaData().setOrigin(name+".servlet.async-supported", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //async-supported set by previous web xml descriptor, only allow override if we're parsing another web descriptor(web.xml/web-override.xml/web-default.xml)
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        holder.setAsyncSupported(val);
                        context.getMetaData().setOrigin(name+".servlet.async-supported", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //async-supported set by another fragment, this fragment's value must match
                    if (holder.isAsyncSupported() != val)
                        throw new IllegalStateException("Conflicting async-supported="+async+" for servlet "+name+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }

        String enabled = node.getString("enabled", false, true);
        if (enabled!=null)
        {
            boolean is_enabled = enabled.length()==0||Boolean.valueOf(enabled);
            switch (context.getMetaData().getOrigin(name+".servlet.enabled"))
            {
                case NotSet:
                {
                    //hasn't been set yet, so set it
                    holder.setEnabled(is_enabled);
                    context.getMetaData().setOrigin(name+".servlet.enabled", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //was set in a web xml descriptor, only allow override from another web xml descriptor
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        holder.setEnabled(is_enabled);
                        context.getMetaData().setOrigin(name+".servlet.enabled", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //was set by another fragment, this fragment's value must match
                    if (holder.isEnabled() != is_enabled)
                        throw new IllegalStateException("Conflicting value of servlet enabled for servlet "+name+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }

        /*
         * If multipart config not set, then set it and record it was by the web.xml or fragment.
         * If it was set by web.xml then if this is a fragment, ignore the settings.
         * If it was set by a fragment, if this is a fragment and the values are different, error!
         */
        XmlParser.Node multipart = node.get("multipart-config");
        if (multipart != null)
        {
            String location = multipart.getString("location", false, true);
            String maxFile = multipart.getString("max-file-size", false, true);
            String maxRequest = multipart.getString("max-request-size", false, true);
            String threshold = multipart.getString("file-size-threshold",false,true);
            MultipartConfigElement element = new MultipartConfigElement(location,
                                                                        (maxFile==null||"".equals(maxFile)?-1L:Long.parseLong(maxFile)),
                                                                        (maxRequest==null||"".equals(maxRequest)?-1L:Long.parseLong(maxRequest)),
                                                                        (threshold==null||"".equals(threshold)?0:Integer.parseInt(threshold)));

            switch (context.getMetaData().getOrigin(name+".servlet.multipart-config"))
            {
                case NotSet:
                {
                    //hasn't been set, so set it
                    holder.getRegistration().setMultipartConfig(element);
                    context.getMetaData().setOrigin(name+".servlet.multipart-config", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //was set in a web xml, only allow changes if we're parsing another web xml (web.xml/web-default.xml/web-override.xml)
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        holder.getRegistration().setMultipartConfig(element);
                        context.getMetaData().setOrigin(name+".servlet.multipart-config", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //another fragment set the value, this fragment's values must match exactly or it is an error
                    MultipartConfigElement cfg = ((ServletHolder.Registration)holder.getRegistration()).getMultipartConfig();

                    if (cfg.getMaxFileSize() != element.getMaxFileSize())
                        throw new IllegalStateException("Conflicting multipart-config max-file-size for servlet "+name+" in "+descriptor.getResource());
                    if (cfg.getMaxRequestSize() != element.getMaxRequestSize())
                        throw new IllegalStateException("Conflicting multipart-config max-request-size for servlet "+name+" in "+descriptor.getResource());
                    if (cfg.getFileSizeThreshold() != element.getFileSizeThreshold())
                        throw new IllegalStateException("Conflicting multipart-config file-size-threshold for servlet "+name+" in "+descriptor.getResource());
                    if ((cfg.getLocation() != null && (element.getLocation() == null || element.getLocation().length()==0))
                            || (cfg.getLocation() == null && (element.getLocation()!=null || element.getLocation().length() > 0)))
                        throw new IllegalStateException("Conflicting multipart-config location for servlet "+name+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }
    }



    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitServletMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        //Servlet Spec 3.0, p74
        //servlet-mappings are always additive, whether from web xml descriptors (web.xml/web-default.xml/web-override.xml) or web-fragments.
        //Maintenance update 3.0a to spec:
        //  Updated 8.2.3.g.v to say <servlet-mapping> elements are additive across web-fragments.
        //  <servlet-mapping> declared in web.xml overrides the mapping for the servlet specified in the web-fragment.xml

        String servlet_name = node.getString("servlet-name", false, true);
        switch (context.getMetaData().getOrigin(servlet_name+".servlet.mappings"))
        {
            case NotSet:
            {
                //no servlet mappings
                context.getMetaData().setOrigin(servlet_name+".servlet.mappings", descriptor);
                addServletMapping(servlet_name, node, context, descriptor);               
                break;
            }
            case WebDefaults:
            case WebXml:
            case WebOverride:
            {
                //previously set by a web xml descriptor, if we're parsing another web xml descriptor allow override
                //otherwise just ignore it as web.xml takes precedence (pg 8-81 5.g.vi)
                if (!(descriptor instanceof FragmentDescriptor))
                {
                   addServletMapping(servlet_name, node, context, descriptor);
                }
                break;
            }
            case WebFragment:
            {
                //mappings previously set by another web-fragment, so merge in this web-fragment's mappings
                addServletMapping(servlet_name, node, context, descriptor);
                break;
            }
            default:
                LOG.warn(new Throwable()); // TODO throw ISE?
        }
    }


    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitSessionConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        XmlParser.Node tNode = node.get("session-timeout");
        if (tNode != null)
        {
            int timeout = Integer.parseInt(tNode.toString(false, true));
            context.getSessionHandler().getSessionManager().setMaxInactiveInterval(timeout * 60);
        }

        //Servlet Spec 3.0
        // <tracking-mode>
        // this is additive across web-fragments
        Iterator<Node> iter = node.iterator("tracking-mode");
        if (iter.hasNext())
        { 
            Set<SessionTrackingMode> modes = null;
            Origin o = context.getMetaData().getOrigin("session.tracking-mode");
            switch (o)
            {
                case NotSet://not previously set, starting fresh
                case WebDefaults://previously set in web defaults, allow this descriptor to start fresh
                {
                    
                    modes = new HashSet<SessionTrackingMode>();
                    context.getMetaData().setOrigin("session.tracking-mode", descriptor);
                    break;
                }
                case WebXml:
                case WebFragment:
                case WebOverride:
                {
                    //if setting from an override descriptor, start afresh, otherwise add-in tracking-modes
                    if (descriptor instanceof OverrideDescriptor)
                        modes = new HashSet<SessionTrackingMode>();
                    else
                        modes = new HashSet<SessionTrackingMode>(context.getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes());
                    context.getMetaData().setOrigin("session.tracking-mode", descriptor);
                    break;
                }    
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?   
            }
            
            while (iter.hasNext())
            {
                XmlParser.Node mNode = (XmlParser.Node) iter.next();
                String trackMode = mNode.toString(false, true);
                modes.add(SessionTrackingMode.valueOf(trackMode));
            }
            context.getSessionHandler().getSessionManager().setSessionTrackingModes(modes);   
        }
       

        //Servlet Spec 3.0
        //<cookie-config>
        XmlParser.Node cookieConfig = node.get("cookie-config");
        if (cookieConfig != null)
        {
            //  <name>
            String name = cookieConfig.getString("name", false, true);
            if (name != null)
            {
                switch (context.getMetaData().getOrigin("cookie-config.name"))
                {
                    case NotSet:
                    {
                        //no <cookie-config><name> set yet, accept it
                        context.getSessionHandler().getSessionManager().getSessionCookieConfig().setName(name);
                        context.getMetaData().setOrigin("cookie-config.name", descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //<cookie-config><name> set in a web xml, only allow web-default/web-override to change
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            context.getSessionHandler().getSessionManager().getSessionCookieConfig().setName(name);
                            context.getMetaData().setOrigin("cookie-config.name", descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //a web-fragment set the value, all web-fragments must have the same value
                        if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getName().equals(name))
                            throw new IllegalStateException("Conflicting cookie-config name "+name+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }

            //  <domain>
            String domain = cookieConfig.getString("domain", false, true);
            if (domain != null)
            {
                switch (context.getMetaData().getOrigin("cookie-config.domain"))
                {
                    case NotSet:
                    {
                        //no <cookie-config><domain> set yet, accept it
                        context.getSessionHandler().getSessionManager().getSessionCookieConfig().setDomain(domain);
                        context.getMetaData().setOrigin("cookie-config.domain", descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //<cookie-config><domain> set in a web xml, only allow web-default/web-override to change
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            context.getSessionHandler().getSessionManager().getSessionCookieConfig().setDomain(domain);
                            context.getMetaData().setOrigin("cookie-config.domain", descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //a web-fragment set the value, all web-fragments must have the same value
                        if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getDomain().equals(domain))
                            throw new IllegalStateException("Conflicting cookie-config domain "+domain+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }

            //  <path>
            String path = cookieConfig.getString("path", false, true);
            if (path != null)
            {
                switch (context.getMetaData().getOrigin("cookie-config.path"))
                {
                    case NotSet:
                    {
                        //no <cookie-config><domain> set yet, accept it
                        context.getSessionHandler().getSessionManager().getSessionCookieConfig().setPath(path);
                        context.getMetaData().setOrigin("cookie-config.path", descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //<cookie-config><domain> set in a web xml, only allow web-default/web-override to change
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            context.getSessionHandler().getSessionManager().getSessionCookieConfig().setPath(path);
                            context.getMetaData().setOrigin("cookie-config.path", descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //a web-fragment set the value, all web-fragments must have the same value
                        if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getPath().equals(path))
                            throw new IllegalStateException("Conflicting cookie-config path "+path+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }

            //  <comment>
            String comment = cookieConfig.getString("comment", false, true);
            if (comment != null)
            {
                switch (context.getMetaData().getOrigin("cookie-config.comment"))
                {
                    case NotSet:
                    {
                        //no <cookie-config><comment> set yet, accept it
                        context.getSessionHandler().getSessionManager().getSessionCookieConfig().setComment(comment);
                        context.getMetaData().setOrigin("cookie-config.comment", descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //<cookie-config><comment> set in a web xml, only allow web-default/web-override to change
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            context.getSessionHandler().getSessionManager().getSessionCookieConfig().setComment(comment);
                            context.getMetaData().setOrigin("cookie-config.comment", descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //a web-fragment set the value, all web-fragments must have the same value
                        if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getComment().equals(comment))
                            throw new IllegalStateException("Conflicting cookie-config comment "+comment+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }

            //  <http-only>true/false
            tNode = cookieConfig.get("http-only");
            if (tNode != null)
            {
                boolean httpOnly = Boolean.parseBoolean(tNode.toString(false,true));
                switch (context.getMetaData().getOrigin("cookie-config.http-only"))
                {
                    case NotSet:
                    {
                        //no <cookie-config><http-only> set yet, accept it
                        context.getSessionHandler().getSessionManager().getSessionCookieConfig().setHttpOnly(httpOnly);
                        context.getMetaData().setOrigin("cookie-config.http-only", descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //<cookie-config><http-only> set in a web xml, only allow web-default/web-override to change
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            context.getSessionHandler().getSessionManager().getSessionCookieConfig().setHttpOnly(httpOnly);
                            context.getMetaData().setOrigin("cookie-config.http-only", descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //a web-fragment set the value, all web-fragments must have the same value
                        if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().isHttpOnly() != httpOnly)
                            throw new IllegalStateException("Conflicting cookie-config http-only "+httpOnly+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }

            //  <secure>true/false
            tNode = cookieConfig.get("secure");
            if (tNode != null)
            {
                boolean secure = Boolean.parseBoolean(tNode.toString(false,true));
                switch (context.getMetaData().getOrigin("cookie-config.secure"))
                {
                    case NotSet:
                    {
                        //no <cookie-config><secure> set yet, accept it
                        context.getSessionHandler().getSessionManager().getSessionCookieConfig().setSecure(secure);
                        context.getMetaData().setOrigin("cookie-config.secure", descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //<cookie-config><secure> set in a web xml, only allow web-default/web-override to change
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            context.getSessionHandler().getSessionManager().getSessionCookieConfig().setSecure(secure);
                            context.getMetaData().setOrigin("cookie-config.secure", descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //a web-fragment set the value, all web-fragments must have the same value
                        if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().isSecure() != secure)
                            throw new IllegalStateException("Conflicting cookie-config secure "+secure+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }

            //  <max-age>
            tNode = cookieConfig.get("max-age");
            if (tNode != null)
            {
                int maxAge = Integer.parseInt(tNode.toString(false,true));
                switch (context.getMetaData().getOrigin("cookie-config.max-age"))
                {
                    case NotSet:
                    {
                        //no <cookie-config><max-age> set yet, accept it
                        context.getSessionHandler().getSessionManager().getSessionCookieConfig().setMaxAge(maxAge);
                        context.getMetaData().setOrigin("cookie-config.max-age", descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //<cookie-config><max-age> set in a web xml, only allow web-default/web-override to change
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            context.getSessionHandler().getSessionManager().getSessionCookieConfig().setMaxAge(maxAge);
                            context.getMetaData().setOrigin("cookie-config.max-age", descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //a web-fragment set the value, all web-fragments must have the same value
                        if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().getMaxAge() != maxAge)
                            throw new IllegalStateException("Conflicting cookie-config max-age "+maxAge+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }
        }
    }



    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitMimeMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        String extension = node.getString("extension", false, true);
        if (extension != null && extension.startsWith("."))
            extension = extension.substring(1);
        String mimeType = node.getString("mime-type", false, true);
        if (extension != null)
        {
            switch (context.getMetaData().getOrigin("extension."+extension))
            {
                case NotSet:
                {
                    //no mime-type set for the extension yet
                    context.getMimeTypes().addMimeMapping(extension, mimeType);
                    context.getMetaData().setOrigin("extension."+extension, descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //a mime-type was set for the extension in a web xml, only allow web-default/web-override to change
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        context.getMimeTypes().addMimeMapping(extension, mimeType);
                        context.getMetaData().setOrigin("extension."+extension, descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //a web-fragment set the value, all web-fragments must have the same value
                    if (!context.getMimeTypes().getMimeByExtension("."+extension).equals(mimeType))
                        throw new IllegalStateException("Conflicting mime-type "+mimeType+" for extension "+extension+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitWelcomeFileList(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        switch (context.getMetaData().getOrigin("welcome-file-list"))
        {
            case NotSet:
            {
                context.getMetaData().setOrigin("welcome-file-list", descriptor);
                addWelcomeFiles(context,node);
                break;
            }
            case WebXml:
            {
                //web.xml set the welcome-file-list, all other descriptors then just merge in
                addWelcomeFiles(context,node);
                break;
            }
            case WebDefaults:
            {
                //if web-defaults set the welcome-file-list first and
                //we're processing web.xml then reset the welcome-file-list
                if (!(descriptor instanceof DefaultsDescriptor) && !(descriptor instanceof OverrideDescriptor) && !(descriptor instanceof FragmentDescriptor))
                {
                    context.setWelcomeFiles(new String[0]);
                }
                addWelcomeFiles(context,node);
                break;
            }
            case WebOverride:
            {
                //web-override set the list, all other descriptors just merge in
                addWelcomeFiles(context,node);
                break;
            }
            case WebFragment:
            {
                //A web-fragment first set the welcome-file-list. Other descriptors just add.
                addWelcomeFiles(context,node);
                break;
            }
            default:
                LOG.warn(new Throwable()); // TODO throw ISE?
        }
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitLocaleEncodingList(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        Iterator<XmlParser.Node> iter = node.iterator("locale-encoding-mapping");
        while (iter.hasNext())
        {
            XmlParser.Node mapping = iter.next();
            String locale = mapping.getString("locale", false, true);
            String encoding = mapping.getString("encoding", false, true);

            if (encoding != null)
            {
                switch (context.getMetaData().getOrigin("locale-encoding."+locale))
                {
                    case NotSet:
                    {
                        //no mapping for the locale yet, so set it
                        context.addLocaleEncoding(locale, encoding);
                        context.getMetaData().setOrigin("locale-encoding."+locale, descriptor);
                        break;
                    }
                    case WebXml:
                    case WebDefaults:
                    case WebOverride:
                    {
                        //a value was set in a web descriptor, only allow another web descriptor to change it (web-default/web-override)
                        if (!(descriptor instanceof FragmentDescriptor))
                        {
                            context.addLocaleEncoding(locale, encoding);
                            context.getMetaData().setOrigin("locale-encoding."+locale, descriptor);
                        }
                        break;
                    }
                    case WebFragment:
                    {
                        //a value was set by a web-fragment, all fragments must have the same value
                        if (!encoding.equals(context.getLocaleEncoding(locale)))
                            throw new IllegalStateException("Conflicting loacle-encoding mapping for locale "+locale+" in "+descriptor.getResource());
                        break;
                    }
                    default:
                        LOG.warn(new Throwable()); // TODO throw ISE?
                }
            }
        }
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitErrorPage(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        String error = node.getString("error-code", false, true);
        int code=0;
        if (error == null || error.length() == 0)
        {
            error = node.getString("exception-type", false, true);
            if (error == null || error.length() == 0)
                error = ErrorPageErrorHandler.GLOBAL_ERROR_PAGE;
        }
        else
            code=Integer.valueOf(error);

        String location = node.getString("location", false, true);
        ErrorPageErrorHandler handler = (ErrorPageErrorHandler)context.getErrorHandler();
        String originName = "error."+error;
        switch (context.getMetaData().getOrigin(originName))
        {
            case NotSet:
            {
                //no error page setup for this code or exception yet
                if (code>0)
                    handler.addErrorPage(code,location);
                else
                    handler.addErrorPage(error,location);
                context.getMetaData().setOrigin("error."+error, descriptor);
                break;
            }
            case WebXml:
            case WebDefaults:
            case WebOverride:
            {
                //an error page setup was set in web.xml/webdefault.xml/web-override.xml, only allow other web xml descriptors to override it
                if (!(descriptor instanceof FragmentDescriptor))
                {
                    //if set twice in the same descriptor, its an error
                    Descriptor originDescriptor = context.getMetaData().getOriginDescriptor(originName);
                    if (descriptor == originDescriptor)
                        throw new IllegalStateException("Duplicate error-page "+error+" at "+location);

                    if (code>0)
                        handler.addErrorPage(code,location);
                    else
                        handler.addErrorPage(error,location);
                    context.getMetaData().setOrigin("error."+error, descriptor);
                }
                break;
            }
            case WebFragment:
            {
                //another web fragment set the same error code or exception, if its different its an error
                if (!handler.getErrorPages().get(error).equals(location))
                    throw new IllegalStateException("Conflicting error-code or exception-type "+error+" in "+descriptor.getResource());
                break;
            }
            default:
                LOG.warn(new Throwable()); // TODO throw ISE?
        }

    }

    /**
     * @param context
     * @param node
     */
    public void addWelcomeFiles(WebAppContext context, XmlParser.Node node)
    {
        Iterator<XmlParser.Node> iter = node.iterator("welcome-file");
        while (iter.hasNext())
        {
            XmlParser.Node indexNode = (XmlParser.Node) iter.next();
            String welcome = indexNode.toString(false, true);

            //Servlet Spec 3.0 p. 74 welcome files are additive
            if (welcome != null && welcome.trim().length() > 0)
               context.setWelcomeFiles((String[])ArrayUtil.addToArray(context.getWelcomeFiles(),welcome,String.class));
        }
    }


    /**
     * @param servletName
     * @param node
     * @param context
     */
    public ServletMapping addServletMapping (String servletName, XmlParser.Node node, WebAppContext context, Descriptor descriptor)
    {
        ServletMapping mapping = new ServletMapping();
        mapping.setServletName(servletName);
        mapping.setDefault(descriptor instanceof DefaultsDescriptor);
        
        List<String> paths = new ArrayList<String>();
        Iterator<XmlParser.Node> iter = node.iterator("url-pattern");
        while (iter.hasNext())
        {
            String p = iter.next().toString(false, true);
            p = normalizePattern(p);
            
            //check if there is already a mapping for this path, and if there is && it is from a defaultdescriptor
            //remove it in favour of the new one      
            ListIterator<ServletMapping> listItor = _servletMappings.listIterator();
            boolean found = false;
            while (listItor.hasNext() && !found)
            {
                ServletMapping sm = listItor.next();
                if (sm.getPathSpecs() != null)
                {
                    for (String ps:sm.getPathSpecs())
                    {
                        if (p.equals(ps) && sm.isDefault())
                        {
                            if (LOG.isDebugEnabled()) LOG.debug("{} in mapping {} from defaults descriptor is overridden by ",ps,sm,servletName);
                            //remove ps from the path specs on the existing mapping
                            //if the mapping now has no pathspecs, remove it
                            String[] updatedPaths = ArrayUtil.removeFromArray(sm.getPathSpecs(), ps);
                            if (updatedPaths == null || updatedPaths.length == 0)
                            { 
                                if (LOG.isDebugEnabled()) LOG.debug("Removed mapping {} from defaults descriptor",sm);
                                listItor.remove();
                            }
                            else 
                            {
                                sm.setPathSpecs(updatedPaths);
                                if (LOG.isDebugEnabled()) LOG.debug("Removed path {} from mapping {} from defaults descriptor ", p,sm);
                            }
                            found = true;
                            break;
                        }
                    }
                }
            }
            
            paths.add(p);
            context.getMetaData().setOrigin(servletName+".servlet.mapping."+p, descriptor);
        }
        mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
        if (LOG.isDebugEnabled()) LOG.debug("Added mapping {} ",mapping);
        
      
      
        _servletMappings.add(mapping);
        return mapping;
    }

    /**
     * @param filterName
     * @param node
     * @param context
     */
    public void addFilterMapping (String filterName, XmlParser.Node node, WebAppContext context, Descriptor descriptor)
    {
        FilterMapping mapping = new FilterMapping();
        mapping.setFilterName(filterName);

        List<String> paths = new ArrayList<String>();
        Iterator<XmlParser.Node>  iter = node.iterator("url-pattern");
        while (iter.hasNext())
        {
            String p = iter.next().toString(false, true);
            p = normalizePattern(p);
            paths.add(p);
            context.getMetaData().setOrigin(filterName+".filter.mapping."+p, descriptor);
        }
        mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));

        List<String> names = new ArrayList<String>();
        iter = node.iterator("servlet-name");
        while (iter.hasNext())
        {
            String n = ((XmlParser.Node) iter.next()).toString(false, true);
            names.add(n);
        }
        mapping.setServletNames((String[]) names.toArray(new String[names.size()]));


        List<DispatcherType> dispatches = new ArrayList<DispatcherType>();
        iter=node.iterator("dispatcher");
        while(iter.hasNext())
        {
            String d=((XmlParser.Node)iter.next()).toString(false,true);
            dispatches.add(FilterMapping.dispatch(d));
        }

        if (dispatches.size()>0)
            mapping.setDispatcherTypes(EnumSet.copyOf(dispatches));

        _filterMappings.add(mapping);
    }


    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitTagLib(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        //Additive across web.xml and web-fragment.xml
        String uri = node.getString("taglib-uri", false, true);
        String location = node.getString("taglib-location", false, true);

        context.setResourceAlias(uri, location);

        JspConfig config = (JspConfig)context.getServletContext().getJspConfigDescriptor();
        if (config == null)
        {
            config = new JspConfig();
            context.getServletContext().setJspConfigDescriptor(config);
        }

        TagLib tl = new TagLib();
        tl.setTaglibLocation(location);
        tl.setTaglibURI(uri);
        config.addTaglibDescriptor(tl);
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitJspConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        //Additive across web.xml and web-fragment.xml
        JspConfig config = (JspConfig)context.getServletContext().getJspConfigDescriptor();
        if (config == null)
        {
           config = new JspConfig();
           context.getServletContext().setJspConfigDescriptor(config);
        }


        for (int i = 0; i < node.size(); i++)
        {
            Object o = node.get(i);
            if (o instanceof XmlParser.Node && "taglib".equals(((XmlParser.Node) o).getTag()))
                visitTagLib(context,descriptor, (XmlParser.Node) o);
        }

        // Map URLs from jsp property groups to JSP servlet.
        // this is more JSP stupidness creeping into the servlet spec
        Iterator<XmlParser.Node> iter = node.iterator("jsp-property-group");
        List<String> paths = new ArrayList<String>();
        while (iter.hasNext())
        {

            JspPropertyGroup jpg = new JspPropertyGroup();
            config.addJspPropertyGroup(jpg);
            XmlParser.Node group = iter.next();
            //url-patterns
            Iterator<XmlParser.Node> iter2 = group.iterator("url-pattern");
            while (iter2.hasNext())
            {
                String url = iter2.next().toString(false, true);
                url = normalizePattern(url);
                paths.add( url);
                jpg.addUrlPattern(url);
            }

            jpg.setElIgnored(group.getString("el-ignored", false, true));
            jpg.setPageEncoding(group.getString("page-encoding", false, true));
            jpg.setScriptingInvalid(group.getString("scripting-invalid", false, true));
            jpg.setIsXml(group.getString("is-xml", false, true));
            jpg.setDeferredSyntaxAllowedAsLiteral(group.getString("deferred-syntax-allowed-as-literal", false, true));
            jpg.setTrimDirectiveWhitespaces(group.getString("trim-directive-whitespaces", false, true));
            jpg.setDefaultContentType(group.getString("default-content-type", false, true));
            jpg.setBuffer(group.getString("buffer", false, true));
            jpg.setErrorOnUndeclaredNamespace(group.getString("error-on-undeclared-namespace", false, true));

            //preludes
            Iterator<XmlParser.Node> preludes = group.iterator("include-prelude");
            while (preludes.hasNext())
            {
                String prelude = preludes.next().toString(false, true);
                jpg.addIncludePrelude(prelude);
            }
            //codas
            Iterator<XmlParser.Node> codas = group.iterator("include-coda");
            while (codas.hasNext())
            {
                String coda = codas.next().toString(false, true);
                jpg.addIncludeCoda(coda);
            }

            if (LOG.isDebugEnabled()) LOG.debug(config.toString());
        }

        //add mappings to the jsp servlet from the property-group mappings
        if (paths.size() > 0)
        {
            ServletMapping mapping = new ServletMapping();
            mapping.setServletName("jsp");
            mapping.setPathSpecs(paths.toArray(new String[paths.size()]));
            _servletMappings.add(mapping);
        }
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitSecurityConstraint(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        Constraint scBase = new Constraint();

        //ServletSpec 3.0, p74 security-constraints, as minOccurs > 1, are additive
        //across fragments
        
        //TODO: need to remember origin of the constraints
        try
        {
            XmlParser.Node auths = node.get("auth-constraint");

            if (auths != null)
            {
                scBase.setAuthenticate(true);
                // auth-constraint
                Iterator<XmlParser.Node> iter = auths.iterator("role-name");
                List<String> roles = new ArrayList<String>();
                while (iter.hasNext())
                {
                    String role = iter.next().toString(false, true);
                    roles.add(role);
                }
                scBase.setRoles(roles.toArray(new String[roles.size()]));
            }

            XmlParser.Node data = node.get("user-data-constraint");
            if (data != null)
            {
                data = data.get("transport-guarantee");
                String guarantee = data.toString(false, true).toUpperCase(Locale.ENGLISH);
                if (guarantee == null || guarantee.length() == 0 || "NONE".equals(guarantee))
                    scBase.setDataConstraint(Constraint.DC_NONE);
                else if ("INTEGRAL".equals(guarantee))
                    scBase.setDataConstraint(Constraint.DC_INTEGRAL);
                else if ("CONFIDENTIAL".equals(guarantee))
                    scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
                else
                {
                    LOG.warn("Unknown user-data-constraint:" + guarantee);
                    scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
                }
            }
            Iterator<XmlParser.Node> iter = node.iterator("web-resource-collection");
            while (iter.hasNext())
            {
                XmlParser.Node collection =  iter.next();
                String name = collection.getString("web-resource-name", false, true);
                Constraint sc = (Constraint) scBase.clone();
                sc.setName(name);

                Iterator<XmlParser.Node> iter2 = collection.iterator("url-pattern");
                while (iter2.hasNext())
                {
                    String url = iter2.next().toString(false, true);
                    url = normalizePattern(url);
                    //remember origin so we can process ServletRegistration.Dynamic.setServletSecurityElement() correctly
                    context.getMetaData().setOrigin("constraint.url."+url, descriptor);
                    
                    Iterator<XmlParser.Node> methods = collection.iterator("http-method");
                    Iterator<XmlParser.Node> ommissions = collection.iterator("http-method-omission");
                   
                    if (methods.hasNext())
                    {
                        if (ommissions.hasNext())
                            throw new IllegalStateException ("web-resource-collection cannot contain both http-method and http-method-omission");
                        
                        //configure all the http-method elements for each url
                        while (methods.hasNext())
                        {
                            String method = ((XmlParser.Node) methods.next()).toString(false, true);
                            ConstraintMapping mapping = new ConstraintMapping();
                            mapping.setMethod(method);
                            mapping.setPathSpec(url);
                            mapping.setConstraint(sc);                                                      
                            ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
                        }
                    }
                    else if (ommissions.hasNext())
                    {
                        //configure all the http-method-omission elements for each url
                        // TODO use the array
                        while (ommissions.hasNext())
                        {
                            String method = ((XmlParser.Node)ommissions.next()).toString(false, true);
                            ConstraintMapping mapping = new ConstraintMapping();
                            mapping.setMethodOmissions(new String[]{method});
                            mapping.setPathSpec(url);
                            mapping.setConstraint(sc);
                            ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
                        }
                    }
                    else
                    {
                        //No http-methods or http-method-omissions specified, the constraint applies to all
                        ConstraintMapping mapping = new ConstraintMapping();
                        mapping.setPathSpec(url);
                        mapping.setConstraint(sc);
                        ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
                    }
                } 
            }
        }
        catch (CloneNotSupportedException e)
        {
            LOG.warn(e);
        }
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     * @throws Exception
     */
    public void visitLoginConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node) throws Exception
    {
        //ServletSpec 3.0 p74 says elements present 0/1 time if specified in web.xml take
        //precendece over any web-fragment. If not specified in web.xml, then if specified
        //in a web-fragment must be the same across all web-fragments.
        XmlParser.Node method = node.get("auth-method");
        if (method != null)
        {
            //handle auth-method merge
            switch (context.getMetaData().getOrigin("auth-method"))
            {
                case NotSet:
                {
                    //not already set, so set it now
                    context.getSecurityHandler().setAuthMethod(method.toString(false, true));
                    context.getMetaData().setOrigin("auth-method", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //if it was already set by a web xml descriptor and we're parsing another web xml descriptor, then override it
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        context.getSecurityHandler().setAuthMethod(method.toString(false, true));
                        context.getMetaData().setOrigin("auth-method", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //it was already set by another fragment, if we're parsing a fragment, the values must match
                    if (!context.getSecurityHandler().getAuthMethod().equals(method.toString(false, true)))
                        throw new IllegalStateException("Conflicting auth-method value in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }

            //handle realm-name merge
            XmlParser.Node name = node.get("realm-name");
            String nameStr = (name == null ? "default" : name.toString(false, true));
            switch (context.getMetaData().getOrigin("realm-name"))
            {
                case NotSet:
                {
                    //no descriptor has set the realm-name yet, so set it
                    context.getSecurityHandler().setRealmName(nameStr);
                    context.getMetaData().setOrigin("realm-name", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //set by a web xml file (web.xml/web-default.xm/web-override.xml), only allow it to be changed by another web xml file
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        context.getSecurityHandler().setRealmName(nameStr);
                        context.getMetaData().setOrigin("realm-name", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //a fragment set it, and we must be parsing another fragment, so the values must match
                    if (!context.getSecurityHandler().getRealmName().equals(nameStr))
                        throw new IllegalStateException("Conflicting realm-name value in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }

            if (Constraint.__FORM_AUTH.equalsIgnoreCase(context.getSecurityHandler().getAuthMethod()))
            {
                XmlParser.Node formConfig = node.get("form-login-config");
                if (formConfig != null)
                {
                    String loginPageName = null;
                    XmlParser.Node loginPage = formConfig.get("form-login-page");
                    if (loginPage != null)
                        loginPageName = loginPage.toString(false, true);
                    String errorPageName = null;
                    XmlParser.Node errorPage = formConfig.get("form-error-page");
                    if (errorPage != null)
                        errorPageName = errorPage.toString(false, true);

                    //handle form-login-page
                    switch (context.getMetaData().getOrigin("form-login-page"))
                    {
                        case NotSet:
                        {
                            //Never been set before, so accept it
                            context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
                            context.getMetaData().setOrigin("form-login-page",descriptor);
                            break;
                        }
                        case WebXml:
                        case WebDefaults:
                        case WebOverride:
                        {
                            //a web xml descriptor previously set it, only allow another one to change it (web.xml/web-default.xml/web-override.xml)
                            if (!(descriptor instanceof FragmentDescriptor))
                            {
                                context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
                                context.getMetaData().setOrigin("form-login-page",descriptor);
                            }
                            break;
                        }
                        case WebFragment:
                        {
                            //a web-fragment previously set it. We must be parsing yet another web-fragment, so the values must agree
                            if (!context.getSecurityHandler().getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE).equals(loginPageName))
                                throw new IllegalStateException("Conflicting form-login-page value in "+descriptor.getResource());
                            break;
                        }
                        default:
                            LOG.warn(new Throwable()); // TODO throw ISE?
                    }

                    //handle form-error-page
                    switch (context.getMetaData().getOrigin("form-error-page"))
                    {
                        case NotSet:
                        {
                            //Never been set before, so accept it
                            context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
                            context.getMetaData().setOrigin("form-error-page",descriptor);
                            break;
                        }
                        case WebXml:
                        case WebDefaults:
                        case WebOverride:
                        {
                            //a web xml descriptor previously set it, only allow another one to change it (web.xml/web-default.xml/web-override.xml)
                            if (!(descriptor instanceof FragmentDescriptor))
                            {
                                context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
                                context.getMetaData().setOrigin("form-error-page",descriptor);
                            }
                            break;
                        }
                        case WebFragment:
                        {
                            //a web-fragment previously set it. We must be parsing yet another web-fragment, so the values must agree
                            if (!context.getSecurityHandler().getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE).equals(errorPageName))
                                throw new IllegalStateException("Conflicting form-error-page value in "+descriptor.getResource());
                            break;
                        }
                        default:
                            LOG.warn(new Throwable()); // TODO throw ISE?
                    }
                }
                else
                {
                    throw new IllegalStateException("!form-login-config");
                }
            }
        }
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitSecurityRole(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        //ServletSpec 3.0, p74 elements with multiplicity >1 are additive when merged
        XmlParser.Node roleNode = node.get("role-name");
        String role = roleNode.toString(false, true);
        ((ConstraintAware)context.getSecurityHandler()).addRole(role);
    }


    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitFilter(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        String name = node.getString("filter-name", false, true);
        FilterHolder holder = _filterHolderMap.get(name);
        if (holder == null)
        {
            holder = context.getServletHandler().newFilterHolder(Source.DESCRIPTOR);
            holder.setName(name);
            _filterHolderMap.put(name,holder);
            _filterHolders.add(holder);
        }

        String filter_class = node.getString("filter-class", false, true);
        if (filter_class != null)
        {
            ((WebDescriptor)descriptor).addClassName(filter_class);

            switch (context.getMetaData().getOrigin(name+".filter.filter-class"))
            {
                case NotSet:
                {
                    //no class set yet
                    holder.setClassName(filter_class);
                    context.getMetaData().setOrigin(name+".filter.filter-class", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //filter class was set in web.xml, only allow other web xml descriptors (override/default) to change it
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        holder.setClassName(filter_class);
                        context.getMetaData().setOrigin(name+".filter.filter-class", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //the filter class was set up by a web fragment, all fragments must be the same
                    if (!holder.getClassName().equals(filter_class))
                        throw new IllegalStateException("Conflicting filter-class for filter "+name+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }

        Iterator<XmlParser.Node>  iter = node.iterator("init-param");
        while (iter.hasNext())
        {
            XmlParser.Node paramNode = iter.next();
            String pname = paramNode.getString("param-name", false, true);
            String pvalue = paramNode.getString("param-value", false, true);

            switch (context.getMetaData().getOrigin(name+".filter.init-param."+pname))
            {
                case NotSet:
                {
                    //init-param not already set, so set it
                    holder.setInitParameter(pname, pvalue);
                    context.getMetaData().setOrigin(name+".filter.init-param."+pname, descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //previously set by a web xml descriptor, if we're parsing another web xml descriptor allow override
                    //otherwise just ignore it
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        holder.setInitParameter(pname, pvalue);
                        context.getMetaData().setOrigin(name+".filter.init-param."+pname, descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //previously set by a web-fragment, make sure that the value matches, otherwise its an error
                    if (!holder.getInitParameter(pname).equals(pvalue))
                        throw new IllegalStateException("Mismatching init-param "+pname+"="+pvalue+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }

        String async=node.getString("async-supported",false,true);
        if (async!=null)
            holder.setAsyncSupported(async.length()==0||Boolean.valueOf(async));
        if (async!=null)
        {
            boolean val = async.length()==0||Boolean.valueOf(async);
            switch (context.getMetaData().getOrigin(name+".filter.async-supported"))
            {
                case NotSet:
                {
                    //set it
                    holder.setAsyncSupported(val);
                    context.getMetaData().setOrigin(name+".filter.async-supported", descriptor);
                    break;
                }
                case WebXml:
                case WebDefaults:
                case WebOverride:
                {
                    //async-supported set by previous web xml descriptor, only allow override if we're parsing another web descriptor(web.xml/web-override.xml/web-default.xml)
                    if (!(descriptor instanceof FragmentDescriptor))
                    {
                        holder.setAsyncSupported(val);
                        context.getMetaData().setOrigin(name+".filter.async-supported", descriptor);
                    }
                    break;
                }
                case WebFragment:
                {
                    //async-supported set by another fragment, this fragment's value must match
                    if (holder.isAsyncSupported() != val)
                        throw new IllegalStateException("Conflicting async-supported="+async+" for filter "+name+" in "+descriptor.getResource());
                    break;
                }
                default:
                    LOG.warn(new Throwable()); // TODO throw ISE?
            }
        }
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitFilterMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        //Servlet Spec 3.0, p74
        //filter-mappings are always additive, whether from web xml descriptors (web.xml/web-default.xml/web-override.xml) or web-fragments.
        //Maintenance update 3.0a to spec:
        //  Updated 8.2.3.g.v to say <servlet-mapping> elements are additive across web-fragments.
        String filter_name = node.getString("filter-name", false, true);
        switch (context.getMetaData().getOrigin(filter_name+".filter.mappings"))
        {
            case NotSet:
            {
                //no filtermappings for this filter yet defined
                context.getMetaData().setOrigin(filter_name+".filter.mappings", descriptor);
                addFilterMapping(filter_name, node, context, descriptor);
                break;
            }
            case WebDefaults:
            case WebOverride:
            case WebXml:
            {
                //filter mappings defined in a web xml file. If we're processing a fragment, we ignore filter mappings.
                if (!(descriptor instanceof FragmentDescriptor))
                {
                   addFilterMapping(filter_name, node, context, descriptor);
                }
                break;
            }
            case WebFragment:
            {
                //filter mappings first defined in a web-fragment, allow other fragments to add
                addFilterMapping(filter_name, node, context, descriptor);
                break;
            }
            default:
                LOG.warn(new Throwable()); // TODO throw ISE?
        }
    }


    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitListener(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        String className = node.getString("listener-class", false, true);
        EventListener listener = null;
        try
        {
            if (className != null && className.length()> 0)
            {
                //Servlet Spec 3.0 p 74
                //Duplicate listener declarations don't result in duplicate listener instances
                EventListener[] listeners=context.getEventListeners();
                if (listeners!=null)
                {
                    for (EventListener l : listeners)
                    {
                        if (l.getClass().getName().equals(className))
                            return;
                    }
                }

                ((WebDescriptor)descriptor).addClassName(className);

                Class<? extends EventListener> listenerClass = (Class<? extends EventListener>)context.loadClass(className);
                listener = newListenerInstance(context,listenerClass);
                if (!(listener instanceof EventListener))
                {
                    LOG.warn("Not an EventListener: " + listener);
                    return;
                }
                context.addEventListener(listener);
                context.getMetaData().setOrigin(className+".listener", descriptor);

            }
        }
        catch (Exception e)
        {
            LOG.warn("Could not instantiate listener " + className, e);
            return;
        }
    }

    /**
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitDistributable(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        // the element has no content, so its simple presence
        // indicates that the webapp is distributable...
        //Servlet Spec 3.0 p.74  distributable only if all fragments are distributable
        ((WebDescriptor)descriptor).setDistributable(true);
    }
    
    
    /**
     * Servlet spec 3.1. When present in web.xml, this means that http methods that are
     * not covered by security constraints should have access denied.
     * 
     * See section 13.8.4, pg 145
     * @param context
     * @param descriptor
     * @param node
     */
    public void visitDenyUncoveredHttpMethods(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
    {
        ((ConstraintAware)context.getSecurityHandler()).setDenyUncoveredHttpMethods(true);
    }

    /**
     * @param context
     * @param clazz
     * @return the new event listener
     * @throws ServletException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public EventListener newListenerInstance(WebAppContext context,Class<? extends EventListener> clazz) throws Exception
    {
        ListenerHolder h = context.getServletHandler().newListenerHolder(Source.DESCRIPTOR);
        EventListener l = context.getServletContext().createInstance(clazz);
        h.setListener(l);
        context.getServletHandler().addListener(h);
        return l;

    }

    /**
     * @param p
     * @return the normalized pattern
     */
    public String normalizePattern(String p)
    {
        if (p != null && p.length() > 0 && !p.startsWith("/") && !p.startsWith("*")) return "/" + p;
        return p;
    }


}
