首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Struts1.3.10深入源代码之核心种ActionServlet类

2012-06-27 
Struts1.3.10深入源代码之核心类ActionServlet类org.apache.struts.action.ActionServlet类是Struts框架的

Struts1.3.10深入源代码之核心类ActionServlet类
org.apache.struts.action.ActionServlet类是Struts框架的核心控制器组件,所有的用户请求都由ActionServlet类来处理,然后再由ActionServlet把请求转发给其他组件。Struts框架只允许在一个应用中配置一个ActionServlet类,在应用的生命周期中,仅创建ActionServlet类的一个实例,这个ActionServlet实例可以同时相应多个用户的请求。
Struts框架的初始化过程:Servlet容器在启动时,或者用户首次请求ActionServlet时加载ActionServlet类。Servlet类在ActionServlet类被加载后立即执行它的init()方法,这可以保证当ActionServlet处理用户请求时已经被初始化。

下面是init()方法:

public void init() throws ServletException {        final String configPrefix = "config/";        final int configPrefixLength = configPrefix.length() - 1;        // Wraps the entire initialization in a try/catch to better handle        // unexpected exceptions and errors to provide better feedback        // to the developer        try {            initInternal();            initOther();            initServlet();            initChain();            getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);            initModuleConfigFactory();            // Initialize modules as needed            ModuleConfig moduleConfig = initModuleConfig("", config);            initModuleMessageResources(moduleConfig);            initModulePlugIns(moduleConfig);            initModuleFormBeans(moduleConfig);            initModuleForwards(moduleConfig);            initModuleExceptionConfigs(moduleConfig);            initModuleActions(moduleConfig);            moduleConfig.freeze();            Enumeration names = getServletConfig().getInitParameterNames();            while (names.hasMoreElements()) {                String name = (String) names.nextElement();                if (!name.startsWith(configPrefix)) {                    continue;                }                String prefix = name.substring(configPrefixLength);                moduleConfig =                    initModuleConfig(prefix,                        getServletConfig().getInitParameter(name));                initModuleMessageResources(moduleConfig);                initModulePlugIns(moduleConfig);                initModuleFormBeans(moduleConfig);                initModuleForwards(moduleConfig);                initModuleExceptionConfigs(moduleConfig);                initModuleActions(moduleConfig);                moduleConfig.freeze();            }            this.initModulePrefixes(this.getServletContext());            this.destroyConfigDigester();        } catch (UnavailableException ex) {            throw ex;        } catch (Throwable t) {            // The follow error message is not retrieved from internal message            // resources as they may not have been able to have been            // initialized            log.error("Unable to initialize Struts ActionServlet due to an "                + "unexpected exception or error thrown, so marking the "                + "servlet as unavailable.  Most likely, this is due to an "                + "incorrect or missing library dependency.", t);            throw new UnavailableException(t.getMessage());        }    }

在init()初始化方法中主要有下面几步构成:
(1)调用initInternal()方法,初始化Struts框架内在的消息资源,如与系统日志相关的通知、警告和错误消息。
(2)调用initOther()方法,从web.xml文件中加载ActionServlet的初始化参数,如congig参数。
(3)调用initServlet()方法,从web.xml文件中加载ActionServlet的URL映射信息。此外还会注册web.xml和Struts配置文件所使用的DTD文件,这些DTD文件用来验证web.xml和Struts配置文件的语法。
(4)调用initModuleConfig()方法,加载并解析默认子应用模块的Struts配置文件,创建ModuleConfig对象,把它存储在ServletContext中。
(5)调用initModuleMessageResources()方法,加载并初始化默认子应用模块的消息资源;创建MessageResources对象,把它存储在ServletContext中。
(6)调用initModuleDataSources(),加载并初始化默认子应用模块的数据源。
(7)调用initModulePlugins()方法,加载并初始化默认子应用模块的所有插件。
(8)当默认子模块被成功地初始化后,如果还包括其他子应用模块,将重复流程(4)~(7),分别对其他子应用模块进行初始化。


下面是ActionSerlet类的完整源代码
package org.apache.struts.action;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.ConvertUtils;import org.apache.commons.beanutils.PropertyUtils;import org.apache.commons.beanutils.converters.BigDecimalConverter;import org.apache.commons.beanutils.converters.BigIntegerConverter;import org.apache.commons.beanutils.converters.BooleanConverter;import org.apache.commons.beanutils.converters.ByteConverter;import org.apache.commons.beanutils.converters.CharacterConverter;import org.apache.commons.beanutils.converters.DoubleConverter;import org.apache.commons.beanutils.converters.FloatConverter;import org.apache.commons.beanutils.converters.IntegerConverter;import org.apache.commons.beanutils.converters.LongConverter;import org.apache.commons.beanutils.converters.ShortConverter;import org.apache.commons.chain.CatalogFactory;import org.apache.commons.chain.config.ConfigParser;import org.apache.commons.digester.Digester;import org.apache.commons.digester.RuleSet;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.struts.Globals;import org.apache.struts.config.ActionConfig;import org.apache.struts.config.ConfigRuleSet;import org.apache.struts.config.ExceptionConfig;import org.apache.struts.config.FormBeanConfig;import org.apache.struts.config.FormPropertyConfig;import org.apache.struts.config.ForwardConfig;import org.apache.struts.config.MessageResourcesConfig;import org.apache.struts.config.ModuleConfig;import org.apache.struts.config.ModuleConfigFactory;import org.apache.struts.config.PlugInConfig;import org.apache.struts.util.MessageResources;import org.apache.struts.util.MessageResourcesFactory;import org.apache.struts.util.ModuleUtils;import org.apache.struts.util.RequestUtils;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.UnavailableException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.math.BigDecimal;import java.math.BigInteger;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.util.ArrayList;import java.util.Enumeration;import java.util.Iterator;import java.util.List;import java.util.MissingResourceException;public class ActionServlet extends HttpServlet {    /**     * <p>Commons Logging instance.</p>     *     * @since Struts 1.1     */    protected static Log log = LogFactory.getLog(ActionServlet.class);    // ----------------------------------------------------- Instance Variables    /**     * <p>Comma-separated list of context-relative path(s) to our     * configuration resource(s) for the default module.</p>     */    protected String config = "/WEB-INF/struts-config.xml";    /**     * <p>Comma-separated list of context or classloader-relative path(s) that     * contain the configuration for the default commons-chain     * catalog(s).</p>     */    protected String chainConfig = "org/apache/struts/chain/chain-config.xml";    /**     * <p>The Digester used to produce ModuleConfig objects from a Struts     * configuration file.</p>     *     * @since Struts 1.1     */    protected Digester configDigester = null;    /**     * <p>The flag to request backwards-compatible conversions for form bean     * properties of the Java wrapper class types.</p>     *     * @since Struts 1.1     */    protected boolean convertNull = false;    /**     * <p>The resources object for our internal resources.</p>     */    protected MessageResources internal = null;    /**     * <p>The Java base name of our internal resources.</p>     *     * @since Struts 1.1     */    protected String internalName = "org.apache.struts.action.ActionResources";    /**     * <p>The set of public identifiers, and corresponding resource names, for     * the versions of the configuration file DTDs that we know about.  There     * <strong>MUST</strong> be an even number of Strings in this list!</p>     */    protected String[] registrations =        {            "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN",            "/org/apache/struts/resources/struts-config_1_0.dtd",            "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN",            "/org/apache/struts/resources/struts-config_1_1.dtd",            "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN",            "/org/apache/struts/resources/struts-config_1_2.dtd",            "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN",            "/org/apache/struts/resources/struts-config_1_3.dtd",            "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",            "/org/apache/struts/resources/web-app_2_3.dtd"        };    /**     * <p>The URL pattern to which we are mapped in our web application     * deployment descriptor.</p>     */    protected String servletMapping = null; // :FIXME: - multiples?    /**     * <p>The servlet name under which we are registered in our web     * application deployment descriptor.</p>     */    protected String servletName = null;    // ---------------------------------------------------- HttpServlet Methods    /**     * <p>Gracefully shut down this controller servlet, releasing any     * resources that were allocated at initialization.</p>     */    public void destroy() {        if (log.isDebugEnabled()) {            log.debug(internal.getMessage("finalizing"));        }        destroyModules();        destroyInternal();        getServletContext().removeAttribute(Globals.ACTION_SERVLET_KEY);        CatalogFactory.clear();        PropertyUtils.clearDescriptors();        // Release our LogFactory and Log instances (if any)        ClassLoader classLoader =            Thread.currentThread().getContextClassLoader();        if (classLoader == null) {            classLoader = ActionServlet.class.getClassLoader();        }        try {            LogFactory.release(classLoader);        } catch (Throwable t) {            ; // Servlet container doesn't have the latest version            // of commons-logging-api.jar installed            // :FIXME: Why is this dependent on the container's version of            // commons-logging? Shouldn't this depend on the version packaged            // with Struts?            /*              Reason: LogFactory.release(classLoader); was added as              an attempt to investigate the OutOfMemory error reported on              Bugzilla #14042. It was committed for version 1.136 by craigmcc            */        }    }    /**     * <p>Initialize this servlet.  Most of the processing has been factored     * into support methods so that you can override particular functionality     * at a fairly granular level.</p>     *     * @throws ServletException if we cannot configure ourselves correctly     */    public void init() throws ServletException {        final String configPrefix = "config/";        final int configPrefixLength = configPrefix.length() - 1;        // Wraps the entire initialization in a try/catch to better handle        // unexpected exceptions and errors to provide better feedback        // to the developer        try {            initInternal();            initOther();            initServlet();            initChain();            getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);            initModuleConfigFactory();            // Initialize modules as needed            ModuleConfig moduleConfig = initModuleConfig("", config);            initModuleMessageResources(moduleConfig);            initModulePlugIns(moduleConfig);            initModuleFormBeans(moduleConfig);            initModuleForwards(moduleConfig);            initModuleExceptionConfigs(moduleConfig);            initModuleActions(moduleConfig);            moduleConfig.freeze();            Enumeration names = getServletConfig().getInitParameterNames();            while (names.hasMoreElements()) {                String name = (String) names.nextElement();                if (!name.startsWith(configPrefix)) {                    continue;                }                String prefix = name.substring(configPrefixLength);                moduleConfig =                    initModuleConfig(prefix,                        getServletConfig().getInitParameter(name));                initModuleMessageResources(moduleConfig);                initModulePlugIns(moduleConfig);                initModuleFormBeans(moduleConfig);                initModuleForwards(moduleConfig);                initModuleExceptionConfigs(moduleConfig);                initModuleActions(moduleConfig);                moduleConfig.freeze();            }            this.initModulePrefixes(this.getServletContext());            this.destroyConfigDigester();        } catch (UnavailableException ex) {            throw ex;        } catch (Throwable t) {            // The follow error message is not retrieved from internal message            // resources as they may not have been able to have been            // initialized            log.error("Unable to initialize Struts ActionServlet due to an "                + "unexpected exception or error thrown, so marking the "                + "servlet as unavailable.  Most likely, this is due to an "                + "incorrect or missing library dependency.", t);            throw new UnavailableException(t.getMessage());        }    }    /**     * <p>Saves a String[] of module prefixes in the ServletContext under     * Globals.MODULE_PREFIXES_KEY.  <strong>NOTE</strong> - the "" prefix for     * the default module is not included in this list.</p>     *     * @param context The servlet context.     * @since Struts 1.2     */    protected void initModulePrefixes(ServletContext context) {        ArrayList prefixList = new ArrayList();        Enumeration names = context.getAttributeNames();        while (names.hasMoreElements()) {            String name = (String) names.nextElement();            if (!name.startsWith(Globals.MODULE_KEY)) {                continue;            }            String prefix = name.substring(Globals.MODULE_KEY.length());            if (prefix.length() > 0) {                prefixList.add(prefix);            }        }        String[] prefixes =            (String[]) prefixList.toArray(new String[prefixList.size()]);        context.setAttribute(Globals.MODULE_PREFIXES_KEY, prefixes);    }    /**     * <p>Process an HTTP "GET" request.</p>     *     * @param request  The servlet request we are processing     * @param response The servlet response we are creating     * @throws IOException      if an input/output error occurs     * @throws ServletException if a servlet exception occurs     */    public void doGet(HttpServletRequest request, HttpServletResponse response)        throws IOException, ServletException {        process(request, response);    }    /**     * <p>Process an HTTP "POST" request.</p>     *     * @param request  The servlet request we are processing     * @param response The servlet response we are creating     * @throws IOException      if an input/output error occurs     * @throws ServletException if a servlet exception occurs     */    public void doPost(HttpServletRequest request, HttpServletResponse response)        throws IOException, ServletException {        process(request, response);    }    // --------------------- Public Methods    /**     * <p>Remember a servlet mapping from our web application deployment     * descriptor, if it is for this servlet.</p>     *     * @param servletName The name of the servlet being mapped     * @param urlPattern  The URL pattern to which this servlet is mapped     */    public void addServletMapping(String servletName, String urlPattern) {        if (servletName == null) {            return;        }        if (servletName.equals(this.servletName)) {            if (log.isDebugEnabled()) {                log.debug("Process servletName=" + servletName                    + ", urlPattern=" + urlPattern);            }            this.servletMapping = urlPattern;        }    }    /**     * <p>Return the <code>MessageResources</code> instance containing our     * internal message strings.</p>     *     * @return the <code>MessageResources</code> instance containing our     *         internal message strings.     * @since Struts 1.1     */    public MessageResources getInternal() {        return (this.internal);    }    // ------------------------------------------------------ Protected Methods    /**     * <p>Gracefully terminate use of any modules associated with this     * application (if any).</p>     *     * @since Struts 1.1     */    protected void destroyModules() {        ArrayList values = new ArrayList();        Enumeration names = getServletContext().getAttributeNames();        while (names.hasMoreElements()) {            values.add(names.nextElement());        }        Iterator keys = values.iterator();        while (keys.hasNext()) {            String name = (String) keys.next();            Object value = getServletContext().getAttribute(name);            if (!(value instanceof ModuleConfig)) {                continue;            }            ModuleConfig config = (ModuleConfig) value;            if (this.getProcessorForModule(config) != null) {                this.getProcessorForModule(config).destroy();            }            getServletContext().removeAttribute(name);            PlugIn[] plugIns =                (PlugIn[]) getServletContext().getAttribute(Globals.PLUG_INS_KEY                    + config.getPrefix());            if (plugIns != null) {                for (int i = 0; i < plugIns.length; i++) {                    int j = plugIns.length - (i + 1);                    plugIns[j].destroy();                }                getServletContext().removeAttribute(Globals.PLUG_INS_KEY                    + config.getPrefix());            }        }    }    /**     * <p>Gracefully release any configDigester instance that we have created.     * </p>     *     * @since Struts 1.1     */    protected void destroyConfigDigester() {        configDigester = null;    }    /**     * <p>Gracefully terminate use of the internal MessageResources.</p>     */    protected void destroyInternal() {        internal = null;    }    /**     * <p>Return the module configuration object for the currently selected     * module.</p>     *     * @param request The servlet request we are processing     * @return The module configuration object for the currently selected     *         module.     * @since Struts 1.1     */    protected ModuleConfig getModuleConfig(HttpServletRequest request) {        ModuleConfig config =            (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);        if (config == null) {            config =                (ModuleConfig) getServletContext().getAttribute(Globals.MODULE_KEY);        }        return (config);    }    /**     * <p>Look up and return the {@link RequestProcessor} responsible for the     * specified module, creating a new one if necessary.</p>     *     * @param config The module configuration for which to acquire and return     *               a RequestProcessor.     * @return The {@link RequestProcessor} responsible for the specified     *         module,     * @throws ServletException If we cannot instantiate a RequestProcessor     *                          instance a {@link UnavailableException} is     *                          thrown, meaning your application is not loaded     *                          and will not be available.     * @since Struts 1.1     */    protected synchronized RequestProcessor getRequestProcessor(        ModuleConfig config) throws ServletException {        RequestProcessor processor = this.getProcessorForModule(config);        if (processor == null) {            try {                processor =                    (RequestProcessor) RequestUtils.applicationInstance(config.getControllerConfig()                                                                              .getProcessorClass());            } catch (Exception e) {                throw new UnavailableException(                    "Cannot initialize RequestProcessor of class "                    + config.getControllerConfig().getProcessorClass() + ": "                    + e);            }            processor.init(this, config);            String key = Globals.REQUEST_PROCESSOR_KEY + config.getPrefix();            getServletContext().setAttribute(key, processor);        }        return (processor);    }    /**     * <p>Returns the RequestProcessor for the given module or null if one     * does not exist.  This method will not create a RequestProcessor.</p>     *     * @param config The ModuleConfig.     * @return The <code>RequestProcessor</code> for the given module, or     *         <code>null</code> if one does not exist.     */    private RequestProcessor getProcessorForModule(ModuleConfig config) {        String key = Globals.REQUEST_PROCESSOR_KEY + config.getPrefix();        return (RequestProcessor) getServletContext().getAttribute(key);    }    /**     * <p>Initialize the factory used to create the module configuration.</p>     *     * @since Struts 1.2     */    protected void initModuleConfigFactory() {        String configFactory =            getServletConfig().getInitParameter("configFactory");        if (configFactory != null) {            ModuleConfigFactory.setFactoryClass(configFactory);        }    }    /**     * <p>Initialize the module configuration information for the specified     * module.</p>     *     * @param prefix Module prefix for this module     * @param paths  Comma-separated list of context-relative resource path(s)     *               for this modules's configuration resource(s)     * @return The new module configuration instance.     * @throws ServletException if initialization cannot be performed     * @since Struts 1.1     */    protected ModuleConfig initModuleConfig(String prefix, String paths)        throws ServletException {        if (log.isDebugEnabled()) {            log.debug("Initializing module path '" + prefix                + "' configuration from '" + paths + "'");        }        // Parse the configuration for this module        ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();        ModuleConfig config = factoryObject.createModuleConfig(prefix);        // Configure the Digester instance we will use        Digester digester = initConfigDigester();        List urls = splitAndResolvePaths(paths);        URL url;        for (Iterator i = urls.iterator(); i.hasNext();) {            url = (URL) i.next();            digester.push(config);            this.parseModuleConfigFile(digester, url);        }        getServletContext().setAttribute(Globals.MODULE_KEY            + config.getPrefix(), config);        return config;    }    /**     * <p>Parses one module config file.</p>     *     * @param digester Digester instance that does the parsing     * @param path     The path to the config file to parse.     * @throws UnavailableException if file cannot be read or parsed     * @since Struts 1.2     * @deprecated use parseModuleConfigFile(Digester digester, URL url)     *             instead     */    protected void parseModuleConfigFile(Digester digester, String path)        throws UnavailableException {        try {            List paths = splitAndResolvePaths(path);            if (paths.size() > 0) {                // Get first path as was the old behavior                URL url = (URL) paths.get(0);                parseModuleConfigFile(digester, url);            } else {                throw new UnavailableException("Cannot locate path " + path);            }        } catch (UnavailableException ex) {            throw ex;        } catch (ServletException ex) {            handleConfigException(path, ex);        }    }    /**     * <p>Parses one module config file.</p>     *     * @param digester Digester instance that does the parsing     * @param url      The url to the config file to parse.     * @throws UnavailableException if file cannot be read or parsed     * @since Struts 1.3     */    protected void parseModuleConfigFile(Digester digester, URL url)        throws UnavailableException {        try {            digester.parse(url);        } catch (IOException e) {            handleConfigException(url.toString(), e);        } catch (SAXException e) {            handleConfigException(url.toString(), e);        }    }    /**     * <p>Simplifies exception handling in the parseModuleConfigFile     * method.<p>     *     * @param path The path to which the exception relates.     * @param e    The exception to be wrapped and thrown.     * @throws UnavailableException as a wrapper around Exception     */    private void handleConfigException(String path, Exception e)        throws UnavailableException {        String msg = internal.getMessage("configParse", path);        log.error(msg, e);        throw new UnavailableException(msg);    }    /**     * <p>Handle errors related to creating an instance of the specified     * class.</p>     *     * @param className The className that could not be instantiated.     * @param e         The exception that was caught.     * @throws ServletException to communicate the error.     */    private void handleCreationException(String className, Exception e)        throws ServletException {        String errorMessage =            internal.getMessage("configExtends.creation", className);        log.error(errorMessage, e);        throw new UnavailableException(errorMessage);    }    /**     * <p>General handling for exceptions caught while inheriting config     * information.</p>     *     * @param configType The type of configuration object of configName.     * @param configName The name of the config that could not be extended.     * @param e          The exception that was caught.     * @throws ServletException to communicate the error.     */    private void handleGeneralExtensionException(String configType,        String configName, Exception e)        throws ServletException {        String errorMessage =            internal.getMessage("configExtends", configType, configName);        log.error(errorMessage, e);        throw new UnavailableException(errorMessage);    }    /**     * <p>Handle errors caused by required fields that were not     * specified.</p>     *     * @param field      The name of the required field that was not found.     * @param configType The type of configuration object of configName.     * @param configName The name of the config that's missing the required     *                   value.     * @throws ServletException to communicate the error.     */    private void handleValueRequiredException(String field, String configType,        String configName) throws ServletException {        String errorMessage =            internal.getMessage("configFieldRequired", field, configType,                configName);        log.error(errorMessage);        throw new UnavailableException(errorMessage);    }    /**     * <p>Initialize the plug ins for the specified module.</p>     *     * @param config ModuleConfig information for this module     * @throws ServletException if initialization cannot be performed     * @since Struts 1.1     */    protected void initModulePlugIns(ModuleConfig config)        throws ServletException {        if (log.isDebugEnabled()) {            log.debug("Initializing module path '" + config.getPrefix()                + "' plug ins");        }        PlugInConfig[] plugInConfigs = config.findPlugInConfigs();        PlugIn[] plugIns = new PlugIn[plugInConfigs.length];        getServletContext().setAttribute(Globals.PLUG_INS_KEY            + config.getPrefix(), plugIns);        for (int i = 0; i < plugIns.length; i++) {            try {                plugIns[i] =                    (PlugIn) RequestUtils.applicationInstance(plugInConfigs[i]                        .getClassName());                BeanUtils.populate(plugIns[i], plugInConfigs[i].getProperties());                // Pass the current plugIn config object to the PlugIn.                // The property is set only if the plugin declares it.                // This plugin config object is needed by Tiles                try {                    PropertyUtils.setProperty(plugIns[i],                        "currentPlugInConfigObject", plugInConfigs[i]);                } catch (Exception e) {                    ;                    // FIXME Whenever we fail silently, we must document a valid                    // reason for doing so.  Why should we fail silently if a                    // property can't be set on the plugin?                    /**                     * Between version 1.138-1.140 cedric made these changes.                     * The exceptions are caught to deal with containers                     * applying strict security. This was in response to bug                     * #15736                     *                     * Recommend that we make the currentPlugInConfigObject part                     * of the PlugIn Interface if we can, Rob                     */                }                plugIns[i].init(this, config);            } catch (ServletException e) {                throw e;            } catch (Exception e) {                String errMsg =                    internal.getMessage("plugIn.init",                        plugInConfigs[i].getClassName());                log(errMsg, e);                throw new UnavailableException(errMsg);            }        }    }    /**     * <p>Initialize the form beans for the specified module.</p>     *     * @param config ModuleConfig information for this module     * @throws ServletException if initialization cannot be performed     * @since Struts 1.3     */    protected void initModuleFormBeans(ModuleConfig config)        throws ServletException {        if (log.isDebugEnabled()) {            log.debug("Initializing module path '" + config.getPrefix()                + "' form beans");        }        // Process form bean extensions.        FormBeanConfig[] formBeans = config.findFormBeanConfigs();        for (int i = 0; i < formBeans.length; i++) {            FormBeanConfig beanConfig = formBeans[i];            processFormBeanExtension(beanConfig, config);        }        for (int i = 0; i < formBeans.length; i++) {            FormBeanConfig formBean = formBeans[i];            // Verify that required fields are all present for the form config            if (formBean.getType() == null) {                handleValueRequiredException("type", formBean.getName(),                    "form bean");            }            // ... and the property configs            FormPropertyConfig[] fpcs = formBean.findFormPropertyConfigs();            for (int j = 0; j < fpcs.length; j++) {                FormPropertyConfig property = fpcs[j];                if (property.getType() == null) {                    handleValueRequiredException("type", property.getName(),                        "form property");                }            }            // Force creation and registration of DynaActionFormClass instances            // for all dynamic form beans            if (formBean.getDynamic()) {                formBean.getDynaActionFormClass();            }        }    }    /**     * <p>Extend the form bean's configuration as necessary.</p>     *     * @param beanConfig   the configuration to process.     * @param moduleConfig the module configuration for this module.     * @throws ServletException if initialization cannot be performed.     */    protected void processFormBeanExtension(FormBeanConfig beanConfig,        ModuleConfig moduleConfig)        throws ServletException {        try {            if (!beanConfig.isExtensionProcessed()) {                if (log.isDebugEnabled()) {                    log.debug("Processing extensions for '"                        + beanConfig.getName() + "'");                }                beanConfig =                    processFormBeanConfigClass(beanConfig, moduleConfig);                beanConfig.processExtends(moduleConfig);            }        } catch (ServletException e) {            throw e;        } catch (Exception e) {            handleGeneralExtensionException("FormBeanConfig",                beanConfig.getName(), e);        }    }    /**     * <p>Checks if the current beanConfig is using the correct class based on     * the class of its ancestor form bean config.</p>     *     * @param beanConfig   The form bean to check.     * @param moduleConfig The config for the current module.     * @return The form bean config using the correct class as determined by     *         the config's ancestor and its own overridden value.     * @throws UnavailableException if an instance of the form bean config     *                              class cannot be created.     * @throws ServletException     on class creation error     */    protected FormBeanConfig processFormBeanConfigClass(        FormBeanConfig beanConfig, ModuleConfig moduleConfig)        throws ServletException {        String ancestor = beanConfig.getExtends();        if (ancestor == null) {            // Nothing to do, then            return beanConfig;        }        // Make sure that this bean is of the right class        FormBeanConfig baseConfig = moduleConfig.findFormBeanConfig(ancestor);        if (baseConfig == null) {            throw new UnavailableException("Unable to find " + "form bean '"                + ancestor + "' to extend.");        }        // Was our bean's class overridden already?        if (beanConfig.getClass().equals(FormBeanConfig.class)) {            // Ensure that our bean is using the correct class            if (!baseConfig.getClass().equals(beanConfig.getClass())) {                // Replace the bean with an instance of the correct class                FormBeanConfig newBeanConfig = null;                String baseConfigClassName = baseConfig.getClass().getName();                try {                    newBeanConfig =                        (FormBeanConfig) RequestUtils.applicationInstance(baseConfigClassName);                    // copy the values                    BeanUtils.copyProperties(newBeanConfig, beanConfig);                    FormPropertyConfig[] fpc =                        beanConfig.findFormPropertyConfigs();                    for (int i = 0; i < fpc.length; i++) {                        newBeanConfig.addFormPropertyConfig(fpc[i]);                    }                } catch (Exception e) {                    handleCreationException(baseConfigClassName, e);                }                // replace beanConfig with newBeanConfig                moduleConfig.removeFormBeanConfig(beanConfig);                moduleConfig.addFormBeanConfig(newBeanConfig);                beanConfig = newBeanConfig;            }        }        return beanConfig;    }    /**     * <p>Initialize the forwards for the specified module.</p>     *     * @param config ModuleConfig information for this module     * @throws ServletException if initialization cannot be performed     */    protected void initModuleForwards(ModuleConfig config)        throws ServletException {        if (log.isDebugEnabled()) {            log.debug("Initializing module path '" + config.getPrefix()                + "' forwards");        }        // Process forwards extensions.        ForwardConfig[] forwards = config.findForwardConfigs();        for (int i = 0; i < forwards.length; i++) {            ForwardConfig forward = forwards[i];            processForwardExtension(forward, config, null);        }        for (int i = 0; i < forwards.length; i++) {            ForwardConfig forward = forwards[i];            // Verify that required fields are all present for the forward            if (forward.getPath() == null) {                handleValueRequiredException("path", forward.getName(),                    "global forward");            }        }    }    /**     * <p>Extend the forward's configuration as necessary.  If actionConfig is     * provided, then this method will process the forwardConfig as part     * of that actionConfig.  If actionConfig is null, the forwardConfig     * will be processed as a global forward.</p>     *     * @param forwardConfig the configuration to process.     * @param moduleConfig  the module configuration for this module.     * @param actionConfig  If applicable, the config for the current action.     * @throws ServletException if initialization cannot be performed.     */    protected void processForwardExtension(ForwardConfig forwardConfig,        ModuleConfig moduleConfig, ActionConfig actionConfig)        throws ServletException {        try {            if (!forwardConfig.isExtensionProcessed()) {                if (log.isDebugEnabled()) {                    log.debug("Processing extensions for '"                        + forwardConfig.getName() + "'");                }                forwardConfig =                    processForwardConfigClass(forwardConfig, moduleConfig,                        actionConfig);                forwardConfig.processExtends(moduleConfig, actionConfig);            }        } catch (ServletException e) {            throw e;        } catch (Exception e) {            handleGeneralExtensionException("Forward", forwardConfig.getName(),                e);        }    }    /**     * <p>Checks if the current forwardConfig is using the correct class based     * on the class of its configuration ancestor.  If actionConfig is     * provided, then this method will process the forwardConfig as part     * of that actionConfig.  If actionConfig is null, the forwardConfig     * will be processed as a global forward.</p>     *     * @param forwardConfig The forward to check.     * @param moduleConfig  The config for the current module.     * @param actionConfig  If applicable, the config for the current action.     * @return The forward config using the correct class as determined by the     *         config's ancestor and its own overridden value.     * @throws UnavailableException if an instance of the forward config class     *                              cannot be created.     * @throws ServletException     on class creation error     */    protected ForwardConfig processForwardConfigClass(        ForwardConfig forwardConfig, ModuleConfig moduleConfig,        ActionConfig actionConfig)        throws ServletException {        String ancestor = forwardConfig.getExtends();        if (ancestor == null) {            // Nothing to do, then            return forwardConfig;        }        // Make sure that this config is of the right class        ForwardConfig baseConfig = null;        if (actionConfig != null) {            // Look for this in the actionConfig            baseConfig = actionConfig.findForwardConfig(ancestor);        }        if (baseConfig == null) {            // Either this is a forwardConfig that inherits a global config,            //  or actionConfig is null            baseConfig = moduleConfig.findForwardConfig(ancestor);        }        if (baseConfig == null) {            throw new UnavailableException("Unable to find " + "forward '"                + ancestor + "' to extend.");        }        // Was our forwards's class overridden already?        if (forwardConfig.getClass().equals(ActionForward.class)) {            // Ensure that our forward is using the correct class            if (!baseConfig.getClass().equals(forwardConfig.getClass())) {                // Replace the config with an instance of the correct class                ForwardConfig newForwardConfig = null;                String baseConfigClassName = baseConfig.getClass().getName();                try {                    newForwardConfig =                        (ForwardConfig) RequestUtils.applicationInstance(                                baseConfigClassName);                    // copy the values                    BeanUtils.copyProperties(newForwardConfig, forwardConfig);                } catch (Exception e) {                    handleCreationException(baseConfigClassName, e);                }                // replace forwardConfig with newForwardConfig                if (actionConfig != null) {                    actionConfig.removeForwardConfig(forwardConfig);                    actionConfig.addForwardConfig(newForwardConfig);                } else {                    // this is a global forward                    moduleConfig.removeForwardConfig(forwardConfig);                    moduleConfig.addForwardConfig(newForwardConfig);                }                forwardConfig = newForwardConfig;            }        }        return forwardConfig;    }    /**     * <p>Initialize the exception handlers for the specified module.</p>     *     * @param config ModuleConfig information for this module     * @throws ServletException if initialization cannot be performed     * @since Struts 1.3     */    protected void initModuleExceptionConfigs(ModuleConfig config)        throws ServletException {        if (log.isDebugEnabled()) {            log.debug("Initializing module path '" + config.getPrefix()                + "' forwards");        }        // Process exception config extensions.        ExceptionConfig[] exceptions = config.findExceptionConfigs();        for (int i = 0; i < exceptions.length; i++) {            ExceptionConfig exception = exceptions[i];            processExceptionExtension(exception, config, null);        }        for (int i = 0; i < exceptions.length; i++) {            ExceptionConfig exception = exceptions[i];            // Verify that required fields are all present for the config            if (exception.getKey() == null) {                handleValueRequiredException("key", exception.getType(),                    "global exception config");            }        }    }    /**     * <p>Extend the exception's configuration as necessary. If actionConfig is     * provided, then this method will process the exceptionConfig as part     * of that actionConfig.  If actionConfig is null, the exceptionConfig     * will be processed as a global forward.</p>     *     * @param exceptionConfig the configuration to process.     * @param moduleConfig    the module configuration for this module.     * @param actionConfig  If applicable, the config for the current action.     * @throws ServletException if initialization cannot be performed.     */    protected void processExceptionExtension(ExceptionConfig exceptionConfig,        ModuleConfig moduleConfig, ActionConfig actionConfig)        throws ServletException {        try {            if (!exceptionConfig.isExtensionProcessed()) {                if (log.isDebugEnabled()) {                    log.debug("Processing extensions for '"                        + exceptionConfig.getType() + "'");                }                exceptionConfig =                    processExceptionConfigClass(exceptionConfig, moduleConfig,                        actionConfig);                exceptionConfig.processExtends(moduleConfig, actionConfig);            }        } catch (ServletException e) {            throw e;        } catch (Exception e) {            handleGeneralExtensionException("Exception",                exceptionConfig.getType(), e);        }    }    /**     * <p>Checks if the current exceptionConfig is using the correct class     * based on the class of its configuration ancestor. If actionConfig is     * provided, then this method will process the exceptionConfig as part     * of that actionConfig.  If actionConfig is null, the exceptionConfig     * will be processed as a global forward.</p>     *     * @param exceptionConfig The config to check.     * @param moduleConfig    The config for the current module.     * @param actionConfig  If applicable, the config for the current action.     * @return The exception config using the correct class as determined by     *         the config's ancestor and its own overridden value.     * @throws ServletException if an instance of the exception config class     *                          cannot be created.     */    protected ExceptionConfig processExceptionConfigClass(        ExceptionConfig exceptionConfig, ModuleConfig moduleConfig,        ActionConfig actionConfig)        throws ServletException {        String ancestor = exceptionConfig.getExtends();        if (ancestor == null) {            // Nothing to do, then            return exceptionConfig;        }        // Make sure that this config is of the right class        ExceptionConfig baseConfig = null;        if (actionConfig != null) {            baseConfig = actionConfig.findExceptionConfig(ancestor);        }        if (baseConfig == null) {            // This means either there's no actionConfig anyway, or the            // ancestor is not defined within the action.            baseConfig = moduleConfig.findExceptionConfig(ancestor);        }        if (baseConfig == null) {            throw new UnavailableException("Unable to find "                + "exception config '" + ancestor + "' to extend.");        }        // Was our config's class overridden already?        if (exceptionConfig.getClass().equals(ExceptionConfig.class)) {            // Ensure that our config is using the correct class            if (!baseConfig.getClass().equals(exceptionConfig.getClass())) {                // Replace the config with an instance of the correct class                ExceptionConfig newExceptionConfig = null;                String baseConfigClassName = baseConfig.getClass().getName();                try {                    newExceptionConfig =                        (ExceptionConfig) RequestUtils.applicationInstance(                            baseConfigClassName);                    // copy the values                    BeanUtils.copyProperties(newExceptionConfig,                        exceptionConfig);                } catch (Exception e) {                    handleCreationException(baseConfigClassName, e);                }                // replace exceptionConfig with newExceptionConfig                if (actionConfig != null) {                    actionConfig.removeExceptionConfig(exceptionConfig);                    actionConfig.addExceptionConfig(newExceptionConfig);                } else {                    moduleConfig.removeExceptionConfig(exceptionConfig);                    moduleConfig.addExceptionConfig(newExceptionConfig);                }                exceptionConfig = newExceptionConfig;            }        }        return exceptionConfig;    }    /**     * <p>Initialize the action configs for the specified module.</p>     *     * @param config ModuleConfig information for this module     * @throws ServletException if initialization cannot be performed     * @since Struts 1.3     */    protected void initModuleActions(ModuleConfig config)        throws ServletException {        if (log.isDebugEnabled()) {            log.debug("Initializing module path '" + config.getPrefix()                + "' action configs");        }        // Process ActionConfig extensions.        ActionConfig[] actionConfigs = config.findActionConfigs();        for (int i = 0; i < actionConfigs.length; i++) {            ActionConfig actionConfig = actionConfigs[i];            processActionConfigExtension(actionConfig, config);        }        for (int i = 0; i < actionConfigs.length; i++) {            ActionConfig actionConfig = actionConfigs[i];            // Verify that required fields are all present for the forward            // configs            ForwardConfig[] forwards = actionConfig.findForwardConfigs();            for (int j = 0; j < forwards.length; j++) {                ForwardConfig forward = forwards[j];                if (forward.getPath() == null) {                    handleValueRequiredException("path", forward.getName(),                        "action forward");                }            }            // ... and the exception configs            ExceptionConfig[] exceptions = actionConfig.findExceptionConfigs();            for (int j = 0; j < exceptions.length; j++) {                ExceptionConfig exception = exceptions[j];                if (exception.getKey() == null) {                    handleValueRequiredException("key", exception.getType(),                        "action exception config");                }            }        }    }    /**     * <p>Extend the action's configuration as necessary.</p>     *     * @param actionConfig the configuration to process.     * @param moduleConfig the module configuration for this module.     * @throws ServletException if initialization cannot be performed.     */    protected void processActionConfigExtension(ActionConfig actionConfig,        ModuleConfig moduleConfig)        throws ServletException {        try {            if (!actionConfig.isExtensionProcessed()) {                if (log.isDebugEnabled()) {                    log.debug("Processing extensions for '"                        + actionConfig.getPath() + "'");                }                actionConfig =                    processActionConfigClass(actionConfig, moduleConfig);                actionConfig.processExtends(moduleConfig);            }            // Process forwards extensions.            ForwardConfig[] forwards = actionConfig.findForwardConfigs();            for (int i = 0; i < forwards.length; i++) {                ForwardConfig forward = forwards[i];                processForwardExtension(forward, moduleConfig, actionConfig);            }            // Process exception extensions.            ExceptionConfig[] exceptions = actionConfig.findExceptionConfigs();            for (int i = 0; i < exceptions.length; i++) {                ExceptionConfig exception = exceptions[i];                processExceptionExtension(exception, moduleConfig,                    actionConfig);            }        } catch (ServletException e) {            throw e;        } catch (Exception e) {            handleGeneralExtensionException("Action", actionConfig.getPath(), e);        }    }    /**     * <p>Checks if the current actionConfig is using the correct class based     * on the class of its ancestor ActionConfig.</p>     *     * @param actionConfig The action config to check.     * @param moduleConfig The config for the current module.     * @return The config object using the correct class as determined by the     *         config's ancestor and its own overridden value.     * @throws ServletException if an instance of the action config class     *                          cannot be created.     */    protected ActionConfig processActionConfigClass(ActionConfig actionConfig,        ModuleConfig moduleConfig)        throws ServletException {        String ancestor = actionConfig.getExtends();        if (ancestor == null) {            // Nothing to do, then            return actionConfig;        }        // Make sure that this config is of the right class        ActionConfig baseConfig = moduleConfig.findActionConfig(ancestor);        if (baseConfig == null) {            throw new UnavailableException("Unable to find "                + "action config for '" + ancestor + "' to extend.");        }        // Was our actionConfig's class overridden already?        if (actionConfig.getClass().equals(ActionMapping.class)) {            // Ensure that our config is using the correct class            if (!baseConfig.getClass().equals(actionConfig.getClass())) {                // Replace the config with an instance of the correct class                ActionConfig newActionConfig = null;                String baseConfigClassName = baseConfig.getClass().getName();                try {                    newActionConfig =                        (ActionConfig) RequestUtils.applicationInstance(baseConfigClassName);                    // copy the values                    BeanUtils.copyProperties(newActionConfig, actionConfig);                    // copy the forward and exception configs, too                    ForwardConfig[] forwards =                        actionConfig.findForwardConfigs();                    for (int i = 0; i < forwards.length; i++) {                        newActionConfig.addForwardConfig(forwards[i]);                    }                    ExceptionConfig[] exceptions =                        actionConfig.findExceptionConfigs();                    for (int i = 0; i < exceptions.length; i++) {                        newActionConfig.addExceptionConfig(exceptions[i]);                    }                } catch (Exception e) {                    handleCreationException(baseConfigClassName, e);                }                // replace actionConfig with newActionConfig                moduleConfig.removeActionConfig(actionConfig);                moduleConfig.addActionConfig(newActionConfig);                actionConfig = newActionConfig;            }        }        return actionConfig;    }    /**     * <p>Initialize the application <code>MessageResources</code> for the     * specified module.</p>     *     * @param config ModuleConfig information for this module     * @throws ServletException if initialization cannot be performed     * @since Struts 1.1     */    protected void initModuleMessageResources(ModuleConfig config)        throws ServletException {        MessageResourcesConfig[] mrcs = config.findMessageResourcesConfigs();        for (int i = 0; i < mrcs.length; i++) {            if ((mrcs[i].getFactory() == null)                || (mrcs[i].getParameter() == null)) {                continue;            }            if (log.isDebugEnabled()) {                log.debug("Initializing module path '" + config.getPrefix()                    + "' message resources from '" + mrcs[i].getParameter()                    + "'");            }            String factory = mrcs[i].getFactory();            MessageResourcesFactory.setFactoryClass(factory);            MessageResourcesFactory factoryObject =                MessageResourcesFactory.createFactory();            factoryObject.setConfig(mrcs[i]);            MessageResources resources =                factoryObject.createResources(mrcs[i].getParameter());            resources.setReturnNull(mrcs[i].getNull());            resources.setEscape(mrcs[i].isEscape());            getServletContext().setAttribute(mrcs[i].getKey()                + config.getPrefix(), resources);        }    }    /**     * <p>Create (if needed) and return a new <code>Digester</code> instance     * that has been initialized to process Struts module configuration files     * and configure a corresponding <code>ModuleConfig</code> object (which     * must be pushed on to the evaluation stack before parsing begins).</p>     *     * @return A new configured <code>Digester</code> instance.     * @throws ServletException if a Digester cannot be configured     * @since Struts 1.1     */    protected Digester initConfigDigester()        throws ServletException {        // :FIXME: Where can ServletException be thrown?        // Do we have an existing instance?        if (configDigester != null) {            return (configDigester);        }        // Create a new Digester instance with standard capabilities        configDigester = new Digester();        configDigester.setNamespaceAware(true);        configDigester.setValidating(this.isValidating());        configDigester.setUseContextClassLoader(true);        configDigester.addRuleSet(new ConfigRuleSet());        for (int i = 0; i < registrations.length; i += 2) {            URL url = this.getClass().getResource(registrations[i + 1]);            if (url != null) {                configDigester.register(registrations[i], url.toString());            }        }        this.addRuleSets();        // Return the completely configured Digester instance        return (configDigester);    }    /**     * <p>Add any custom RuleSet instances to configDigester that have been     * specified in the <code>rulesets</code> init parameter.</p>     *     * @throws ServletException if an error occurs     */    private void addRuleSets()        throws ServletException {        String rulesets = getServletConfig().getInitParameter("rulesets");        if (rulesets == null) {            rulesets = "";        }        rulesets = rulesets.trim();        String ruleset;        while (rulesets.length() > 0) {            int comma = rulesets.indexOf(",");            if (comma < 0) {                ruleset = rulesets.trim();                rulesets = "";            } else {                ruleset = rulesets.substring(0, comma).trim();                rulesets = rulesets.substring(comma + 1).trim();            }            if (log.isDebugEnabled()) {                log.debug("Configuring custom Digester Ruleset of type "                    + ruleset);            }            try {                RuleSet instance =                    (RuleSet) RequestUtils.applicationInstance(ruleset);                this.configDigester.addRuleSet(instance);            } catch (Exception e) {                log.error("Exception configuring custom Digester RuleSet", e);                throw new ServletException(e);            }        }    }    /**     * <p>Check the status of the <code>validating</code> initialization     * parameter.</p>     *     * @return true if the module Digester should validate.     */    private boolean isValidating() {        boolean validating = true;        String value = getServletConfig().getInitParameter("validating");        if ("false".equalsIgnoreCase(value) || "no".equalsIgnoreCase(value)            || "n".equalsIgnoreCase(value) || "0".equalsIgnoreCase(value)) {            validating = false;        }        return validating;    }    /**     * <p>Initialize our internal MessageResources bundle.</p>     *     * @throws ServletException     if we cannot initialize these resources     * @throws UnavailableException if we cannot load  resources     */    protected void initInternal()        throws ServletException {        try {            internal = MessageResources.getMessageResources(internalName);        } catch (MissingResourceException e) {            log.error("Cannot load internal resources from '" + internalName                + "'", e);            throw new UnavailableException(                "Cannot load internal resources from '" + internalName + "'");        }    }    /**     * <p>Parse the configuration documents specified by the     * <code>chainConfig</code> init-param to configure the default {@link     * org.apache.commons.chain.Catalog} that is registered in the {@link     * CatalogFactory} instance for this application.</p>     *     * @throws ServletException if an error occurs.     */    protected void initChain()        throws ServletException {        // Parse the configuration file specified by path or resource        try {            String value;            value = getServletConfig().getInitParameter("chainConfig");            if (value != null) {                chainConfig = value;            }            ConfigParser parser = new ConfigParser();            List urls = splitAndResolvePaths(chainConfig);            URL resource;            for (Iterator i = urls.iterator(); i.hasNext();) {                resource = (URL) i.next();                log.info("Loading chain catalog from " + resource);                parser.parse(resource);            }        } catch (Exception e) {            log.error("Exception loading resources", e);            throw new ServletException(e);        }    }    /**     * <p>Initialize other global characteristics of the controller     * servlet.</p>     *     * @throws ServletException if we cannot initialize these resources     */    protected void initOther()        throws ServletException {        String value;        value = getServletConfig().getInitParameter("config");        if (value != null) {            config = value;        }        // Backwards compatibility for form beans of Java wrapper classes        // Set to true for strict Struts 1.0 compatibility        value = getServletConfig().getInitParameter("convertNull");        if ("true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value)            || "on".equalsIgnoreCase(value) || "y".equalsIgnoreCase(value)            || "1".equalsIgnoreCase(value)) {            convertNull = true;        }        if (convertNull) {            ConvertUtils.deregister();            ConvertUtils.register(new BigDecimalConverter(null),                BigDecimal.class);            ConvertUtils.register(new BigIntegerConverter(null),                BigInteger.class);            ConvertUtils.register(new BooleanConverter(null), Boolean.class);            ConvertUtils.register(new ByteConverter(null), Byte.class);            ConvertUtils.register(new CharacterConverter(null), Character.class);            ConvertUtils.register(new DoubleConverter(null), Double.class);            ConvertUtils.register(new FloatConverter(null), Float.class);            ConvertUtils.register(new IntegerConverter(null), Integer.class);            ConvertUtils.register(new LongConverter(null), Long.class);            ConvertUtils.register(new ShortConverter(null), Short.class);        }    }    /**     * <p>Initialize the servlet mapping under whi 

热点排行