Package org.apache.catalina.startup

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

/*
* JBoss, Home of Professional Open Source
* Copyright 2009, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 1999-2009 The Apache Software Foundation
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.servlet.HttpMethodConstraintElement;
import javax.servlet.ServletSecurityElement;
import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
import javax.servlet.annotation.ServletSecurity.TransportGuarantee;

import org.apache.catalina.Authenticator;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Valve;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.ContainerBase;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.deploy.ErrorPage;
import org.apache.catalina.deploy.FilterDef;
import org.apache.catalina.deploy.FilterMap;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityCollection;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.catalina.util.StringManager;

/**
* 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: 1441 $ $Date: 2010-04-16 15:49:07 +0200 (Fri, 16 Apr 2010) $
*/

public class ContextConfig
    implements LifecycleListener {

    protected static org.jboss.logging.Logger log=
        org.jboss.logging.Logger.getLogger( ContextConfig.class );

    // ----------------------------------------------------- Instance Variables


    /**
     * Custom mappings of login methods to authenticators
     */
    protected Map customAuthenticators;


    /**
     * 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.
     */
    protected static Properties authenticators = null;


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


    /**
     * Track any fatal errors during startup configuration processing.
     */
    protected boolean ok = false;


    /**
     * The string resources for this package.
     */
    protected static final StringManager sm =
        StringManager.getManager(Constants.Package);


    /**
     * Deployment count.
     */
    protected static long deploymentCount = 0L;
   
   
    protected static final LoginConfig DUMMY_LOGIN_CONFIG =
                                new LoginConfig("NONE", null, null, null);


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


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


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


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

        // Identify the context we are associated with
        try {
            context = (Context) event.getLifecycle();
        } catch (ClassCastException e) {
            log.error(sm.getString("contextConfig.cce", event.getLifecycle()), e);
            return;
        }

        // Process the event that has occurred
        if (event.getType().equals(Lifecycle.START_EVENT)) {
            start();
        } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
            beforeStart();
        } else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
           
        } else if (event.getType().equals(Context.COMPLETE_CONFIG_EVENT)) {
            completeConfig();
        } else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
            stop();
        } else if (event.getType().equals(Lifecycle.INIT_EVENT)) {
            init();
        } else if (event.getType().equals(Lifecycle.DESTROY_EVENT)) {
            destroy();
        }

    }


    // -------------------------------------------------------- Protected Methods


    /**
     * Process the application configuration file, if it exists.
     */
    protected void applicationWebConfig() {
    }
   
    /**
     * Parse TLDs. This is separate, and is not subject to the order defined. Also,
     * all TLDs from all JARs are parsed.
     */
    protected void applicationTldConfig() {
       
    }
   

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

        // Does this Context require an Authenticator?
        SecurityConstraint constraints[] = context.findConstraints();
        if ((constraints == null) || (constraints.length == 0))
            return;
        LoginConfig loginConfig = context.getLoginConfig();
        if (loginConfig == null) {
            loginConfig = DUMMY_LOGIN_CONFIG;
            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) {
                Valve basic = pipeline.getBasic();
                if ((basic != null) && (basic instanceof Authenticator))
                    return;
                Valve 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?
        if (context.getRealm() == null) {
            log.error(sm.getString("contextConfig.missingRealm"));
            ok = false;
            return;
        }

        /*
         * 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.
         */
        Valve authenticator = null;
        if (customAuthenticators != null) {
            authenticator = (Valve)
                customAuthenticators.get(loginConfig.getAuthMethod());
        }
        if (authenticator == null) {
            // Load our mapping properties if necessary
            if (authenticators == null) {
                try {
                    InputStream is=this.getClass().getClassLoader().getResourceAsStream("org/apache/catalina/startup/Authenticators.properties");
                    if( is!=null ) {
                        authenticators = new Properties();
                        authenticators.load(is);
                    } else {
                        log.error(sm.getString(
                                "contextConfig.authenticatorResources"));
                        ok=false;
                        return;
                    }
                } catch (IOException e) {
                    log.error(sm.getString(
                                "contextConfig.authenticatorResources"), e);
                    ok = false;
                    return;
                }
            }

            // Identify the class name of the Valve we should configure
            String authenticatorName = null;
            authenticatorName =
                    authenticators.getProperty(loginConfig.getAuthMethod());
            if (authenticatorName == null) {
                log.error(sm.getString("contextConfig.authenticatorMissing",
                                 loginConfig.getAuthMethod()));
                ok = false;
                return;
            }

            // Instantiate and install an Authenticator of the requested class
            try {
                Class authenticatorClass = Class.forName(authenticatorName);
                authenticator = (Valve) authenticatorClass.newInstance();
            } catch (Throwable t) {
                log.error(sm.getString(
                                    "contextConfig.authenticatorInstantiate",
                                    authenticatorName),
                          t);
                ok = false;
            }
        }

        if (authenticator instanceof Authenticator) {
            context.setAuthenticator((Authenticator) authenticator);
        }
        if (authenticator != null && context instanceof ContainerBase) {
            Pipeline pipeline = ((ContainerBase) context).getPipeline();
            if (pipeline != null) {
                ((ContainerBase) context).addValve(authenticator);
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString(
                                    "contextConfig.authenticatorConfigured",
                                    loginConfig.getAuthMethod()));
                }
            }
        }

    }


    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 defaultWebConfig() {
       
    }


    /**
     * Parse fragments order.
     */
    protected void createFragmentsOrder() {
       
    }
   
   
    /**
     * Process additional descriptors: TLDs, web fragments, and map overlays.
     */
    protected void applicationExtraDescriptorsConfig() {
       
    }
   
   
    /**
     * Find and parse ServletContainerInitializer service in specified JAR.
     */
    public void applicationServletContainerInitializerConfig() {
       
    }
   
   
    /**
     * Process a "init" event for this Context.
     */
    protected void init() {
            if (log.isDebugEnabled())
            log.debug(sm.getString("contextConfig.init"));
        context.setConfigured(false);
        ok = true;
    }
   
   
    /**
     * Process a "before start" event for this Context.
     */
    protected void beforeStart() {
    }
   
   
    /**
     * Process a "start" event for this Context.
     */
    protected void start() {
        // Called from StandardContext.start()

        if (log.isDebugEnabled())
            log.debug(sm.getString("contextConfig.start"));

        // Process the default and application web.xml files
        if (ok) {
            defaultWebConfig();
        }
        // Scan the main descriptors
        if (ok) {
            applicationWebConfig();
        }
        // Parse any Servlet context initializer defined in a Jar
        if (ok) {
            applicationServletContainerInitializerConfig();
        }
        // Parse fragment order
        if (ok && !context.getIgnoreAnnotations()) {
            createFragmentsOrder();
        }
        // Scan fragments, TLDs and annotations
        if (ok) {
            applicationExtraDescriptorsConfig();
        }
        // Parse any TLDs found for listeners
        if (ok) {
            applicationTldConfig();
        }

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

        // Make our application available if no problems were encountered
        if (ok) {
            context.setConfigured(true);
        } else {
            log.error(sm.getString("contextConfig.unavailable"));
            context.setConfigured(false);
        }

    }

    /**
     * Process a "start" event for this Context.
     */
    protected void completeConfig() {
       
    }

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

        if (log.isDebugEnabled())
            log.debug(sm.getString("contextConfig.stop"));

        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
        SecurityConstraint[] securityConstraints = context.findConstraints();
        for (i = 0; i < securityConstraints.length; i++) {
            context.removeConstraint(securityConstraints[i]);
        }

        // Removing errors pages
        ErrorPage[] errorPages = context.findErrorPages();
        for (i = 0; i < errorPages.length; i++) {
            context.removeErrorPage(errorPages[i]);
        }

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

        // Removing filter maps
        FilterMap[] filterMaps = context.findFilterMaps();
        for (i = 0; i < filterMaps.length; i++) {
            context.removeFilterMap(filterMaps[i]);
        }

        // 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 sercurity role
        String[] securityRoles = context.findSecurityRoles();
        for (i = 0; i < securityRoles.length; i++) {
            context.removeSecurityRole(securityRoles[i]);
        }

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

        // FIXME : Removing status pages

        // Removing taglibs
        String[] taglibs = context.findTaglibs();
        for (i = 0; i < taglibs.length; i++) {
            context.removeTaglib(taglibs[i]);
        }

        // FIXME: remove JSP property groups
       
        // FIXME: remove JSP tag libraries
       
        // Removing welcome files
        String[] welcomeFiles = context.findWelcomeFiles();
        for (i = 0; i < welcomeFiles.length; i++) {
            context.removeWelcomeFile(welcomeFiles[i]);
        }

        // Removing wrapper lifecycles
        String[] wrapperLifecycles = context.findWrapperLifecycles();
        for (i = 0; i < wrapperLifecycles.length; i++) {
            context.removeWrapperLifecycle(wrapperLifecycles[i]);
        }

        // Removing wrapper listeners
        String[] wrapperListeners = context.findWrapperListeners();
        for (i = 0; i < wrapperListeners.length; i++) {
            context.removeWrapperListener(wrapperListeners[i]);
        }

        ok = true;

    }
   
   
    /**
     * Process a "destroy" event for this Context.
     */
    protected void destroy() {
        // Called from StandardContext.destroy()
        if (log.isDebugEnabled())
            log.debug(sm.getString("contextConfig.destroy"));

        // Changed to getWorkPath per Bugzilla 35819.
        String workDir = ((StandardContext) context).getWorkPath();
        if (workDir != null)
            ExpandWar.delete(new File(workDir));
    }
   
   
    /**
     * Translate servlet security associated with Servlets to security constraints.
     */
    protected void resolveServletSecurity() {
        // Skip all patterns for which a static security constraint has been defined
        HashSet<String> excludedPatterns = new HashSet<String>();
        SecurityConstraint[] staticConstraints = context.findConstraints();
        for (SecurityConstraint staticConstraint : staticConstraints) {
            for (SecurityCollection collection : staticConstraint.findCollections()) {
                for (String urlPattern : collection.findPatterns()) {
                    excludedPatterns.add(urlPattern);
                }
            }
        }
        // Iterate over servlet security objects
        Container wrappers[] = context.findChildren();
        for (int i = 0; i < wrappers.length; i++) {
            Wrapper wrapper = (Wrapper) wrappers[i];
            ServletSecurityElement servletSecurity = wrapper.getServletSecurity();
            if (servletSecurity != null) {
               
                ArrayList<String> methodOmissions = new ArrayList<String>();
                boolean classPA = servletSecurity.getEmptyRoleSemantic().equals(EmptyRoleSemantic.PERMIT);
                boolean classDA = servletSecurity.getEmptyRoleSemantic().equals(EmptyRoleSemantic.DENY);
                boolean classTP = servletSecurity.getTransportGuarantee().equals(TransportGuarantee.CONFIDENTIAL);
                String[] classRA = servletSecurity.getRolesAllowed();
                Collection<HttpMethodConstraintElement> httpMethodConstraints =
                    servletSecurity.getHttpMethodConstraints();

                // Process method constraints
                if (httpMethodConstraints != null && httpMethodConstraints.size() > 0)
                {
                   for (HttpMethodConstraintElement httpMethodConstraint : httpMethodConstraints)
                   {
                       String method = toHttpMethod(httpMethodConstraint.getMethodName());
                      methodOmissions.add(method);
                      boolean methodPA = httpMethodConstraint.getEmptyRoleSemantic().equals(EmptyRoleSemantic.PERMIT);
                      boolean methodDA = httpMethodConstraint.getEmptyRoleSemantic().equals(EmptyRoleSemantic.DENY);
                      boolean methodTP = httpMethodConstraint.getTransportGuarantee().equals(TransportGuarantee.CONFIDENTIAL);
                      String[] methodRA = httpMethodConstraint.getRolesAllowed();
                      if (methodDA || methodTP || (methodRA != null && methodRA.length > 0))
                      {
                         // Define a constraint specific for the method
                         SecurityConstraint constraint = new SecurityConstraint();
                         if (methodDA) {
                             constraint.setAuthConstraint(true);
                         }
                         if (methodPA && (methodRA == null || methodRA.length == 0)) {
                             constraint.addAuthRole("*");
                         }
                         if (methodRA != null) {
                             for (String role : methodRA) {
                                 constraint.addAuthRole(role);
                             }
                         }
                         if (methodTP) {
                             constraint.setUserConstraint(org.apache.catalina.realm.Constants.CONFIDENTIAL_TRANSPORT);
                         }
                         SecurityCollection collection = new SecurityCollection();
                         collection.addMethod(method);
                         // Determine pattern set
                         String[] urlPatterns = wrapper.findMappings();
                         Set<String> servletSecurityPatterns = new HashSet<String>();
                         for (String urlPattern : urlPatterns) {
                             if (!excludedPatterns.contains(urlPattern)) {
                                 servletSecurityPatterns.add(urlPattern);
                             }
                         }
                         for (String urlPattern : servletSecurityPatterns) {
                             collection.addPattern(urlPattern);
                         }
                         constraint.addCollection(collection);
                         context.addConstraint(constraint);
                      }

                   }

                }

                if (classDA || classTP || (classRA != null && classRA.length > 0))
                {
                    // Define a constraint for the class
                    SecurityConstraint constraint = new SecurityConstraint();
                    if (classPA && (classRA == null || classRA.length == 0)) {
                        constraint.addAuthRole("*");
                    }
                    if (classDA) {
                        constraint.setAuthConstraint(true);
                    }
                    if (classRA != null) {
                        for (String role : classRA) {
                            constraint.addAuthRole(role);
                        }
                    }
                    if (classTP) {
                        constraint.setUserConstraint(org.apache.catalina.realm.Constants.CONFIDENTIAL_TRANSPORT);
                    }
                    SecurityCollection collection = new SecurityCollection();
                    // Determine pattern set
                    String[] urlPatterns = wrapper.findMappings();
                    Set<String> servletSecurityPatterns = new HashSet<String>();
                    for (String urlPattern : urlPatterns) {
                        if (!excludedPatterns.contains(urlPattern)) {
                            servletSecurityPatterns.add(urlPattern);
                        }
                    }
                    for (String urlPattern : servletSecurityPatterns) {
                        collection.addPattern(urlPattern);
                    }
                    for (String methodOmission : methodOmissions) {
                        collection.addMethodOmission(methodOmission);
                    }
                    constraint.addCollection(collection);
                    context.addConstraint(constraint);
                }
               
            }
        }
    }
   
   
    /**
     * Although this does not comply with the spec, it is likely Java method names
     * will be used in the annotations. Since it is not possible to validate, this
     * would be an error that is invisible for the user.
     * @param method
     * @return
     */
    protected String toHttpMethod(String method) {
        if (method == null || method.length() < 3 || (!method.startsWith("do")))
            return method;
        return method.substring(2).toUpperCase();
    }
   
   
    /**
     * 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
        SecurityConstraint constraints[] = context.findConstraints();
        for (int i = 0; i < constraints.length; i++) {
            String roles[] = constraints[i].findAuthRoles();
            for (int j = 0; j < roles.length; j++) {
                if (!"*".equals(roles[j]) &&
                    !context.findSecurityRole(roles[j])) {
                    log.info(sm.getString("contextConfig.role.auth", roles[j]));
                    context.addSecurityRole(roles[j]);
                }
            }
        }

        // 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.findSecurityRole(runAs)) {
                log.info(sm.getString("contextConfig.role.runas", runAs));
                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.findSecurityRole(link)) {
                    log.info(sm.getString("contextConfig.role.link", link));
                    context.addSecurityRole(link);
                }
            }
        }

    }


    protected String getHostConfigPath(String resourceName) {
        StringBuilder result = new StringBuilder();
        Container container = context;
        Container host = null;
        Container engine = null;
        while (container != null) {
            if (container instanceof Host)
                host = container;
            if (container instanceof Engine)
                engine = container;
            container = container.getParent();
        }
        if (engine != null) {
            result.append(engine.getName()).append('/');
        }
        if (host != null) {
            result.append(host.getName()).append('/');
        }
        result.append(resourceName);
        return result.toString();
    }


}
TOP

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

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.