103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.webapp;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.URI;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.URL;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ArrayList;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Collection;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.EventListener;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashMap;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashSet;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Iterator;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Locale;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set;
3403928aee4356845252ac6b662d5c72c29903813eJake Slack
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.Servlet;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContextEvent;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContextListener;
3803928aee4356845252ac6b662d5c72c29903813eJake Slack
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.Loader;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
4103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
4203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.Resource;
4303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.xml.XmlParser;
4403928aee4356845252ac6b662d5c72c29903813eJake Slack
4503928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
4603928aee4356845252ac6b662d5c72c29903813eJake Slack/** TagLibConfiguration.
4703928aee4356845252ac6b662d5c72c29903813eJake Slack *
4803928aee4356845252ac6b662d5c72c29903813eJake Slack * The class searches for TLD descriptors found in web.xml, in WEB-INF/*.tld files of the web app
4903928aee4356845252ac6b662d5c72c29903813eJake Slack * or *.tld files within jars found in WEB-INF/lib of the webapp.   Any listeners defined in these
5003928aee4356845252ac6b662d5c72c29903813eJake Slack * tld's are added to the context.
5103928aee4356845252ac6b662d5c72c29903813eJake Slack *
5203928aee4356845252ac6b662d5c72c29903813eJake Slack * <bile>This is total rubbish special case for JSPs! If there was a general use-case for web app
5303928aee4356845252ac6b662d5c72c29903813eJake Slack * frameworks to register listeners directly, then a generic mechanism could have been added to the servlet
5403928aee4356845252ac6b662d5c72c29903813eJake Slack * spec.  Instead some special purpose JSP support is required that breaks all sorts of encapsulation rules as
5503928aee4356845252ac6b662d5c72c29903813eJake Slack * the servlet container must go searching for and then parsing the descriptors for one particular framework.
5603928aee4356845252ac6b662d5c72c29903813eJake Slack * It only appears to be used by JSF, which is being developed by the same developer who implemented this
5703928aee4356845252ac6b662d5c72c29903813eJake Slack * feature in the first place!
5803928aee4356845252ac6b662d5c72c29903813eJake Slack * </bile>
5903928aee4356845252ac6b662d5c72c29903813eJake Slack *
6003928aee4356845252ac6b662d5c72c29903813eJake Slack *
6103928aee4356845252ac6b662d5c72c29903813eJake Slack * Note- this has been superceded by the new TldScanner in jasper which uses ServletContainerInitializer to
6203928aee4356845252ac6b662d5c72c29903813eJake Slack * find all the listeners in tag libs and register them.
6303928aee4356845252ac6b662d5c72c29903813eJake Slack */
6403928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class TagLibConfiguration extends AbstractConfiguration
6503928aee4356845252ac6b662d5c72c29903813eJake Slack{
6603928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(TagLibConfiguration.class);
6703928aee4356845252ac6b662d5c72c29903813eJake Slack
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final String TLD_RESOURCES = "org.eclipse.jetty.tlds";
6903928aee4356845252ac6b662d5c72c29903813eJake Slack
7003928aee4356845252ac6b662d5c72c29903813eJake Slack
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
7203928aee4356845252ac6b662d5c72c29903813eJake Slack     * TagLibListener
7303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
7403928aee4356845252ac6b662d5c72c29903813eJake Slack     * A listener that does the job of finding .tld files that contain
7503928aee4356845252ac6b662d5c72c29903813eJake Slack     * (other) listeners that need to be called by the servlet container.
7603928aee4356845252ac6b662d5c72c29903813eJake Slack     *
7703928aee4356845252ac6b662d5c72c29903813eJake Slack     * This implementation is necessitated by the fact that it is only
7803928aee4356845252ac6b662d5c72c29903813eJake Slack     * after all the Configuration classes have run that we will
7903928aee4356845252ac6b662d5c72c29903813eJake Slack     * parse web.xml/fragments etc and thus find tlds mentioned therein.
8003928aee4356845252ac6b662d5c72c29903813eJake Slack     *
8103928aee4356845252ac6b662d5c72c29903813eJake Slack     * Note: TagLibConfiguration is not used in jetty-8 as jasper (JSP engine)
8203928aee4356845252ac6b662d5c72c29903813eJake Slack     * uses the new TldScanner class - a ServletContainerInitializer from
8303928aee4356845252ac6b662d5c72c29903813eJake Slack     * Servlet Spec 3 - to find all listeners in taglibs and register them
8403928aee4356845252ac6b662d5c72c29903813eJake Slack     * with the servlet container.
8503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
8603928aee4356845252ac6b662d5c72c29903813eJake Slack    public  class TagLibListener implements ServletContextListener {
8703928aee4356845252ac6b662d5c72c29903813eJake Slack        private List<EventListener> _tldListeners;
8803928aee4356845252ac6b662d5c72c29903813eJake Slack        private WebAppContext _context;
8903928aee4356845252ac6b662d5c72c29903813eJake Slack
9003928aee4356845252ac6b662d5c72c29903813eJake Slack        public TagLibListener (WebAppContext context) {
9103928aee4356845252ac6b662d5c72c29903813eJake Slack            _context = context;
9203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
9303928aee4356845252ac6b662d5c72c29903813eJake Slack
9403928aee4356845252ac6b662d5c72c29903813eJake Slack        public void contextDestroyed(ServletContextEvent sce)
9503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
9603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_tldListeners == null)
9703928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
9803928aee4356845252ac6b662d5c72c29903813eJake Slack
9903928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=_tldListeners.size()-1; i>=0; i--) {
10003928aee4356845252ac6b662d5c72c29903813eJake Slack                EventListener l = _tldListeners.get(i);
10103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (l instanceof ServletContextListener) {
10203928aee4356845252ac6b662d5c72c29903813eJake Slack                    ((ServletContextListener)l).contextDestroyed(sce);
10303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
10403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
10503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
10603928aee4356845252ac6b662d5c72c29903813eJake Slack
10703928aee4356845252ac6b662d5c72c29903813eJake Slack        public void contextInitialized(ServletContextEvent sce)
10803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
10903928aee4356845252ac6b662d5c72c29903813eJake Slack            try
11003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
11103928aee4356845252ac6b662d5c72c29903813eJake Slack                //For jasper 2.1:
11203928aee4356845252ac6b662d5c72c29903813eJake Slack                //Get the system classpath tlds and tell jasper about them, if jasper is on the classpath
11303928aee4356845252ac6b662d5c72c29903813eJake Slack                try
11403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
11503928aee4356845252ac6b662d5c72c29903813eJake Slack
11603928aee4356845252ac6b662d5c72c29903813eJake Slack                    ClassLoader loader = _context.getClassLoader();
11703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (loader == null || loader.getParent() == null)
11803928aee4356845252ac6b662d5c72c29903813eJake Slack                        loader = getClass().getClassLoader();
11903928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
12003928aee4356845252ac6b662d5c72c29903813eJake Slack                        loader = loader.getParent();
12103928aee4356845252ac6b662d5c72c29903813eJake Slack                    Class<?> clazz = loader.loadClass("org.apache.jasper.compiler.TldLocationsCache");
12203928aee4356845252ac6b662d5c72c29903813eJake Slack                    assert clazz!=null;
12303928aee4356845252ac6b662d5c72c29903813eJake Slack                    Collection<Resource> tld_resources = (Collection<Resource>)_context.getAttribute(TLD_RESOURCES);
12403928aee4356845252ac6b662d5c72c29903813eJake Slack
12503928aee4356845252ac6b662d5c72c29903813eJake Slack                    Map<URI, List<String>> tldMap = new HashMap<URI, List<String>>();
12603928aee4356845252ac6b662d5c72c29903813eJake Slack
12703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (tld_resources != null)
12803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
12903928aee4356845252ac6b662d5c72c29903813eJake Slack                        //get the jar file names of the files
13003928aee4356845252ac6b662d5c72c29903813eJake Slack                        for (Resource r:tld_resources)
13103928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
13203928aee4356845252ac6b662d5c72c29903813eJake Slack                            Resource jarResource = extractJarResource(r);
13303928aee4356845252ac6b662d5c72c29903813eJake Slack                            //jasper is happy with an empty list of tlds
13403928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (!tldMap.containsKey(jarResource.getURI()))
13503928aee4356845252ac6b662d5c72c29903813eJake Slack                                tldMap.put(jarResource.getURI(), null);
13603928aee4356845252ac6b662d5c72c29903813eJake Slack
13703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
13803928aee4356845252ac6b662d5c72c29903813eJake Slack                        //set the magic context attribute that tells jasper about the system tlds
13903928aee4356845252ac6b662d5c72c29903813eJake Slack                        sce.getServletContext().setAttribute("com.sun.appserv.tld.map", tldMap);
14003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
14103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
14203928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (ClassNotFoundException e)
14303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
14403928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
14503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
14603928aee4356845252ac6b662d5c72c29903813eJake Slack
14703928aee4356845252ac6b662d5c72c29903813eJake Slack                //find the tld files and parse them to get out their
14803928aee4356845252ac6b662d5c72c29903813eJake Slack                //listeners
14903928aee4356845252ac6b662d5c72c29903813eJake Slack                Set<Resource> tlds = findTldResources();
15003928aee4356845252ac6b662d5c72c29903813eJake Slack                List<TldDescriptor> descriptors = parseTlds(tlds);
15103928aee4356845252ac6b662d5c72c29903813eJake Slack                processTlds(descriptors);
15203928aee4356845252ac6b662d5c72c29903813eJake Slack
15303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_tldListeners == null)
15403928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
15503928aee4356845252ac6b662d5c72c29903813eJake Slack
15603928aee4356845252ac6b662d5c72c29903813eJake Slack                //call the listeners that are ServletContextListeners, put the
15703928aee4356845252ac6b662d5c72c29903813eJake Slack                //rest into the context's list of listeners to call at the appropriate
15803928aee4356845252ac6b662d5c72c29903813eJake Slack                //moment
15903928aee4356845252ac6b662d5c72c29903813eJake Slack                for (EventListener l:_tldListeners) {
16003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (l instanceof ServletContextListener) {
16103928aee4356845252ac6b662d5c72c29903813eJake Slack                        ((ServletContextListener)l).contextInitialized(sce);
16203928aee4356845252ac6b662d5c72c29903813eJake Slack                    } else {
16303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _context.addEventListener(l);
16403928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
16503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
16603928aee4356845252ac6b662d5c72c29903813eJake Slack
16703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
16803928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (Exception e) {
16903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn(e);
17003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
17103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
17203928aee4356845252ac6b662d5c72c29903813eJake Slack
17303928aee4356845252ac6b662d5c72c29903813eJake Slack
17403928aee4356845252ac6b662d5c72c29903813eJake Slack
17503928aee4356845252ac6b662d5c72c29903813eJake Slack
17603928aee4356845252ac6b662d5c72c29903813eJake Slack        private Resource extractJarResource (Resource r)
17703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
17803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (r == null)
17903928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
18003928aee4356845252ac6b662d5c72c29903813eJake Slack
18103928aee4356845252ac6b662d5c72c29903813eJake Slack            try
18203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
18303928aee4356845252ac6b662d5c72c29903813eJake Slack                String url = r.getURI().toURL().toString();
18403928aee4356845252ac6b662d5c72c29903813eJake Slack                int idx = url.lastIndexOf("!/");
18503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (idx >= 0)
18603928aee4356845252ac6b662d5c72c29903813eJake Slack                    url = url.substring(0, idx);
18703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (url.startsWith("jar:"))
18803928aee4356845252ac6b662d5c72c29903813eJake Slack                    url = url.substring(4);
18903928aee4356845252ac6b662d5c72c29903813eJake Slack                return Resource.newResource(url);
19003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
19103928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IOException e)
19203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
19303928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn(e);
19403928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
19503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
19603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
19703928aee4356845252ac6b662d5c72c29903813eJake Slack
19803928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
19903928aee4356845252ac6b662d5c72c29903813eJake Slack         * Find all the locations that can harbour tld files that may contain
20003928aee4356845252ac6b662d5c72c29903813eJake Slack         * a listener which the web container is supposed to instantiate and
20103928aee4356845252ac6b662d5c72c29903813eJake Slack         * call.
20203928aee4356845252ac6b662d5c72c29903813eJake Slack         *
20303928aee4356845252ac6b662d5c72c29903813eJake Slack         * @return
20403928aee4356845252ac6b662d5c72c29903813eJake Slack         * @throws IOException
20503928aee4356845252ac6b662d5c72c29903813eJake Slack         */
20603928aee4356845252ac6b662d5c72c29903813eJake Slack        private Set<Resource> findTldResources () throws IOException {
20703928aee4356845252ac6b662d5c72c29903813eJake Slack
20803928aee4356845252ac6b662d5c72c29903813eJake Slack            Set<Resource> tlds = new HashSet<Resource>();
20903928aee4356845252ac6b662d5c72c29903813eJake Slack
21003928aee4356845252ac6b662d5c72c29903813eJake Slack            // Find tld's from web.xml
21103928aee4356845252ac6b662d5c72c29903813eJake Slack            // When web.xml was processed, it should have created aliases for all TLDs.  So search resources aliases
21203928aee4356845252ac6b662d5c72c29903813eJake Slack            // for aliases ending in tld
21303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_context.getResourceAliases()!=null &&
21403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _context.getBaseResource()!=null &&
21503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _context.getBaseResource().exists())
21603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
21703928aee4356845252ac6b662d5c72c29903813eJake Slack                Iterator<String> iter=_context.getResourceAliases().values().iterator();
21803928aee4356845252ac6b662d5c72c29903813eJake Slack                while(iter.hasNext())
21903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
22003928aee4356845252ac6b662d5c72c29903813eJake Slack                    String location = iter.next();
22103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (location!=null && location.toLowerCase(Locale.ENGLISH).endsWith(".tld"))
22203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
22303928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (!location.startsWith("/"))
22403928aee4356845252ac6b662d5c72c29903813eJake Slack                            location="/WEB-INF/"+location;
22503928aee4356845252ac6b662d5c72c29903813eJake Slack                        Resource l=_context.getBaseResource().addPath(location);
22603928aee4356845252ac6b662d5c72c29903813eJake Slack                        tlds.add(l);
22703928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
22803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
22903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
23003928aee4356845252ac6b662d5c72c29903813eJake Slack
23103928aee4356845252ac6b662d5c72c29903813eJake Slack            // Look for any tlds in WEB-INF directly.
23203928aee4356845252ac6b662d5c72c29903813eJake Slack            Resource web_inf = _context.getWebInf();
23303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (web_inf!=null)
23403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
23503928aee4356845252ac6b662d5c72c29903813eJake Slack                String[] contents = web_inf.list();
23603928aee4356845252ac6b662d5c72c29903813eJake Slack                for (int i=0;contents!=null && i<contents.length;i++)
23703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
23803928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (contents[i]!=null && contents[i].toLowerCase(Locale.ENGLISH).endsWith(".tld"))
23903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
24003928aee4356845252ac6b662d5c72c29903813eJake Slack                        Resource l=web_inf.addPath(contents[i]);
24103928aee4356845252ac6b662d5c72c29903813eJake Slack                        tlds.add(l);
24203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
24303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
24403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
24503928aee4356845252ac6b662d5c72c29903813eJake Slack
24603928aee4356845252ac6b662d5c72c29903813eJake Slack            //Look for tlds in common location of WEB-INF/tlds
24703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (web_inf != null) {
24803928aee4356845252ac6b662d5c72c29903813eJake Slack                Resource web_inf_tlds = _context.getWebInf().addPath("/tlds/");
24903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (web_inf_tlds.exists() && web_inf_tlds.isDirectory()) {
25003928aee4356845252ac6b662d5c72c29903813eJake Slack                    String[] contents = web_inf_tlds.list();
25103928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i=0;contents!=null && i<contents.length;i++)
25203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
25303928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (contents[i]!=null && contents[i].toLowerCase(Locale.ENGLISH).endsWith(".tld"))
25403928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
25503928aee4356845252ac6b662d5c72c29903813eJake Slack                            Resource l=web_inf_tlds.addPath(contents[i]);
25603928aee4356845252ac6b662d5c72c29903813eJake Slack                            tlds.add(l);
25703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
25803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
25903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
26003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
26103928aee4356845252ac6b662d5c72c29903813eJake Slack
26203928aee4356845252ac6b662d5c72c29903813eJake Slack            // Add in tlds found in META-INF of jars. The jars that will be scanned are controlled by
26303928aee4356845252ac6b662d5c72c29903813eJake Slack            // the patterns defined in the context attributes: org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern,
26403928aee4356845252ac6b662d5c72c29903813eJake Slack            // and org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern
26503928aee4356845252ac6b662d5c72c29903813eJake Slack            @SuppressWarnings("unchecked")
26603928aee4356845252ac6b662d5c72c29903813eJake Slack            Collection<Resource> tld_resources=(Collection<Resource>)_context.getAttribute(TLD_RESOURCES);
26703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (tld_resources!=null)
26803928aee4356845252ac6b662d5c72c29903813eJake Slack                tlds.addAll(tld_resources);
26903928aee4356845252ac6b662d5c72c29903813eJake Slack
27003928aee4356845252ac6b662d5c72c29903813eJake Slack            return tlds;
27103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
27203928aee4356845252ac6b662d5c72c29903813eJake Slack
27303928aee4356845252ac6b662d5c72c29903813eJake Slack
27403928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
27503928aee4356845252ac6b662d5c72c29903813eJake Slack         * Parse xml into in-memory tree
27603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param tlds
27703928aee4356845252ac6b662d5c72c29903813eJake Slack         * @return
27803928aee4356845252ac6b662d5c72c29903813eJake Slack         */
27903928aee4356845252ac6b662d5c72c29903813eJake Slack        private List<TldDescriptor> parseTlds (Set<Resource> tlds) {
28003928aee4356845252ac6b662d5c72c29903813eJake Slack            List<TldDescriptor> descriptors = new ArrayList<TldDescriptor>();
28103928aee4356845252ac6b662d5c72c29903813eJake Slack
28203928aee4356845252ac6b662d5c72c29903813eJake Slack            Resource tld = null;
28303928aee4356845252ac6b662d5c72c29903813eJake Slack            Iterator<Resource> iter = tlds.iterator();
28403928aee4356845252ac6b662d5c72c29903813eJake Slack            while (iter.hasNext())
28503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
28603928aee4356845252ac6b662d5c72c29903813eJake Slack                try
28703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
28803928aee4356845252ac6b662d5c72c29903813eJake Slack                    tld = iter.next();
28903928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (LOG.isDebugEnabled()) LOG.debug("TLD="+tld);
29003928aee4356845252ac6b662d5c72c29903813eJake Slack
29103928aee4356845252ac6b662d5c72c29903813eJake Slack                    TldDescriptor d = new TldDescriptor(tld);
29203928aee4356845252ac6b662d5c72c29903813eJake Slack                    d.parse();
29303928aee4356845252ac6b662d5c72c29903813eJake Slack                    descriptors.add(d);
29403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
29503928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(Exception e)
29603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
29703928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn("Unable to parse TLD: " + tld,e);
29803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
29903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
30003928aee4356845252ac6b662d5c72c29903813eJake Slack            return descriptors;
30103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
30203928aee4356845252ac6b662d5c72c29903813eJake Slack
30303928aee4356845252ac6b662d5c72c29903813eJake Slack
30403928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
30503928aee4356845252ac6b662d5c72c29903813eJake Slack         * Create listeners from the parsed tld trees
30603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param descriptors
30703928aee4356845252ac6b662d5c72c29903813eJake Slack         * @throws Exception
30803928aee4356845252ac6b662d5c72c29903813eJake Slack         */
30903928aee4356845252ac6b662d5c72c29903813eJake Slack        private void processTlds (List<TldDescriptor> descriptors) throws Exception {
31003928aee4356845252ac6b662d5c72c29903813eJake Slack
31103928aee4356845252ac6b662d5c72c29903813eJake Slack            TldProcessor processor = new TldProcessor();
31203928aee4356845252ac6b662d5c72c29903813eJake Slack            for (TldDescriptor d:descriptors)
31303928aee4356845252ac6b662d5c72c29903813eJake Slack                processor.process(_context, d);
31403928aee4356845252ac6b662d5c72c29903813eJake Slack
31503928aee4356845252ac6b662d5c72c29903813eJake Slack            _tldListeners = new ArrayList<EventListener>(processor.getListeners());
31603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
31703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
31803928aee4356845252ac6b662d5c72c29903813eJake Slack
31903928aee4356845252ac6b662d5c72c29903813eJake Slack
32003928aee4356845252ac6b662d5c72c29903813eJake Slack
32103928aee4356845252ac6b662d5c72c29903813eJake Slack
32203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
32303928aee4356845252ac6b662d5c72c29903813eJake Slack     * TldDescriptor
32403928aee4356845252ac6b662d5c72c29903813eJake Slack     *
32503928aee4356845252ac6b662d5c72c29903813eJake Slack     *
32603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
32703928aee4356845252ac6b662d5c72c29903813eJake Slack    public static class TldDescriptor extends Descriptor
32803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
32903928aee4356845252ac6b662d5c72c29903813eJake Slack        protected static XmlParser __parserSingleton;
33003928aee4356845252ac6b662d5c72c29903813eJake Slack
33103928aee4356845252ac6b662d5c72c29903813eJake Slack        public TldDescriptor(Resource xml)
33203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
33303928aee4356845252ac6b662d5c72c29903813eJake Slack            super(xml);
33403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
33503928aee4356845252ac6b662d5c72c29903813eJake Slack
33603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
33703928aee4356845252ac6b662d5c72c29903813eJake Slack        public void ensureParser() throws ClassNotFoundException
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
33903928aee4356845252ac6b662d5c72c29903813eJake Slack           if (__parserSingleton == null)
34003928aee4356845252ac6b662d5c72c29903813eJake Slack               __parserSingleton = newParser();
34103928aee4356845252ac6b662d5c72c29903813eJake Slack            _parser = __parserSingleton;
34203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
34303928aee4356845252ac6b662d5c72c29903813eJake Slack
34403928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
34503928aee4356845252ac6b662d5c72c29903813eJake Slack        public XmlParser newParser() throws ClassNotFoundException
34603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34703928aee4356845252ac6b662d5c72c29903813eJake Slack            // Create a TLD parser
34803928aee4356845252ac6b662d5c72c29903813eJake Slack            XmlParser parser = new XmlParser(false);
34903928aee4356845252ac6b662d5c72c29903813eJake Slack
35003928aee4356845252ac6b662d5c72c29903813eJake Slack            URL taglib11=null;
35103928aee4356845252ac6b662d5c72c29903813eJake Slack            URL taglib12=null;
35203928aee4356845252ac6b662d5c72c29903813eJake Slack            URL taglib20=null;
35303928aee4356845252ac6b662d5c72c29903813eJake Slack            URL taglib21=null;
35403928aee4356845252ac6b662d5c72c29903813eJake Slack
35503928aee4356845252ac6b662d5c72c29903813eJake Slack            try
35603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
35703928aee4356845252ac6b662d5c72c29903813eJake Slack                Class<?> jsp_page = Loader.loadClass(WebXmlConfiguration.class,"javax.servlet.jsp.JspPage");
35803928aee4356845252ac6b662d5c72c29903813eJake Slack                taglib11=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd");
35903928aee4356845252ac6b662d5c72c29903813eJake Slack                taglib12=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd");
36003928aee4356845252ac6b662d5c72c29903813eJake Slack                taglib20=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd");
36103928aee4356845252ac6b662d5c72c29903813eJake Slack                taglib21=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsd");
36203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
36303928aee4356845252ac6b662d5c72c29903813eJake Slack            catch(Exception e)
36403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
36503928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
36603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
36703928aee4356845252ac6b662d5c72c29903813eJake Slack            finally
36803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
36903928aee4356845252ac6b662d5c72c29903813eJake Slack                if(taglib11==null)
37003928aee4356845252ac6b662d5c72c29903813eJake Slack                    taglib11=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd",true);
37103928aee4356845252ac6b662d5c72c29903813eJake Slack                if(taglib12==null)
37203928aee4356845252ac6b662d5c72c29903813eJake Slack                    taglib12=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd",true);
37303928aee4356845252ac6b662d5c72c29903813eJake Slack                if(taglib20==null)
37403928aee4356845252ac6b662d5c72c29903813eJake Slack                    taglib20=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd",true);
37503928aee4356845252ac6b662d5c72c29903813eJake Slack                if(taglib21==null)
37603928aee4356845252ac6b662d5c72c29903813eJake Slack                    taglib21=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsd",true);
37703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
37803928aee4356845252ac6b662d5c72c29903813eJake Slack
37903928aee4356845252ac6b662d5c72c29903813eJake Slack
38003928aee4356845252ac6b662d5c72c29903813eJake Slack            if(taglib11!=null)
38103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
38203928aee4356845252ac6b662d5c72c29903813eJake Slack                redirect(parser, "web-jsptaglib_1_1.dtd",taglib11);
38303928aee4356845252ac6b662d5c72c29903813eJake Slack                redirect(parser, "web-jsptaglibrary_1_1.dtd",taglib11);
38403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
38503928aee4356845252ac6b662d5c72c29903813eJake Slack            if(taglib12!=null)
38603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
38703928aee4356845252ac6b662d5c72c29903813eJake Slack                redirect(parser, "web-jsptaglib_1_2.dtd",taglib12);
38803928aee4356845252ac6b662d5c72c29903813eJake Slack                redirect(parser, "web-jsptaglibrary_1_2.dtd",taglib12);
38903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
39003928aee4356845252ac6b662d5c72c29903813eJake Slack            if(taglib20!=null)
39103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
39203928aee4356845252ac6b662d5c72c29903813eJake Slack                redirect(parser, "web-jsptaglib_2_0.xsd",taglib20);
39303928aee4356845252ac6b662d5c72c29903813eJake Slack                redirect(parser, "web-jsptaglibrary_2_0.xsd",taglib20);
39403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
39503928aee4356845252ac6b662d5c72c29903813eJake Slack            if(taglib21!=null)
39603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
39703928aee4356845252ac6b662d5c72c29903813eJake Slack                redirect(parser, "web-jsptaglib_2_1.xsd",taglib21);
39803928aee4356845252ac6b662d5c72c29903813eJake Slack                redirect(parser, "web-jsptaglibrary_2_1.xsd",taglib21);
39903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
40003928aee4356845252ac6b662d5c72c29903813eJake Slack
40103928aee4356845252ac6b662d5c72c29903813eJake Slack            parser.setXpath("/taglib/listener/listener-class");
40203928aee4356845252ac6b662d5c72c29903813eJake Slack            return parser;
40303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
40403928aee4356845252ac6b662d5c72c29903813eJake Slack
40503928aee4356845252ac6b662d5c72c29903813eJake Slack        public void parse ()
40603928aee4356845252ac6b662d5c72c29903813eJake Slack        throws Exception
40703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
40803928aee4356845252ac6b662d5c72c29903813eJake Slack            ensureParser();
40903928aee4356845252ac6b662d5c72c29903813eJake Slack            try
41003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
41103928aee4356845252ac6b662d5c72c29903813eJake Slack                //xerces on apple appears to sometimes close the zip file instead
41203928aee4356845252ac6b662d5c72c29903813eJake Slack                //of the inputstream, so try opening the input stream, but if
41303928aee4356845252ac6b662d5c72c29903813eJake Slack                //that doesn't work, fallback to opening a new url
41403928aee4356845252ac6b662d5c72c29903813eJake Slack                _root = _parser.parse(_xml.getInputStream());
41503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
41603928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (Exception e)
41703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
41803928aee4356845252ac6b662d5c72c29903813eJake Slack                _root = _parser.parse(_xml.getURL().toString());
41903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
42003928aee4356845252ac6b662d5c72c29903813eJake Slack
42103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_root==null)
42203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
42303928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("No TLD root in {}",_xml);
42403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
42503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
42603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
42703928aee4356845252ac6b662d5c72c29903813eJake Slack
42803928aee4356845252ac6b662d5c72c29903813eJake Slack
42903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
43003928aee4356845252ac6b662d5c72c29903813eJake Slack     * TldProcessor
43103928aee4356845252ac6b662d5c72c29903813eJake Slack     *
43203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Process TldDescriptors representing tag libs to find listeners.
43303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
43403928aee4356845252ac6b662d5c72c29903813eJake Slack    public class TldProcessor extends IterativeDescriptorProcessor
43503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
43603928aee4356845252ac6b662d5c72c29903813eJake Slack        public static final String TAGLIB_PROCESSOR = "org.eclipse.jetty.tagLibProcessor";
43703928aee4356845252ac6b662d5c72c29903813eJake Slack        XmlParser _parser;
43803928aee4356845252ac6b662d5c72c29903813eJake Slack        List<XmlParser.Node> _roots = new ArrayList<XmlParser.Node>();
43903928aee4356845252ac6b662d5c72c29903813eJake Slack        List<EventListener> _listeners;
44003928aee4356845252ac6b662d5c72c29903813eJake Slack
44103928aee4356845252ac6b662d5c72c29903813eJake Slack
44203928aee4356845252ac6b662d5c72c29903813eJake Slack        public TldProcessor ()
44303928aee4356845252ac6b662d5c72c29903813eJake Slack        throws Exception
44403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
44503928aee4356845252ac6b662d5c72c29903813eJake Slack            _listeners = new ArrayList<EventListener>();
44603928aee4356845252ac6b662d5c72c29903813eJake Slack            registerVisitor("listener", this.getClass().getDeclaredMethod("visitListener", __signature));
44703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
44803928aee4356845252ac6b662d5c72c29903813eJake Slack
44903928aee4356845252ac6b662d5c72c29903813eJake Slack
45003928aee4356845252ac6b662d5c72c29903813eJake Slack        public void visitListener (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
45103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
45203928aee4356845252ac6b662d5c72c29903813eJake Slack            String className=node.getString("listener-class",false,true);
45303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
45403928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("listener="+className);
45503928aee4356845252ac6b662d5c72c29903813eJake Slack
45603928aee4356845252ac6b662d5c72c29903813eJake Slack            try
45703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
45803928aee4356845252ac6b662d5c72c29903813eJake Slack                Class<?> listenerClass = context.loadClass(className);
45903928aee4356845252ac6b662d5c72c29903813eJake Slack                EventListener l = (EventListener)listenerClass.newInstance();
46003928aee4356845252ac6b662d5c72c29903813eJake Slack                _listeners.add(l);
46103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
46203928aee4356845252ac6b662d5c72c29903813eJake Slack            catch(Exception e)
46303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46403928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("Could not instantiate listener "+className+": "+e);
46503928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug(e);
46603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
46703928aee4356845252ac6b662d5c72c29903813eJake Slack            catch(Error e)
46803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("Could not instantiate listener "+className+": "+e);
47003928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug(e);
47103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
47203928aee4356845252ac6b662d5c72c29903813eJake Slack
47303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
47403928aee4356845252ac6b662d5c72c29903813eJake Slack
47503928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
47603928aee4356845252ac6b662d5c72c29903813eJake Slack        public void end(WebAppContext context, Descriptor descriptor)
47703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
47803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
47903928aee4356845252ac6b662d5c72c29903813eJake Slack
48003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
48103928aee4356845252ac6b662d5c72c29903813eJake Slack        public void start(WebAppContext context, Descriptor descriptor)
48203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
48303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
48403928aee4356845252ac6b662d5c72c29903813eJake Slack
48503928aee4356845252ac6b662d5c72c29903813eJake Slack        public List<EventListener> getListeners() {
48603928aee4356845252ac6b662d5c72c29903813eJake Slack            return _listeners;
48703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
48803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
48903928aee4356845252ac6b662d5c72c29903813eJake Slack
49003928aee4356845252ac6b662d5c72c29903813eJake Slack
49103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
49203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void preConfigure(WebAppContext context) throws Exception
49303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
49403928aee4356845252ac6b662d5c72c29903813eJake Slack        try
49503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
49603928aee4356845252ac6b662d5c72c29903813eJake Slack            Class<?> jsp_page = Loader.loadClass(WebXmlConfiguration.class,"javax.servlet.jsp.JspPage");
49703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
49803928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Exception e)
49903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
50003928aee4356845252ac6b662d5c72c29903813eJake Slack            //no jsp available, don't parse TLDs
50103928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
50203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
50303928aee4356845252ac6b662d5c72c29903813eJake Slack
50403928aee4356845252ac6b662d5c72c29903813eJake Slack        TagLibListener tagLibListener = new TagLibListener(context);
50503928aee4356845252ac6b662d5c72c29903813eJake Slack        context.addEventListener(tagLibListener);
50603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
50703928aee4356845252ac6b662d5c72c29903813eJake Slack
50803928aee4356845252ac6b662d5c72c29903813eJake Slack
50903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
51003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void configure (WebAppContext context) throws Exception
51103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
51203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
51303928aee4356845252ac6b662d5c72c29903813eJake Slack
51403928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
51503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void postConfigure(WebAppContext context) throws Exception
51603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
51703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
51803928aee4356845252ac6b662d5c72c29903813eJake Slack
51903928aee4356845252ac6b662d5c72c29903813eJake Slack
52003928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
52103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
52203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
52303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
52403928aee4356845252ac6b662d5c72c29903813eJake Slack
52503928aee4356845252ac6b662d5c72c29903813eJake Slack
52603928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
52703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void deconfigure(WebAppContext context) throws Exception
52803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
52903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
53003928aee4356845252ac6b662d5c72c29903813eJake Slack}
531