Package org.apache.catalina.startup

Source Code of org.apache.catalina.startup.ContextConfig$ContextErrorHandler

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.catalina.startup;

import org.apache.catalina.*;
import org.apache.catalina.authenticator.*;
import org.apache.catalina.core.*;
import org.apache.catalina.deploy.FilterDef;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.catalina.session.StandardManager;
import org.apache.tomcat.util.digester.Digester;
import org.apache.tomcat.util.digester.RuleSet;
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.web.valve.GlassFishValve;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;

import javax.servlet.ServletContext;
import java.io.*;
import java.net.URL;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.*;
import java.util.logging.Logger;

/**
* Startup event listener for a <b>Context</b> that configures the properties
* of that Context, and the associated defined servlets.
*
* @author Craig R. McClanahan
* @author Jean-Francois Arcand
* @version $Revision: 1.14 $ $Date: 2007/02/20 20:16:56 $
*/

// START OF SJAS 8.0 BUG 5046959
// public final class ContextConfig
// NOTE: All the methods were originally private and changed to public.
public class ContextConfig
// END OF SJAS 8.0 BUG 5046959
    implements LifecycleListener {

    private static final Logger log = StandardServer.log;
    private static final ResourceBundle rb = log.getResourceBundle();

    @LogMessageInfo(
            message = "Lifecycle event data object {0} is not a Context",
            level = "WARNING"
    )
    public static final String EVENT_DATA_IS_NOT_CONTEXT_EXCEPTION = "AS-WEB-CORE-00408";

    @LogMessageInfo(
            message = "alt-dd file {0} not found",
            level = "WARNING"
    )
    public static final String ALT_DD_FILE_NOT_FOUND_EXCEPTION = "AS-WEB-CORE-00409";

    @LogMessageInfo(
            message = "Missing application web.xml, using defaults only {0}",
            level = "FINE"
    )
    public static final String MISSING_APP_WEB_XML_FINE = "AS-WEB-CORE-00410";

    @LogMessageInfo(
            message = "Parse error in application web.xml at line {0} and column {1}",
            level = "WARNING"
    )
    public static final String PARSE_ERROR_IN_APP_WEB_XML_EXCEPTION = "AS-WEB-CORE-00411";

    @LogMessageInfo(
            message = "Parse error in application web.xml",
            level = "WARNING"
    )
    public static final String PARSE_ERROR_IN_APP_WEB_XML = "AS-WEB-CORE-00412";

    @LogMessageInfo(
            message = "Error closing application web.xml",
            level = "SEVERE",
            cause = "Could not close this input stream and releases any system resources " +
                    "associated with the stream.",
            action = "Verify if any I/O errors occur"
    )
    public static final String ERROR_CLOSING_APP_WEB_XML_EXCEPTION = "AS-WEB-CORE-00413";

    @LogMessageInfo(
            message = "No Realm has been configured to authenticate against",
            level = "WARNING"
    )
    public static final String NO_REALM_BEEN_CONFIGURED_EXCEPTION = "AS-WEB-CORE-00414";

    @LogMessageInfo(
            message = "Cannot configure an authenticator for method {0}",
            level = "WARNING"
    )
    public static final String CANNOT_CONFIG_AUTHENTICATOR_EXCEPTION = "AS-WEB-CORE-00415";

    @LogMessageInfo(
            message = "Cannot instantiate an authenticator of class {0}",
            level = "WARNING"
    )
    public static final String CANNOT_INSTANTIATE_AUTHENTICATOR_EXCEPTION = "AS-WEB-CORE-00416";

    @LogMessageInfo(
            message = "Configured an authenticator for method {0}",
            level = "FINE"
    )
    public static final String CONFIGURED_AUTHENTICATOR_FINE = "AS-WEB-CORE-00417";

    @LogMessageInfo(
            message = "No default web.xml",
            level = "INFO"
    )
    public static final String NO_DEFAULT_WEB_XML_INFO = "AS-WEB-CORE-00418";

    @LogMessageInfo(
            message = "Missing default web.xml, using application web.xml only {0} {1}",
            level = "WARNING"
    )
    public static final String MISSING_DEFAULT_WEB_XML_EXCEPTION = "AS-WEB-CORE-00419";

    @LogMessageInfo(
            message = "Parse error in default web.xml at line {0} and column {1}",
            level = "SEVERE",
            cause = "Could not parse the content of the specified input source using this Digester",
            action = "Verify the input parameter, if any I/O errors occur"
    )
    public static final String PARSE_ERROR_IN_DEFAULT_WEB_XML_EXCEPTION = "AS-WEB-CORE-00420";

    @LogMessageInfo(
            message = "Parse error in default web.xml",
            level = "SEVERE",
            cause = "Could not parse the content of the specified input source using this Digester",
            action = "Verify the input parameter, if any I/O errors occur"
    )
    public static final String PARSE_ERROR_IN_DEFAULT_WEB_XML = "AS-WEB-CORE-00421";

    @LogMessageInfo(
            message = "Error closing default web.xml",
            level = "SEVERE",
            cause = "Could not close this input stream and releases any system resources " +
                    "associated with the stream.",
            action = "Verify if any I/O errors occur"
    )
    public static final String ERROR_CLOSING_DEFAULT_WEB_XML_EXCEPTION = "AS-WEB-CORE-00422";

    @LogMessageInfo(
            message = "ContextConfig: Initializing",
            level = "FINE"
    )
    public static final String CONTEXT_CONFIG_INIT_FINE = "AS-WEB-CORE-00423";

    @LogMessageInfo(
            message = "Exception fixing docBase",
            level = "SEVERE",
            cause = "Could not adjust docBase",
            action = "Verify if any I/O errors occur"
    )
    public static final String FIXING_DOC_BASE_EXCEPTION = "AS-WEB-CORE-00424";

    @LogMessageInfo(
            message = "ContextConfig: Processing START",
            level = "FINEST"
    )
    public static final String PROCESSING_START_FINEST = "AS-WEB-CORE-00425";

    @LogMessageInfo(
            message = "ContextConfig: Processing STOP",
            level = "FINEST"
    )
    public static final String PROCESSING_STOP_FINEST = "AS-WEB-CORE-00426";

    @LogMessageInfo(
            message = "Security role name {0} used in an <auth-constraint> " +
                      "without being defined in a <security-role> in context [{1}]",
            level = "INFO"
    )
    public static final String SECURITY_ROLE_NAME_USED_IN_AUTH_WITHOUT_DEFINITION = "AS-WEB-CORE-00427";

    @LogMessageInfo(
            message = "Security role name {0} used in a <run-as> " +
                      "without being defined in a <security-role> in context [{1}]",
            level = "INFO"
    )
    public static final String SECURITY_ROLE_NAME_USED_IN_RUNAS_WITHOUT_DEFINITION = "AS-WEB-CORE-00428";

    @LogMessageInfo(
            message = "Security role name {0} used in a <role-link> " +
                      "without being defined in a <security-role> in context [{1}]",
            level = "INFO"
    )
    public static final String SECURITY_ROLE_NAME_USED_IN_LINK_WITHOUT_DEFINITION = "AS-WEB-CORE-00429";

    @LogMessageInfo(
            message = "No web.xml, using defaults {0}",
            level = "INFO"
    )
    public static final String NO_WEB_XML_INFO = "AS-WEB-CORE-00430";
    // --------------------------------------------------- Instance Variables


    /*
     * Custom mappings of login methods to authenticators
     */
    //START SJSAS 6202703
    //private Map customAuthenticators;
    protected Map<String, Authenticator> customAuthenticators;
    //END SJSAS 6202703


    /**
     * The set of Authenticators that we know how to configure.  The key is
     * the name of the implemented authentication method, and the value is
     * the fully qualified Java class name of the corresponding Valve.
     */
    //START SJSAS 6202703
    //private static Properties authenticators = null;
   
    protected static final Properties authenticators = new Properties();
    //END SJSAS 6202703


    private ClassLoader classLoader;


    /**
     * The Context we are associated with.
     */
    protected Context context = null;


    /**
     * The debugging detail level for this component.
     */
    private int debug = 0;


    // START GlassFish 2439
    /**
     * The default web application's context file location.
     */
    protected String defaultContextXml = null;
    // END GlassFish 2439
   

    /**
     * The default web application's deployment descriptor location.
     */
    // BEGIN OF SJSAS 8.1 6172288 
    // private String defaultWebXml = null;
    protected String defaultWebXml = null;
   
   
    /**
     * Track any fatal errors during startup configuration processing.
     */
    // private boolean ok = false;
    protected boolean ok = false;
    // END OF SJSAS 8.1 6172288


    // START GlassFish 2439
    /**
     * Any parse error which occurred while parsing XML descriptors.
     */
    protected SAXParseException parseException = null;
    // END GlassFish 2439


    // START GlassFish 2439
    /**
     * The <code>Digester</code> we will use to process web application
     * context files.
     */
    protected static final Digester contextDigester =
        createContextDigester();
    // END GlassFish 2439


    /**
     * The <code>Digester</code> we will use to process web application
     * deployment descriptor files.
     */
    // BEGIN OF SJSAS 8.1 6172288 
    // private static Digester webDigester = null;
    protected static final Digester webDigester =
        createWebDigester();
    // END OF SJSAS 8.1 6172288 
   
   
    /**
     * The <code>Rule</code> used to parse the web.xml
     */
    // BEGIN OF SJSAS 8.1 6172288 
    // private static WebRuleSet webRuleSet = new WebRuleSet();
    protected static final WebRuleSet webRuleSet = new WebRuleSet();
    // END OF SJSAS 8.1 6172288 

    /**
     * Attribute value used to turn on/off XML validation
     */
    private static boolean xmlValidation = false;


    /**
     * Attribute value used to turn on/off XML namespace awarenes.
     */
    private static boolean xmlNamespaceAware = false;

       
    /**
     * Static initializer
     */
    static {
        authenticators.setProperty(
            "BASIC", BasicAuthenticator.class.getName());
        authenticators.setProperty(
            "CLIENT-CERT", SSLAuthenticator.class.getName());
        authenticators.setProperty(
            "FORM", FormAuthenticator.class.getName());
        authenticators.setProperty(
            "NONE", NonLoginAuthenticator.class.getName());
        authenticators.setProperty(
            "DIGEST", DigestAuthenticator.class.getName());
    }


    // ----------------------------------------------------------- Properties


    public void setClassLoader(ClassLoader cl) {
        this.classLoader = cl;
    }


    /**
     * Return the debugging detail level for this component.
     */
    public int getDebug() {

        return (this.debug);

    }


    /**
     * Set the debugging detail level for this component.
     *
     * @param debug The new debugging detail level
     */
    public void setDebug(int debug) {
        this.debug = debug;
    }
   
   
    // START GlassFish 2439
    /**
     * Return the location of the default deployment descriptor
     */
    public String getDefaultWebXml() {
        if( defaultWebXml == null ) defaultWebXml=Constants.DefaultWebXml;
        return (this.defaultWebXml);
    }


    /**
     * Set the location of the default deployment descriptor
     *
     * @param path Absolute/relative path to the default web.xml
     */
    public void setDefaultWebXml(String path) {
        this.defaultWebXml = path;
    }
    // END GlassFish 2439


    /**
     * Return the location of the default context file
     */
    public String getDefaultContextXml() {
        if( defaultContextXml == null ) {
            defaultContextXml=Constants.DEFAULT_CONTEXT_XML;
        }

        return (this.defaultContextXml);
    }


    /**
     * Set the location of the default context file
     *
     * @param path Absolute/relative path to the default context.xml
     */
    public void setDefaultContextXml(String path) {
        this.defaultContextXml = path;
    }


    /**
     * Sets custom mappings of login methods to authenticators.
     *
     * @param customAuthenticators Custom mappings of login methods to
     * authenticators
     */
    public void setCustomAuthenticators(Map<String, Authenticator> customAuthenticators) {
        this.customAuthenticators = customAuthenticators;
    }


    // --------------------------------------------------------- Public Methods


    /**
     * Process the START event for an associated Context.
     *
     * @param event The lifecycle event that has occurred
     */
    public void lifecycleEvent(LifecycleEvent event)
            throws LifecycleException {

        // Identify the context we are associated with
        try {
            context = (Context) event.getLifecycle();
        } catch (ClassCastException e) {
            String msg = MessageFormat.format(rb.getString(EVENT_DATA_IS_NOT_CONTEXT_EXCEPTION),
                                              event.getLifecycle());
            throw new LifecycleException(msg, e);
        }

        // Called from ContainerBase.addChild() -> StandardContext.start()
        // Process the event that has occurred
        if (event.getType().equals(Lifecycle.START_EVENT)) {
            start();
        } else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
            stop();
        // START GlassFish 2439
        } else if (event.getType().equals(Lifecycle.INIT_EVENT)) {
            init();
        // END GlassFish 2439
        }
    }


    // -------------------------------------------------------- Private Methods


    /**
     * Process the application configuration file, if it exists.
     */
    protected void applicationConfig() throws LifecycleException {

        String altDDName = null;

        // Open the application web.xml file, if it exists
        InputStream stream = null;
        ServletContext servletContext = context.getServletContext();
        if (servletContext != null) {
            altDDName = (String)servletContext.getAttribute(
                    Globals.ALT_DD_ATTR);
            if (altDDName != null) {
                try {
                    stream = new FileInputStream(altDDName);
                } catch (FileNotFoundException e) {
                    String msg = MessageFormat.format(rb.getString(ALT_DD_FILE_NOT_FOUND_EXCEPTION),
                                                      altDDName);
                    throw new LifecycleException(msg);
                }
            }
            else {
                stream = servletContext.getResourceAsStream
                    (Constants.ApplicationWebXml);
            }
        }
        if (stream == null) {
            /* PWC 6296257
            log.info(sm.getString("contextConfig.applicationMissing") + " " + context);
            //contextConfig.applicationMissing=PWC3013: Missing application web.xml, using defaults only
            */
            // START PWC 6296257
            if (log.isLoggable(Level.FINE)) {
                log.log(Level.FINE, MISSING_APP_WEB_XML_FINE, context);
            }
            // END PWC 6296257
            return;
        }
       
        long t1=System.currentTimeMillis();

        URL url=null;
        // Process the application web.xml file
        synchronized (webDigester) {
            try {
                if (altDDName != null) {
                    url = new File(altDDName).toURL();
                } else {
                    url = servletContext.getResource(
                                                Constants.ApplicationWebXml);
                }
                if( url!=null ) {
                    InputSource is = new InputSource(url.toExternalForm());
                    is.setByteStream(stream);
                    webDigester.clear();
                    webDigester.setDebug(getDebug());
                    if (context instanceof StandardContext) {
                        ((StandardContext) context).setReplaceWelcomeFiles(true);
                    }
                    webDigester.setUseContextClassLoader(false);
                    webDigester.push(context);
                    webDigester.parse(is);
                } else {
                    if (log.isLoggable(Level.INFO)) {
                        log.log(Level.INFO, NO_WEB_XML_INFO);
                    }
                }
            } catch (SAXParseException e) {
                String msg = MessageFormat.format(rb.getString(PARSE_ERROR_IN_APP_WEB_XML_EXCEPTION),
                                                  new Object[] {e.getLineNumber(), e.getColumnNumber()});
                throw new LifecycleException(msg, e);
            } catch (Exception e) {
                throw new LifecycleException(rb.getString(PARSE_ERROR_IN_APP_WEB_XML), e);
            } finally {
                try {
                    stream.close();
                } catch (IOException e) {
                    log.log(Level.SEVERE, ERROR_CLOSING_APP_WEB_XML_EXCEPTION,
                            e);
                }
                webDigester.push(null);
            }
        }
        webRuleSet.recycle();

        long t2=System.currentTimeMillis();
        if (context instanceof StandardContext) {
            ((StandardContext) context).setStartupTime(t2-t1);
        }
    }


    /**
     * Set up a manager.
     */
    protected synchronized void managerConfig() {
        if (context.getManager() == null) {
            context.setManager(new StandardManager());
        }
    }


    /**
     * Set up an Authenticator automatically if required, and one has not
     * already been configured.
     */
    protected synchronized void authenticatorConfig()
            throws LifecycleException {

        // Does this Context require an Authenticator?
        /* START IASRI 4856062
           // This constraints check is relocated to happen after
           // setRealmName(). This allows apps which have no constraints
           // and no authenticator to still have a realm name set in
           // their RealmAdapater. This is only relevant in the case where
           // the core ACLs are doing all access control AND the servlet
           // wishes to call isUserInRole AND the application does have
           // security-role-mapping elements in sun-web.xml. This is probably
           // not an interesting scenario. But might as well allow it to
           // work, maybe it is of some use.
        SecurityConstraint constraints[] = context.findConstraints();
        if ((constraints == null) || (constraints.length == 0))
            return;
        */
        LoginConfig loginConfig = context.getLoginConfig();
        if (loginConfig == null) {
            loginConfig = new LoginConfig("NONE", null, null, null);
            context.setLoginConfig(loginConfig);
        }

        // Has an authenticator been configured already?
        if (context instanceof Authenticator)
            return;
        if (context instanceof ContainerBase) {
            Pipeline pipeline = ((ContainerBase) context).getPipeline();
            if (pipeline != null) {
                GlassFishValve basic = pipeline.getBasic();
                if ((basic != null) && (basic instanceof Authenticator))
                    return;
                GlassFishValve valves[] = pipeline.getValves();
                for (int i = 0; i < valves.length; i++) {
                    if (valves[i] instanceof Authenticator)
                        return;
                }
            }
        } else {
            return;     // Cannot install a Valve even if it would be needed
        }

        // Has a Realm been configured for us to authenticate against?
        /* START IASRI 4856062
        if (context.getRealm() == null) {
        */
        // BEGIN IASRI 4856062
        Realm rlm = context.getRealm();
        if (rlm == null) {
        // END IASRI 4856062
            throw new LifecycleException(rb.getString(NO_REALM_BEEN_CONFIGURED_EXCEPTION));
        }

        // BEGIN IASRI 4856062
        // If a realm is available set its name in the Realm(Adapter)
        rlm.setRealmName(loginConfig.getRealmName(),
                         loginConfig.getAuthMethod());
        if (!context.hasConstraints()) {
            return;
        }
        // END IASRI 4856062

        /*
         * First check to see if there is a custom mapping for the login
         * method. If so, use it. Otherwise, check if there is a mapping in
         * org/apache/catalina/startup/Authenticators.properties.
         */
        GlassFishValve authenticator = null;
        if (customAuthenticators != null) {
            /* PWC 6392537
            authenticator = (Valve)
                customAuthenticators.get(loginConfig.getAuthMethod());
            */
            // START PWC 6392537
            String loginMethod = loginConfig.getAuthMethod();
            if (loginMethod != null
                    && customAuthenticators.containsKey(loginMethod)) {
                authenticator = getGlassFishValveAuthenticator(loginMethod);
                if (authenticator == null) {
                    String msg = MessageFormat.format(rb.getString(CANNOT_CONFIG_AUTHENTICATOR_EXCEPTION),
                                                      loginMethod);
                    throw new LifecycleException(msg);
                }
            }
            // END PWC 6392537
        }

        if (authenticator == null) {
            // Identify the class name of the Valve we should configure
            String authenticatorName = null;

            // BEGIN RIMOD 4808402
            // If login-config is given but auth-method is null, use NONE
            // so that NonLoginAuthenticator is picked
            String authMethod = loginConfig.getAuthMethod();
            if (authMethod == null) {
                authMethod = "NONE";
            }
            authenticatorName = authenticators.getProperty(authMethod);
            // END RIMOD 4808402
            /* RIMOD 4808402
            authenticatorName =
                    authenticators.getProperty(loginConfig.getAuthMethod());
            */

            if (authenticatorName == null) {
                String msg = MessageFormat.format(rb.getString(CANNOT_CONFIG_AUTHENTICATOR_EXCEPTION),
                                                  loginConfig.getAuthMethod());
                throw new LifecycleException(msg);
            }

            // Instantiate and install an Authenticator of the requested class
            try {
                Class authenticatorClass = Class.forName(authenticatorName);
                authenticator = (GlassFishValve) authenticatorClass.newInstance();
            } catch (Throwable t) {
                String msg = MessageFormat.format(rb.getString(CANNOT_INSTANTIATE_AUTHENTICATOR_EXCEPTION),
                                                  authenticatorName);
                throw new LifecycleException(msg, t);
            }
        }

        if (authenticator != null && context instanceof ContainerBase) {
            Pipeline pipeline = ((ContainerBase) context).getPipeline();
            if (pipeline != null) {
                ((ContainerBase) context).addValve(authenticator);
                if (log.isLoggable(Level.FINE)) {
                    log.log(Level.FINE, CONFIGURED_AUTHENTICATOR_FINE, loginConfig.getAuthMethod());
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private GlassFishValve getGlassFishValveAuthenticator(String loginMethod) {
        return (GlassFishValve) customAuthenticators.get(loginMethod);
    }

    /**
     * Create and return a Digester configured to process the
     * web application deployment descriptor (web.xml).
     */
    // BEGIN OF SJSAS 8.1 6172288 
    // private static Digester createWebDigester() {
    public static Digester createWebDigester() {
    // END OF SJSAS 8.1 6172288 
        return createWebXmlDigester(xmlNamespaceAware, xmlValidation);
    }


    /*
     * Create and return a Digester configured to process the
     * web application deployment descriptor (web.xml).
     */
    public static Digester createWebXmlDigester(boolean namespaceAware,
                                                boolean validation) {
        DigesterFactory df = org.glassfish.internal.api.Globals.get(
            DigesterFactory.class);
        Digester digester = df.newDigester(xmlValidation,
            xmlNamespaceAware, webRuleSet);
        digester.getParser();
        return digester;
    }


    // START GlassFish 2439
    /**
     * Create and return a Digester configured to process the
     * context configuration descriptor for an application.
     */
    protected static Digester createContextDigester() {
        Digester digester = new Digester();
        digester.setValidating(false);
        RuleSet contextRuleSet = new ContextRuleSet("", false);
        digester.addRuleSet(contextRuleSet);
        RuleSet namingRuleSet = new NamingRuleSet("Context/");
        digester.addRuleSet(namingRuleSet);
        digester.getParser();
        return digester;
    }
    // END GlassFish 2439


    protected String getBaseDir() {
        Container engineC=context.getParent().getParent();
        if( engineC instanceof StandardEngine ) {
            return ((StandardEngine)engineC).getBaseDir();
        }
        return System.getProperty("catalina.base");
    }

    /**
     * Process the default configuration file, if it exists.
     * The default config must be read with the container loader - so
     * container servlets can be loaded
     */
    protected void defaultConfig() throws LifecycleException {
        long t1 = System.currentTimeMillis();

        // Open the default web.xml file, if it exists
        if (defaultWebXml == null && context instanceof StandardContext) {
            defaultWebXml=((StandardContext)context).getDefaultWebXml();
        }
        // set the default if we don't have any overrides
        if (defaultWebXml == null) getDefaultWebXml();

        File file = new File(this.defaultWebXml);
        if (!file.isAbsolute()) {
            file = new File(getBaseDir(), this.defaultWebXml);
        }
       
        InputStream stream = null;
        InputSource source = null;

        try {
            if ( ! file.exists() ) {
                // Use getResource and getResourceAsStream
                stream = getClass().getClassLoader()
                    .getResourceAsStream(defaultWebXml);
                if( stream != null ) {
                    source = new InputSource
                            (getClass().getClassLoader()
                            .getResource(defaultWebXml).toString());
                }

                if (stream == null) {
                    // maybe embedded
                    stream = getClass().getClassLoader()
                        .getResourceAsStream("web-embed.xml");
                    if( stream != null ) {
                        source = new InputSource
                        (getClass().getClassLoader()
                                .getResource("web-embed.xml").toString());
                    }                                        
                }

                if( stream== null ) {
                    if (log.isLoggable(Level.INFO)) {
                        log.log(Level.INFO, NO_DEFAULT_WEB_XML_INFO);
                    }
                    // no default web.xml
                    return;
                }
            } else {
                source =
                    new InputSource("file://" + file.getAbsolutePath());
                stream = new FileInputStream(file);
            }
        } catch (Exception e) {
            String msg = MessageFormat.format(rb.getString(MISSING_DEFAULT_WEB_XML_EXCEPTION),
                                              new Object[] {defaultWebXml, file});
            throw new LifecycleException(msg, e);
        }

        // Process the default web.xml file
        synchronized (webDigester) {
            try {
                source.setByteStream(stream);
                webDigester.setDebug(getDebug());
                // JFA
                if (context instanceof StandardContext)
                    ((StandardContext) context).setReplaceWelcomeFiles(true);
                webDigester.clear();
                webDigester.setClassLoader(this.getClass().getClassLoader());
                webDigester.setUseContextClassLoader(false);
                webDigester.push(context);
                webDigester.parse(source);
            } catch (SAXParseException e) {
                String msg = MessageFormat.format(rb.getString(PARSE_ERROR_IN_DEFAULT_WEB_XML_EXCEPTION),
                                                  new Object[] {e.getLineNumber(), e.getColumnNumber()});
                throw new LifecycleException(msg, e);
            } catch (Exception e) {
                throw new LifecycleException(rb.getString(PARSE_ERROR_IN_DEFAULT_WEB_XML), e);
            } finally {
                try {
                    if (stream != null) {
                        stream.close();
                    }
                } catch (IOException e) {
                    log.log(Level.SEVERE, ERROR_CLOSING_DEFAULT_WEB_XML_EXCEPTION, e);
                }
            }
        }
        webRuleSet.recycle();
       
        long t2=System.currentTimeMillis();
        if( (t2-t1) > 200 && log.isLoggable(Level.FINE) )
            log.log(Level.FINE, "Processed default web.xml " + file + " "  + ( t2-t1));
    }


    // START GlassFish 2439
    /**
     * Process the default configuration file, if it exists.
     */
    protected void contextConfig() {

        if( defaultContextXml==null ) getDefaultContextXml();

        if (!context.getOverride()) {
            processContextConfig(new File(getBaseDir()), defaultContextXml);
        }

        if (context.getConfigFile() != null)
            processContextConfig(new File(context.getConfigFile()), null);

    }


    /**
     * Process a context.xml.
     */
    protected void processContextConfig(File baseDir, String resourceName) {
        if (log.isLoggable(Level.FINE))
            log.log(Level.FINE, "Processing context [" + context.getName() +
                    "] configuration file " + baseDir + " " + resourceName);

        InputSource source = null;
        InputStream stream = null;

        File file = baseDir;
        if (resourceName != null) {
            file = new File(baseDir, resourceName);
        }
        try {
            if ( !file.exists() ) {
                if (resourceName != null) {
                    // Use getResource and getResourceAsStream
                    stream = getClass().getClassLoader()
                        .getResourceAsStream(resourceName);
                    if( stream != null ) {
                        source = new InputSource
                            (getClass().getClassLoader()
                            .getResource(resourceName).toString());
                    }
                }
            } else {
                source =
                    new InputSource("file://" + file.getAbsolutePath());
                stream = new FileInputStream(file);
                // Add as watched resource so that cascade reload occurs if a default
                // config file is modified/added/removed
                context.addWatchedResource(file.getAbsolutePath());
            }
        } catch (Exception e) {
            String msg = MessageFormat.format(rb.getString(MISSING_DEFAULT_WEB_XML_EXCEPTION),
                                              new Object[] {resourceName, file});
            log.log(Level.SEVERE, msg, e);
        }

        if (source == null) {
            if (stream != null) {
                try {
                    stream.close();
                } catch(IOException e) {
                    log.log(Level.SEVERE, ERROR_CLOSING_DEFAULT_WEB_XML_EXCEPTION, e);
                }
            }

            return;
        }

        synchronized (contextDigester) {
            try {
                source.setByteStream(stream);
                contextDigester.setClassLoader(classLoader);
                contextDigester.setUseContextClassLoader(false);
                contextDigester.push(context.getParent());
                contextDigester.push(context);
                contextDigester.setErrorHandler(new ContextErrorHandler());
                contextDigester.parse(source);
                if (parseException != null) {
                    ok = false;
                }
                if (log.isLoggable(Level.FINE))
                    log.log(Level.FINE, "Successfully processed context [" +
                            context.getName() + "] configuration file " +
                            baseDir + " " + resourceName);
            } catch (SAXParseException e) {
                String msg = MessageFormat.format(rb.getString(PARSE_ERROR_IN_DEFAULT_WEB_XML_EXCEPTION),
                                                  new Object[] {e.getLineNumber(), e.getColumnNumber()});
                log.log(Level.SEVERE, PARSE_ERROR_IN_DEFAULT_WEB_XML, e);
                log.log(Level.SEVERE, msg);
                ok = false;
            } catch (Exception e) {
                log.log(Level.SEVERE, PARSE_ERROR_IN_DEFAULT_WEB_XML, e);
                ok = false;
            } finally {
                //contextDigester.reset();
                parseException = null;
                try {
                    if (stream != null) {
                        stream.close();
                    }
                } catch (IOException e) {
                    log.log(Level.SEVERE, ERROR_CLOSING_DEFAULT_WEB_XML_EXCEPTION, e);
                }
            }
        }

    }
    // END GlassFish 2439

       
    /**
     * Adjust docBase.
     */
    protected void fixDocBase()
        throws IOException {
       
        Host host = (Host) context.getParent();
        String appBase = host.getAppBase();
       
        boolean unpackWARs = true;
        if (host instanceof StandardHost) {
            unpackWARs = ((StandardHost) host).isUnpackWARs()
                && ((StandardContext) context).getUnpackWAR();
        }

        File canonicalAppBase = null;
        if (appBase != null) {
            canonicalAppBase = new File(appBase);
            if (canonicalAppBase.isAbsolute()) {
                canonicalAppBase = canonicalAppBase.getCanonicalFile();
            } else {
                canonicalAppBase =
                    new File(System.getProperty("catalina.base"), appBase)
                    .getCanonicalFile();
            }
        }

        String docBase = context.getDocBase();
        if (docBase == null) {
            // Trying to guess the docBase according to the path
            String path = context.getPath();
            if (path == null) {
                return;
            }
            if (path.equals("")) {
                docBase = "ROOT";
            } else {
                if (path.startsWith("/")) {
                    docBase = path.substring(1).replace('/', '#');
                } else {
                    docBase = path.replace('/', '#');
                }
            }
        }

        File file = new File(docBase);
        if (!file.isAbsolute() && canonicalAppBase != null) {
            docBase = (new File(canonicalAppBase, docBase)).getPath();
        } else {
            docBase = file.getCanonicalPath();
        }
        file = new File(docBase);
        String origDocBase = docBase;
       
        String pathName = context.getPath();
        if (pathName.equals("")) {
            pathName = "ROOT";
        } else {
            // Context path must start with '/'
            pathName = pathName.substring(1).replace('/','#');
        }
        if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") && !file.isDirectory() && unpackWARs) {
            URL war = new URL("jar:" + (new File(docBase)).toURI().toURL() + "!/");
            docBase = ExpandWar.expand(host, war, pathName);
            file = new File(docBase);
            docBase = file.getCanonicalPath();
            if (context instanceof StandardContext) {
                ((StandardContext) context).setOriginalDocBase(origDocBase);
            }
        } else if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") &&
                !file.isDirectory() && !unpackWARs) {
            URL war =
                new URL("jar:" + (new File (docBase)).toURI().toURL() + "!/");
            ExpandWar.validate(host, war, pathName);
        } else {
            File docDir = new File(docBase);
            if (!docDir.exists()) {
                File warFile = new File(docBase + ".war");
                if (warFile.exists()) {
                    URL war =
                        new URL("jar:" + warFile.toURI().toURL() + "!/");
                    if (unpackWARs) {
                        docBase = ExpandWar.expand(host, war, pathName);
                        file = new File(docBase);
                        docBase = file.getCanonicalPath();
                    } else {
                        docBase = warFile.getCanonicalPath();
                        ExpandWar.validate(host, war, pathName);
                    }
                }
                if (context instanceof StandardContext) {
                    ((StandardContext) context).setOriginalDocBase(origDocBase);
                }
            }
        }

        if (canonicalAppBase != null &&
                docBase.startsWith(canonicalAppBase.getPath())) {
            docBase = docBase.substring(canonicalAppBase.getPath().length());
            docBase = docBase.replace(File.separatorChar, '/');
            if (docBase.startsWith("/")) {
                docBase = docBase.substring(1);
            }
        } else {
            docBase = docBase.replace(File.separatorChar, '/');
        }

        context.setDocBase(docBase);

    }


    /**
     * Log a message on the Logger associated with our Context (if any)
     *
     * @param message Message to be logged
     *
    private void log(String message) {

        org.apache.catalina.Logger logger = null;
        if (context != null)
            logger = context.getLogger();
        if (logger != null)
            logger.log("ContextConfig[" + context.getName() + "]: " + message);
        else
            log.info( message );
    }


    /**
     * Log a message on the Logger associated with our Context (if any)
     *
     * @param message Message to be logged
     * @param throwable Associated exception
     *
    private void log(String message, Throwable throwable) {

        org.apache.catalina.Logger logger = null;
        if (context != null)
            logger = context.getLogger();
        if (logger != null)
            logger.log("ContextConfig[" + context.getName() + "] "
                       + message, throwable);
        else {
            log.log(Level.SEVERE, message, throwable );
        }
    }
    */


   
    // START GlassFish 2439
    /**
     * Process a "init" event for this Context.
     */
    protected void init() {
        // Called from StandardContext.init()

        if (log.isLoggable(Level.FINE))
            log.log(Level.FINE, CONTEXT_CONFIG_INIT_FINE);
        context.setConfigured(false);
        ok = true;

        contextConfig();
       
        try {
            fixDocBase();
        } catch (IOException e) {
            log.log(Level.SEVERE, FIXING_DOC_BASE_EXCEPTION, e);
        }


    }
    // END GlassFish 2439


    /**
     * Process a "start" event for this Context - in background
     */
    protected synchronized void start() throws LifecycleException {
        if (log.isLoggable(Level.FINEST)) {
            log.log(Level.FINEST, PROCESSING_START_FINEST);
        }

        context.setConfigured(false);

        // Set properties based on DefaultContext
        Container container = context.getParent();
        if( !context.getOverride() ) {
            if( container instanceof Host ) {
            
                // Reset the value only if the attribute wasn't
                // set on the context.
                xmlValidation = context.getXmlValidation();
                if (!xmlValidation) {
                    xmlValidation = ((Host)container).getXmlValidation();
                }
               
                xmlNamespaceAware = context.getXmlNamespaceAware();
                if (!xmlNamespaceAware){
                    xmlNamespaceAware
                                = ((Host)container).getXmlNamespaceAware();
                }

            }
        }

        // Process the default and application web.xml files
        defaultConfig();
        applicationConfig();
        validateSecurityRoles();

        // Configure an authenticator if we need one
        authenticatorConfig();

        // Configure a manager
        managerConfig();

        // Dump the contents of this pipeline if requested
        if ((log.isLoggable(Level.FINEST)) &&
                (context instanceof ContainerBase)) {
            log.log(Level.FINEST, "Pipline Configuration:");
            Pipeline pipeline = ((ContainerBase) context).getPipeline();
            GlassFishValve valves[] = null;
            if (pipeline != null)
                valves = pipeline.getValves();
            if (valves != null) {
                for (int i = 0; i < valves.length; i++) {
                    log.log(Level.FINEST, "  " + valves[i].getInfo());
                }
            }
            log.log(Level.FINEST, "======================");
        }

        // Make our application available because no problems
        // were encountered
        context.setConfigured(true);
    }


    /**
     * Process a "stop" event for this Context.
     */
    protected synchronized void stop() {

        if (log.isLoggable(Level.FINEST))
            log.log(Level.FINEST, PROCESSING_STOP_FINEST);

        int i;

        // Removing children
        Container[] children = context.findChildren();
        for (i = 0; i < children.length; i++) {
            context.removeChild(children[i]);
        }

        // Removing application parameters
/*        ApplicationParameter[] applicationParameters =
            context.findApplicationParameters();
        for (i = 0; i < applicationParameters.length; i++) {
            context.removeApplicationParameter
                (applicationParameters[i].getName());
        }
*/
        // Removing security constraints
        context.removeConstraints();

        // Removing Ejbs
        /*
        ContextEjb[] contextEjbs = context.findEjbs();
        for (i = 0; i < contextEjbs.length; i++) {
            context.removeEjb(contextEjbs[i].getName());
        }
        */

        // Removing environments
        /*
        ContextEnvironment[] contextEnvironments = context.findEnvironments();
        for (i = 0; i < contextEnvironments.length; i++) {
            context.removeEnvironment(contextEnvironments[i].getName());
        }
        */

        // Removing errors pages
        context.removeErrorPages();

        // Removing filter defs
        FilterDef[] filterDefs = context.findFilterDefs();
        for (i = 0; i < filterDefs.length; i++) {
            context.removeFilterDef(filterDefs[i]);
        }

        // Removing filter maps
        context.removeFilterMaps();

        // Removing local ejbs
        /*
        ContextLocalEjb[] contextLocalEjbs = context.findLocalEjbs();
        for (i = 0; i < contextLocalEjbs.length; i++) {
            context.removeLocalEjb(contextLocalEjbs[i].getName());
        }
        */

        // Removing Mime mappings
        String[] mimeMappings = context.findMimeMappings();
        for (i = 0; i < mimeMappings.length; i++) {
            context.removeMimeMapping(mimeMappings[i]);
        }

        // Removing parameters
        String[] parameters = context.findParameters();
        for (i = 0; i < parameters.length; i++) {
            context.removeParameter(parameters[i]);
        }

        // Removing resource env refs
        /*
        String[] resourceEnvRefs = context.findResourceEnvRefs();
        for (i = 0; i < resourceEnvRefs.length; i++) {
            context.removeResourceEnvRef(resourceEnvRefs[i]);
        }
        */

        // Removing resource links
        /*
        ContextResourceLink[] contextResourceLinks =
            context.findResourceLinks();
        for (i = 0; i < contextResourceLinks.length; i++) {
            context.removeResourceLink(contextResourceLinks[i].getName());
        }
        */

        // Removing resources
        /*
        ContextResource[] contextResources = context.findResources();
        for (i = 0; i < contextResources.length; i++) {
            context.removeResource(contextResources[i].getName());
        }
        */

        // Removing sercurity role
        context.removeSecurityRoles();

        // Removing servlet mappings
        String[] servletMappings = context.findServletMappings();
        for (i = 0; i < servletMappings.length; i++) {
            context.removeServletMapping(servletMappings[i]);
        }

        // FIXME : Removing status pages

        // Removing welcome files
        context.removeWelcomeFiles();

        // Removing wrapper lifecycles
        context.removeWrapperLifecycles();

        // Removing wrapper listeners
        context.removeWrapperListeners();

        ok = true;

    }

    /**
     * Validate the usage of security role names in the web application
     * deployment descriptor.  If any problems are found, issue warning
     * messages (for backwards compatibility) and add the missing roles.
     * (To make these problems fatal instead, simply set the <code>ok</code>
     * instance variable to <code>false</code> as well).
     */
    protected void validateSecurityRoles() {

        // Check role names used in <security-constraint> elements
        Iterator<SecurityConstraint> iter =
            context.getConstraints().iterator();
        while (iter.hasNext()) {
            for (String role : iter.next().findAuthRoles()) {
                if (!"*".equals(role) &&
                        !context.hasSecurityRole(role)) {
                    if (log.isLoggable(Level.INFO)) {
                        log.log(Level.INFO, SECURITY_ROLE_NAME_USED_IN_AUTH_WITHOUT_DEFINITION,
                                new Object[] {role, context.getName()});
                    }
                    context.addSecurityRole(role);
                }
            }
        }

        // Check role names used in <servlet> elements
        Container wrappers[] = context.findChildren();
        for (int i = 0; i < wrappers.length; i++) {
            Wrapper wrapper = (Wrapper) wrappers[i];
            String runAs = wrapper.getRunAs();
            if ((runAs != null) && !context.hasSecurityRole(runAs)) {
                if (log.isLoggable(Level.INFO)) {
                    log.log(Level.INFO, SECURITY_ROLE_NAME_USED_IN_RUNAS_WITHOUT_DEFINITION,
                            new Object[] {runAs, context.getName()});
                }
                context.addSecurityRole(runAs);
            }
            String names[] = wrapper.findSecurityReferences();
            for (int j = 0; j < names.length; j++) {
                String link = wrapper.findSecurityReference(names[j]);
                if ((link != null) && !context.hasSecurityRole(link)) {
                    if (log.isLoggable(Level.INFO)) {
                        log.log(Level.INFO, SECURITY_ROLE_NAME_USED_IN_LINK_WITHOUT_DEFINITION,
                                new Object[] {link, context.getName()});
                    }
                    context.addSecurityRole(link);
                }
            }
        }

    }


    // START GlassFish 2439
    protected class ContextErrorHandler
        implements ErrorHandler {

        public void error(SAXParseException exception) {
            parseException = exception;
        }

        public void fatalError(SAXParseException exception) {
            parseException = exception;
        }

        public void warning(SAXParseException exception) {
            parseException = exception;
        }

    }
    // END GlassFish 2439


} //end of public class
TOP

Related Classes of org.apache.catalina.startup.ContextConfig$ContextErrorHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.