/*
 * 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 com.opensymphony.xwork2.config.providers;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.FileManagerFactory;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.BeanSelectionProvider;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.ConfigurationProvider;
import com.opensymphony.xwork2.config.ConfigurationUtil;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
import com.opensymphony.xwork2.config.entities.InterceptorConfig;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
import com.opensymphony.xwork2.config.entities.UnknownHandlerConfig;
import com.opensymphony.xwork2.config.impl.LocatableFactory;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.inject.Scope;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.ClassPathFinder;
import com.opensymphony.xwork2.util.DomHelper;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import com.opensymphony.xwork2.util.location.Location;
import com.opensymphony.xwork2.util.location.LocationUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;


/**
 * Looks in the classpath for an XML file, "xwork.xml" by default,
 * and uses it for the XWork configuration.
 *
 * @author tmjee
 * @author Rainer Hermanns
 * @author Neo
 * @version $Revision$
 */
public class XmlConfigurationProvider implements ConfigurationProvider {

    private static final Logger LOG = LogManager.getLogger(XmlConfigurationProvider.class);

    private List<Document> documents;
    private Set<String> includedFileNames;
    private String configFileName;
    private ObjectFactory objectFactory;

    private final Set<String> loadedFileUrls = new HashSet<>();
    private boolean errorIfMissing;
    private Map<String, String> dtdMappings;
    private Configuration configuration;
    private boolean throwExceptionOnDuplicateBeans = true;
    private final Map<String, Element> declaredPackages = new HashMap<>();

    private FileManager fileManager;
    private ValueSubstitutor valueSubstitutor;

    public XmlConfigurationProvider() {
        this("xwork.xml", true);
    }

    public XmlConfigurationProvider(String filename) {
        this(filename, true);
    }

    public XmlConfigurationProvider(String filename, boolean errorIfMissing) {
        this.configFileName = filename;
        this.errorIfMissing = errorIfMissing;

        Map<String, String> mappings = new HashMap<>();
        mappings.put("-//Apache Struts//XWork 2.6//EN", "xwork-2.6.dtd");
        mappings.put("-//Apache Struts//XWork 2.5//EN", "xwork-2.5.dtd");
        mappings.put("-//Apache Struts//XWork 2.3//EN", "xwork-2.3.dtd");
        mappings.put("-//Apache Struts//XWork 2.1.3//EN", "xwork-2.1.3.dtd");
        mappings.put("-//Apache Struts//XWork 2.1//EN", "xwork-2.1.dtd");
        mappings.put("-//Apache Struts//XWork 2.0//EN", "xwork-2.0.dtd");
        mappings.put("-//Apache Struts//XWork 1.1.1//EN", "xwork-1.1.1.dtd");
        mappings.put("-//Apache Struts//XWork 1.1//EN", "xwork-1.1.dtd");
        mappings.put("-//Apache Struts//XWork 1.0//EN", "xwork-1.0.dtd");
        setDtdMappings(mappings);
    }

    public void setThrowExceptionOnDuplicateBeans(boolean val) {
        this.throwExceptionOnDuplicateBeans = val;
    }

    public void setDtdMappings(Map<String, String> mappings) {
        this.dtdMappings = Collections.unmodifiableMap(mappings);
    }

    @Inject
    public void setObjectFactory(ObjectFactory objectFactory) {
        this.objectFactory = objectFactory;
    }

    @Inject
    public void setFileManagerFactory(FileManagerFactory fileManagerFactory) {
        this.fileManager = fileManagerFactory.getFileManager();
    }

    @Inject(required = false)
    public void setValueSubstitutor(ValueSubstitutor valueSubstitutor) {
        this.valueSubstitutor = valueSubstitutor;
    }

    /**
     * Returns an unmodifiable map of DTD mappings
     *
     * @return map of DTD mappings
     */
    public Map<String, String> getDtdMappings() {
        return dtdMappings;
    }

    public void init(Configuration configuration) {
        this.configuration = configuration;
        this.includedFileNames = configuration.getLoadedFileNames();
        loadDocuments(configFileName);
    }

    public void destroy() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof XmlConfigurationProvider)) {
            return false;
        }

        final XmlConfigurationProvider xmlConfigurationProvider = (XmlConfigurationProvider) o;

        if ((configFileName != null) ? (!configFileName.equals(xmlConfigurationProvider.configFileName)) : (xmlConfigurationProvider.configFileName != null)) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        return ((configFileName != null) ? configFileName.hashCode() : 0);
    }

    private void loadDocuments(String configFileName) {
        try {
            loadedFileUrls.clear();
            documents = loadConfigurationFiles(configFileName, null);
        } catch (ConfigurationException e) {
            throw e;
        } catch (Exception e) {
            throw new ConfigurationException("Error loading configuration file " + configFileName, e);
        }
    }

    public void register(ContainerBuilder containerBuilder, LocatableProperties props) throws ConfigurationException {
        LOG.trace("Parsing configuration file [{}]", configFileName);
        Map<String, Node> loadedBeans = new HashMap<>();
        for (Document doc : documents) {
            Element rootElement = doc.getDocumentElement();
            NodeList children = rootElement.getChildNodes();
            int childSize = children.getLength();

            for (int i = 0; i < childSize; i++) {
                Node childNode = children.item(i);

                if (childNode instanceof Element) {
                    Element child = (Element) childNode;

                    final String nodeName = child.getNodeName();

                    if ("bean-provider".equals(nodeName)) {
                        String name = child.getAttribute("name");
                        String impl = child.getAttribute("class");
                        try {
                            Class classImpl = ClassLoaderUtil.loadClass(impl, getClass());
                            if (BeanSelectionProvider.class.isAssignableFrom(classImpl)) {
                                BeanSelectionProvider provider = (BeanSelectionProvider) classImpl.newInstance();
                                provider.register(containerBuilder, props);
                            } else {
                                throw new ConfigurationException("The bean-provider: name:" + name + " class:" + impl + " does not implement " + BeanSelectionProvider.class.getName(), childNode);
                            }
                        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
                            throw new ConfigurationException("Unable to load bean-provider: name:" + name + " class:" + impl, e, childNode);
                        }
                    } else if ("bean".equals(nodeName)) {
                        String type = child.getAttribute("type");
                        String name = child.getAttribute("name");
                        String impl = child.getAttribute("class");
                        String onlyStatic = child.getAttribute("static");
                        String scopeStr = child.getAttribute("scope");
                        boolean optional = "true".equals(child.getAttribute("optional"));
                        Scope scope = Scope.SINGLETON;
                        if ("prototype".equals(scopeStr)) {
                            scope = Scope.PROTOTYPE;
                        } else if ("request".equals(scopeStr)) {
                            scope = Scope.REQUEST;
                        } else if ("session".equals(scopeStr)) {
                            scope = Scope.SESSION;
                        } else if ("thread".equals(scopeStr)) {
                            scope = Scope.THREAD;
                        }

                        if (StringUtils.isEmpty(name)) {
                            name = Container.DEFAULT_NAME;
                        }

                        try {
                            Class classImpl = ClassLoaderUtil.loadClass(impl, getClass());
                            Class classType = classImpl;
                            if (StringUtils.isNotEmpty(type)) {
                                classType = ClassLoaderUtil.loadClass(type, getClass());
                            }
                            if ("true".equals(onlyStatic)) {
                                // Force loading of class to detect no class def found exceptions
                                classImpl.getDeclaredClasses();
                                containerBuilder.injectStatics(classImpl);
                            } else {
                                if (containerBuilder.contains(classType, name)) {
                                    Location loc = LocationUtils.getLocation(loadedBeans.get(classType.getName() + name));
                                    if (throwExceptionOnDuplicateBeans) {
                                        throw new ConfigurationException("Bean type " + classType + " with the name " +
                                                name + " has already been loaded by " + loc, child);
                                    }
                                }

                                // Force loading of class to detect no class def found exceptions
                                classImpl.getDeclaredConstructors();

                                LOG.debug("Loaded type: {} name: {} impl: {}", type, name, impl);
                                containerBuilder.factory(classType, name, new LocatableFactory(name, classType, classImpl, scope, childNode), scope);
                            }
                            loadedBeans.put(classType.getName() + name, child);
                        } catch (Throwable ex) {
                            if (!optional) {
                                throw new ConfigurationException("Unable to load bean: type:" + type + " class:" + impl, ex, childNode);
                            } else {
                                LOG.debug("Unable to load optional class: {}", impl);
                            }
                        }
                    } else if ("constant".equals(nodeName)) {
                        String name = child.getAttribute("name");
                        String value = child.getAttribute("value");

                        if (valueSubstitutor != null) {
                            LOG.debug("Substituting value [{}] using [{}]", value, valueSubstitutor.getClass().getName());
                            value = valueSubstitutor.substitute(value);
                        }

                        props.setProperty(name, value, childNode);
                    } else if (nodeName.equals("unknown-handler-stack")) {
                        List<UnknownHandlerConfig> unknownHandlerStack = new ArrayList<UnknownHandlerConfig>();
                        NodeList unknownHandlers = child.getElementsByTagName("unknown-handler-ref");
                        int unknownHandlersSize = unknownHandlers.getLength();

                        for (int k = 0; k < unknownHandlersSize; k++) {
                            Element unknownHandler = (Element) unknownHandlers.item(k);
                            Location location = LocationUtils.getLocation(unknownHandler);
                            unknownHandlerStack.add(new UnknownHandlerConfig(unknownHandler.getAttribute("name"), location));
                        }

                        if (!unknownHandlerStack.isEmpty())
                            configuration.setUnknownHandlerStack(unknownHandlerStack);
                    }
                }
            }
        }
    }

    public void loadPackages() throws ConfigurationException {
        List<Element> reloads = new ArrayList<Element>();
        verifyPackageStructure();

        for (Document doc : documents) {
            Element rootElement = doc.getDocumentElement();
            NodeList children = rootElement.getChildNodes();
            int childSize = children.getLength();

            for (int i = 0; i < childSize; i++) {
                Node childNode = children.item(i);

                if (childNode instanceof Element) {
                    Element child = (Element) childNode;

                    final String nodeName = child.getNodeName();

                    if ("package".equals(nodeName)) {
                        PackageConfig cfg = addPackage(child);
                        if (cfg.isNeedsRefresh()) {
                            reloads.add(child);
                        }
                    }
                }
            }
            loadExtraConfiguration(doc);
        }

        if (reloads.size() > 0) {
            reloadRequiredPackages(reloads);
        }

        for (Document doc : documents) {
            loadExtraConfiguration(doc);
        }

        documents.clear();
        declaredPackages.clear();
        configuration = null;
    }

    private void verifyPackageStructure() {
        DirectedGraph<String> graph = new DirectedGraph<>();

        for (Document doc : documents) {
            Element rootElement = doc.getDocumentElement();
            NodeList children = rootElement.getChildNodes();
            int childSize = children.getLength();
            for (int i = 0; i < childSize; i++) {
                Node childNode = children.item(i);
                if (childNode instanceof Element) {
                    Element child = (Element) childNode;

                    final String nodeName = child.getNodeName();

                    if ("package".equals(nodeName)) {
                        String packageName = child.getAttribute("name");
                        declaredPackages.put(packageName, child);
                        graph.addNode(packageName);

                        String extendsAttribute = child.getAttribute("extends");
                        List<String> parents = ConfigurationUtil.buildParentListFromString(extendsAttribute);
                        for (String parent : parents) {
                            graph.addNode(parent);
                            graph.addEdge(packageName, parent);
                        }
                    }
                }
            }
        }

        CycleDetector<String> detector = new CycleDetector<>(graph);
        if (detector.containsCycle()) {
            StringBuilder builder = new StringBuilder("The following packages participate in cycles:");
            for (String packageName : detector.getVerticesInCycles()) {
                builder.append(" ");
                builder.append(packageName);
            }
            throw new ConfigurationException(builder.toString());
        }
    }

    private void reloadRequiredPackages(List<Element> reloads) {
        if (reloads.size() > 0) {
            List<Element> result = new ArrayList<>();
            for (Element pkg : reloads) {
                PackageConfig cfg = addPackage(pkg);
                if (cfg.isNeedsRefresh()) {
                    result.add(pkg);
                }
            }
            if ((result.size() > 0) && (result.size() != reloads.size())) {
                reloadRequiredPackages(result);
                return;
            }

            // Print out error messages for all misconfigured inheritance packages
            if (result.size() > 0) {
                for (Element rp : result) {
                    String parent = rp.getAttribute("extends");
                    if (parent != null) {
                        List<PackageConfig> parents = ConfigurationUtil.buildParentsFromString(configuration, parent);
                        if (parents != null && parents.size() <= 0) {
                            LOG.error("Unable to find parent packages {}", parent);
                        }
                    }
                }
            }
        }
    }

    /**
     * Tells whether the ConfigurationProvider should reload its configuration. This method should only be called
     * if ConfigurationManager.isReloadingConfigs() is true.
     *
     * @return true if the file has been changed since the last time we read it
     */
    public boolean needsReload() {

        for (String url : loadedFileUrls) {
            if (fileManager.fileNeedsReloading(url)) {
                return true;
            }
        }
        return false;
    }

    protected void addAction(Element actionElement, PackageConfig.Builder packageContext) throws ConfigurationException {
        String name = actionElement.getAttribute("name");
        String className = actionElement.getAttribute("class");
        //methodName should be null if it's not set
        String methodName = StringUtils.trimToNull(actionElement.getAttribute("method"));
        Location location = DomHelper.getLocationObject(actionElement);

        if (location == null) {
            LOG.warn("Location null for {}", className);
        }

        // if there isn't a class name specified for an <action/> then try to
        // use the default-class-ref from the <package/>
        if (StringUtils.isEmpty(className)) {
            // if there is a package default-class-ref use that, otherwise use action support
           /* if (StringUtils.isNotEmpty(packageContext.getDefaultClassRef())) {
                className = packageContext.getDefaultClassRef();
            } else {
                className = ActionSupport.class.getName();
            }*/

        } else {
            if (!verifyAction(className, name, location)) {
                LOG.error("Unable to verify action [{}] with class [{}], from [{}]", name, className, location);
                return;
            }
        }

        Map<String, ResultConfig> results;
        try {
            results = buildResults(actionElement, packageContext);
        } catch (ConfigurationException e) {
            throw new ConfigurationException("Error building results for action " + name + " in namespace " + packageContext.getNamespace(), e, actionElement);
        }

        List<InterceptorMapping> interceptorList = buildInterceptorList(actionElement, packageContext);

        List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(actionElement, packageContext);

        Set<String> allowedMethods = buildAllowedMethods(actionElement, packageContext);

        ActionConfig actionConfig = new ActionConfig.Builder(packageContext.getName(), name, className)
                .methodName(methodName)
                .addResultConfigs(results)
                .addInterceptors(interceptorList)
                .addExceptionMappings(exceptionMappings)
                .addParams(XmlHelper.getParams(actionElement))
                .setStrictMethodInvocation(packageContext.isStrictMethodInvocation())
                .addAllowedMethod(allowedMethods)
                .location(location)
                .build();
        packageContext.addActionConfig(name, actionConfig);

        LOG.debug("Loaded {}{} in '{}' package: {}",
                StringUtils.isNotEmpty(packageContext.getNamespace()) ? (packageContext.getNamespace() + "/") : "",
                name, packageContext.getName(), actionConfig);
    }

    protected boolean verifyAction(String className, String name, Location loc) {
        if (className.contains("{")) {
            LOG.debug("Action class [{}] contains a wildcard replacement value, so it can't be verified", className);
            return true;
        }
        try {
            if (objectFactory.isNoArgConstructorRequired()) {
                Class clazz = objectFactory.getClassInstance(className);
                if (!Modifier.isPublic(clazz.getModifiers())) {
                    throw new ConfigurationException("Action class [" + className + "] is not public", loc);
                }
                clazz.getConstructor(new Class[]{});
            }
        } catch (ClassNotFoundException e) {
            LOG.debug("Class not found for action [{}]", className, e);
            throw new ConfigurationException("Action class [" + className + "] not found", loc);
        } catch (NoSuchMethodException e) {
            LOG.debug("No constructor found for action [{}]", className, e);
            throw new ConfigurationException("Action class [" + className + "] does not have a public no-arg constructor", e, loc);
        } catch (RuntimeException ex) {
            // Probably not a big deal, like request or session-scoped Spring beans that need a real request
            LOG.info("Unable to verify action class [{}] exists at initialization", className);
            LOG.debug("Action verification cause", ex);
        } catch (Exception ex) {
            // Default to failing fast
            LOG.debug("Unable to verify action class [{}]", className, ex);
            throw new ConfigurationException(ex, loc);
        }
        return true;
    }

    /**
     * Create a PackageConfig from an XML element representing it.
     *
     * @param packageElement the given XML element
     * @return the package config
     * @throws ConfigurationException in case of configuration errors
     */
    protected PackageConfig addPackage(Element packageElement) throws ConfigurationException {
        String packageName = packageElement.getAttribute("name");
        PackageConfig packageConfig = configuration.getPackageConfig(packageName);
        if (packageConfig != null) {
            LOG.debug("Package [{}] already loaded, skipping re-loading it and using existing PackageConfig [{}]", packageName, packageConfig);
            return packageConfig;
        }

        PackageConfig.Builder newPackage = buildPackageContext(packageElement);

        if (newPackage.isNeedsRefresh()) {
            return newPackage.build();
        }

        LOG.debug("Loaded {}", newPackage);

        // add result types (and default result) to this package
        addResultTypes(newPackage, packageElement);

        // load the interceptors and interceptor stacks for this package
        loadInterceptors(newPackage, packageElement);

        // load the default interceptor reference for this package
        loadDefaultInterceptorRef(newPackage, packageElement);

        // load the default class ref for this package
        loadDefaultClassRef(newPackage, packageElement);

        // load the global result list for this package
        loadGlobalResults(newPackage, packageElement);

        loadGlobalAllowedMethods(newPackage, packageElement);

        // load the global exception handler list for this package
        loadGlobalExceptionMappings(newPackage, packageElement);

        // get actions
        NodeList actionList = packageElement.getElementsByTagName("action");

        for (int i = 0; i < actionList.getLength(); i++) {
            Element actionElement = (Element) actionList.item(i);
            addAction(actionElement, newPackage);
        }

        // load the default action reference for this package
        loadDefaultActionRef(newPackage, packageElement);

        PackageConfig cfg = newPackage.build();
        configuration.addPackageConfig(cfg.getName(), cfg);
        return cfg;
    }

    protected void addResultTypes(PackageConfig.Builder packageContext, Element element) {
        NodeList resultTypeList = element.getElementsByTagName("result-type");

        for (int i = 0; i < resultTypeList.getLength(); i++) {
            Element resultTypeElement = (Element) resultTypeList.item(i);
            String name = resultTypeElement.getAttribute("name");
            String className = resultTypeElement.getAttribute("class");
            String def = resultTypeElement.getAttribute("default");

            Location loc = DomHelper.getLocationObject(resultTypeElement);

            Class clazz = verifyResultType(className, loc);
            if (clazz != null) {
                String paramName = null;
                try {
                    paramName = (String) clazz.getField("DEFAULT_PARAM").get(null);
                } catch (Throwable t) {
                    LOG.debug("The result type [{}] doesn't have a default param [DEFAULT_PARAM] defined!", className, t);
                }
                ResultTypeConfig.Builder resultType = new ResultTypeConfig.Builder(name, className).defaultResultParam(paramName)
                        .location(DomHelper.getLocationObject(resultTypeElement));

                Map<String, String> params = XmlHelper.getParams(resultTypeElement);

                if (!params.isEmpty()) {
                    resultType.addParams(params);
                }
                packageContext.addResultTypeConfig(resultType.build());

                // set the default result type
                if (BooleanUtils.toBoolean(def)) {
                    packageContext.defaultResultType(name);
                }
            }
        }
    }

    protected Class verifyResultType(String className, Location loc) {
        try {
            return objectFactory.getClassInstance(className);
        } catch (ClassNotFoundException | NoClassDefFoundError e) {
            LOG.warn("Result class [{}] doesn't exist ({}) at {}, ignoring", className, e.getClass().getSimpleName(), loc, e);
        }

        return null;
    }

    protected List<InterceptorMapping> buildInterceptorList(Element element, PackageConfig.Builder context) throws ConfigurationException {
        List<InterceptorMapping> interceptorList = new ArrayList<>();
        NodeList interceptorRefList = element.getElementsByTagName("interceptor-ref");

        for (int i = 0; i < interceptorRefList.getLength(); i++) {
            Element interceptorRefElement = (Element) interceptorRefList.item(i);

            if (interceptorRefElement.getParentNode().equals(element) || interceptorRefElement.getParentNode().getNodeName().equals(element.getNodeName())) {
                List<InterceptorMapping> interceptors = lookupInterceptorReference(context, interceptorRefElement);
                interceptorList.addAll(interceptors);
            }
        }

        return interceptorList;
    }

    /**
     * <p>
     * This method builds a package context by looking for the parents of this new package.
     * </p>
     *
     * <p>
     * If no parents are found, it will return a root package.
     * </p>
     *
     * @param packageElement the package element
     *
     * @return the package config builder
     */
    protected PackageConfig.Builder buildPackageContext(Element packageElement) {
        String parent = packageElement.getAttribute("extends");
        String abstractVal = packageElement.getAttribute("abstract");
        boolean isAbstract = Boolean.parseBoolean(abstractVal);
        String name = StringUtils.defaultString(packageElement.getAttribute("name"));
        String namespace = StringUtils.defaultString(packageElement.getAttribute("namespace"));

        // Strict DMI is enabled by default, it can disabled by user
        boolean strictDMI = true;
        if (packageElement.hasAttribute("strict-method-invocation")) {
            strictDMI = Boolean.parseBoolean(packageElement.getAttribute("strict-method-invocation"));
        }

        PackageConfig.Builder cfg = new PackageConfig.Builder(name)
                .namespace(namespace)
                .isAbstract(isAbstract)
                .strictMethodInvocation(strictDMI)
                .location(DomHelper.getLocationObject(packageElement));

        if (StringUtils.isNotEmpty(StringUtils.defaultString(parent))) { // has parents, let's look it up
            List<PackageConfig> parents = new ArrayList<>();
            for (String parentPackageName : ConfigurationUtil.buildParentListFromString(parent)) {
                if (configuration.getPackageConfigNames().contains(parentPackageName)) {
                    parents.add(configuration.getPackageConfig(parentPackageName));
                } else if (declaredPackages.containsKey(parentPackageName)) {
                    if (configuration.getPackageConfig(parentPackageName) == null) {
                        addPackage(declaredPackages.get(parentPackageName));
                    }
                    parents.add(configuration.getPackageConfig(parentPackageName));
                } else {
                    throw new ConfigurationException("Parent package is not defined: " + parentPackageName);
                }

            }

            if (parents.size() <= 0) {
                cfg.needsRefresh(true);
            } else {
                cfg.addParents(parents);
            }
        }

        return cfg;
    }

    /**
     * Build a map of ResultConfig objects from below a given XML element.
     *
     * @param element the given XML element
     * @param packageContext the package context
     *
     * @return map of result config objects
     */
    protected Map<String, ResultConfig> buildResults(Element element, PackageConfig.Builder packageContext) {
        NodeList resultEls = element.getElementsByTagName("result");

        Map<String, ResultConfig> results = new LinkedHashMap<>();

        for (int i = 0; i < resultEls.getLength(); i++) {
            Element resultElement = (Element) resultEls.item(i);

            if (resultElement.getParentNode().equals(element) || resultElement.getParentNode().getNodeName().equals(element.getNodeName())) {
                String resultName = resultElement.getAttribute("name");
                String resultType = resultElement.getAttribute("type");

                // if you don't specify a name on <result/>, it defaults to "success"
                if (StringUtils.isEmpty(resultName)) {
                    resultName = Action.SUCCESS;
                }

                // there is no result type, so let's inherit from the parent package
                if (StringUtils.isEmpty(resultType)) {
                    resultType = packageContext.getFullDefaultResultType();

                    // now check if there is a result type now
                    if (StringUtils.isEmpty(resultType)) {
                        // uh-oh, we have a problem
                        throw new ConfigurationException("No result type specified for result named '"
                                + resultName + "', perhaps the parent package does not specify the result type?", resultElement);
                    }
                }


                ResultTypeConfig config = packageContext.getResultType(resultType);

                if (config == null) {
                    throw new ConfigurationException("There is no result type defined for type '" + resultType
                            + "' mapped with name '" + resultName + "'."
                            + "  Did you mean '" + guessResultType(resultType) + "'?", resultElement);
                }

                String resultClass = config.getClassName();

                // invalid result type specified in result definition
                if (resultClass == null) {
                    throw new ConfigurationException("Result type '" + resultType + "' is invalid");
                }

                Map<String, String> resultParams = XmlHelper.getParams(resultElement);

                if (resultParams.size() == 0) // maybe we just have a body - therefore a default parameter
                {
                    // if <result ...>something</result> then we add a parameter of 'something' as this is the most used result param
                    if (resultElement.getChildNodes().getLength() >= 1) {
                        resultParams = new LinkedHashMap<>();

                        String paramName = config.getDefaultResultParam();
                        if (paramName != null) {
                            StringBuilder paramValue = new StringBuilder();
                            for (int j = 0; j < resultElement.getChildNodes().getLength(); j++) {
                                if (resultElement.getChildNodes().item(j).getNodeType() == Node.TEXT_NODE) {
                                    String val = resultElement.getChildNodes().item(j).getNodeValue();
                                    if (val != null) {
                                        paramValue.append(val);
                                    }
                                }
                            }
                            String val = paramValue.toString().trim();
                            if (val.length() > 0) {
                                resultParams.put(paramName, val);
                            }
                        } else {
                            LOG.debug("No default parameter defined for result [{}] of type [{}] ", config.getName(), config.getClassName());
                        }
                    }
                }

                // create new param map, so that the result param can override the config param
                Map<String, String> params = new LinkedHashMap<String, String>();
                Map<String, String> configParams = config.getParams();
                if (configParams != null) {
                    params.putAll(configParams);
                }
                params.putAll(resultParams);

                Set<String> resultNamesSet = TextParseUtil.commaDelimitedStringToSet(resultName);
                if (resultNamesSet.isEmpty()) {
                    resultNamesSet.add(resultName);
                }

                for (String name : resultNamesSet) {
                    ResultConfig resultConfig = new ResultConfig.Builder(name, resultClass)
                            .addParams(params)
                            .location(DomHelper.getLocationObject(element))
                            .build();
                    results.put(resultConfig.getName(), resultConfig);
                }
            }
        }

        return results;
    }

    protected String guessResultType(String type) {
        StringBuilder sb = null;
        if (type != null) {
            sb = new StringBuilder();
            boolean capNext = false;
            for (int x=0; x<type.length(); x++) {
                char c = type.charAt(x);
                if (c == '-') {
                    capNext = true;
                    continue;
                } else if (Character.isLowerCase(c) && capNext) {
                    c = Character.toUpperCase(c);
                    capNext = false;
                }
                sb.append(c);
            }
        }
        return (sb != null ? sb.toString() : null);
    }

    /**
     * Build a list of exception mapping objects from below a given XML element.
     *
     * @param element the given XML element
     * @param packageContext the package context
     *
     * @return list of exception mapping config objects
     */
    protected List<ExceptionMappingConfig> buildExceptionMappings(Element element, PackageConfig.Builder packageContext) {
        NodeList exceptionMappingEls = element.getElementsByTagName("exception-mapping");

        List<ExceptionMappingConfig> exceptionMappings = new ArrayList<>();

        for (int i = 0; i < exceptionMappingEls.getLength(); i++) {
            Element ehElement = (Element) exceptionMappingEls.item(i);

            if (ehElement.getParentNode().equals(element) || ehElement.getParentNode().getNodeName().equals(element.getNodeName())) {
                String emName = ehElement.getAttribute("name");
                String exceptionClassName = ehElement.getAttribute("exception");
                String exceptionResult = ehElement.getAttribute("result");

                Map<String, String> params = XmlHelper.getParams(ehElement);

                if (StringUtils.isEmpty(emName)) {
                    emName = exceptionResult;
                }

                ExceptionMappingConfig ehConfig = new ExceptionMappingConfig.Builder(emName, exceptionClassName, exceptionResult)
                        .addParams(params)
                        .location(DomHelper.getLocationObject(ehElement))
                        .build();
                exceptionMappings.add(ehConfig);
            }
        }

        return exceptionMappings;
    }

    protected Set<String> buildAllowedMethods(Element element, PackageConfig.Builder packageContext) {
        NodeList allowedMethodsEls = element.getElementsByTagName("allowed-methods");

        Set<String> allowedMethods;
        if (allowedMethodsEls.getLength() > 0) {
            // user defined 'allowed-methods' so used them whatever Strict DMI was enabled or not
            allowedMethods = new HashSet<>(packageContext.getGlobalAllowedMethods());
            // Fix for WW-5029 (concatenate all possible text node children)
            final Node allowedMethodsNode = allowedMethodsEls.item(0);
            if (allowedMethodsNode != null) {
                final NodeList allowedMethodsChildren = allowedMethodsNode.getChildNodes();
                final StringBuilder allowedMethodsSB = new StringBuilder();
                for (int i = 0; i < allowedMethodsChildren.getLength(); i++) {
                    Node allowedMethodsChildNode = allowedMethodsChildren.item(i);
                    if (allowedMethodsChildNode != null && allowedMethodsChildNode.getNodeType() == Node.TEXT_NODE) {
                        String childNodeValue = allowedMethodsChildNode.getNodeValue();
                        childNodeValue = (childNodeValue != null ? childNodeValue.trim() : "");
                        if (childNodeValue.length() > 0) {
                            allowedMethodsSB.append(childNodeValue);
                        }
                    }
                }
                if (allowedMethodsSB.length() > 0) {
                    allowedMethods.addAll(TextParseUtil.commaDelimitedStringToSet(allowedMethodsSB.toString()));
                }
            }
        } else if (packageContext.isStrictMethodInvocation()) {
            // user enabled Strict DMI but didn't defined action specific 'allowed-methods' so we use 'global-allowed-methods' only
            allowedMethods = new HashSet<>(packageContext.getGlobalAllowedMethods());
        } else {
            // Strict DMI is disabled so any method can be called
            allowedMethods = new HashSet<>();
            allowedMethods.add(ActionConfig.WILDCARD);
        }

        LOG.debug("Collected allowed methods: {}", allowedMethods);

        return Collections.unmodifiableSet(allowedMethods);
    }

    protected void loadDefaultInterceptorRef(PackageConfig.Builder packageContext, Element element) {
        NodeList resultTypeList = element.getElementsByTagName("default-interceptor-ref");

        if (resultTypeList.getLength() > 0) {
            Element defaultRefElement = (Element) resultTypeList.item(0);
            packageContext.defaultInterceptorRef(defaultRefElement.getAttribute("name"));
        }
    }

    protected void loadDefaultActionRef(PackageConfig.Builder packageContext, Element element) {
        NodeList resultTypeList = element.getElementsByTagName("default-action-ref");

        if (resultTypeList.getLength() > 0) {
            Element defaultRefElement = (Element) resultTypeList.item(0);
            packageContext.defaultActionRef(defaultRefElement.getAttribute("name"));
        }
    }

    /**
     * Load all of the global results for this package from the XML element.
     *
     * @param packageContext the package context
     * @param packageElement the given XML element
     */
    protected void loadGlobalResults(PackageConfig.Builder packageContext, Element packageElement) {
        NodeList globalResultList = packageElement.getElementsByTagName("global-results");

        if (globalResultList.getLength() > 0) {
            Element globalResultElement = (Element) globalResultList.item(0);
            Map<String, ResultConfig> results = buildResults(globalResultElement, packageContext);
            packageContext.addGlobalResultConfigs(results);
        }
    }

    protected void loadGlobalAllowedMethods(PackageConfig.Builder packageContext, Element packageElement) {
        NodeList globalAllowedMethodsElms = packageElement.getElementsByTagName("global-allowed-methods");

        if (globalAllowedMethodsElms.getLength() > 0) {
            Set<String> globalAllowedMethods = new HashSet<>();
            // Fix for WW-5029 (concatenate all possible text node children)
            Node globaAllowedMethodsNode = globalAllowedMethodsElms.item(0);
            if (globaAllowedMethodsNode != null) {
                NodeList globaAllowedMethodsChildren = globaAllowedMethodsNode.getChildNodes();
                final StringBuilder globalAllowedMethodsSB = new StringBuilder();
                for (int i = 0; i < globaAllowedMethodsChildren.getLength(); i++) {
                    Node globalAllowedMethodsChildNode = globaAllowedMethodsChildren.item(i);
                    if (globalAllowedMethodsChildNode != null && globalAllowedMethodsChildNode.getNodeType() == Node.TEXT_NODE) {
                        String childNodeValue = globalAllowedMethodsChildNode.getNodeValue();
                        childNodeValue = (childNodeValue != null ? childNodeValue.trim() : "");
                        if (childNodeValue.length() > 0) {
                            globalAllowedMethodsSB.append(childNodeValue);
                        }
                    }
                }
                if (globalAllowedMethodsSB.length() > 0) {
                    globalAllowedMethods.addAll(TextParseUtil.commaDelimitedStringToSet(globalAllowedMethodsSB.toString()));
                }
            }
            packageContext.addGlobalAllowedMethods(globalAllowedMethods);
        }
    }

    protected void loadDefaultClassRef(PackageConfig.Builder packageContext, Element element) {
        NodeList defaultClassRefList = element.getElementsByTagName("default-class-ref");
        if (defaultClassRefList.getLength() > 0) {
            Element defaultClassRefElement = (Element) defaultClassRefList.item(0);
            packageContext.defaultClassRef(defaultClassRefElement.getAttribute("class"));
        }
    }

    /**
     * Load all of the global results for this package from the XML element.
     *
     * @param packageContext the package context
     * @param packageElement the given XML element
     */
    protected void loadGlobalExceptionMappings(PackageConfig.Builder packageContext, Element packageElement) {
        NodeList globalExceptionMappingList = packageElement.getElementsByTagName("global-exception-mappings");

        if (globalExceptionMappingList.getLength() > 0) {
            Element globalExceptionMappingElement = (Element) globalExceptionMappingList.item(0);
            List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(globalExceptionMappingElement, packageContext);
            packageContext.addGlobalExceptionMappingConfigs(exceptionMappings);
        }
    }

    protected InterceptorStackConfig loadInterceptorStack(Element element, PackageConfig.Builder context) throws ConfigurationException {
        String name = element.getAttribute("name");

        InterceptorStackConfig.Builder config = new InterceptorStackConfig.Builder(name)
                .location(DomHelper.getLocationObject(element));
        NodeList interceptorRefList = element.getElementsByTagName("interceptor-ref");

        for (int j = 0; j < interceptorRefList.getLength(); j++) {
            Element interceptorRefElement = (Element) interceptorRefList.item(j);
            List<InterceptorMapping> interceptors = lookupInterceptorReference(context, interceptorRefElement);
            config.addInterceptors(interceptors);
        }

        return config.build();
    }

    protected void loadInterceptorStacks(Element element, PackageConfig.Builder context) throws ConfigurationException {
        NodeList interceptorStackList = element.getElementsByTagName("interceptor-stack");

        for (int i = 0; i < interceptorStackList.getLength(); i++) {
            Element interceptorStackElement = (Element) interceptorStackList.item(i);

            InterceptorStackConfig config = loadInterceptorStack(interceptorStackElement, context);

            context.addInterceptorStackConfig(config);
        }
    }

    protected void loadInterceptors(PackageConfig.Builder context, Element element) throws ConfigurationException {
        NodeList interceptorList = element.getElementsByTagName("interceptor");

        for (int i = 0; i < interceptorList.getLength(); i++) {
            Element interceptorElement = (Element) interceptorList.item(i);
            String name = interceptorElement.getAttribute("name");
            String className = interceptorElement.getAttribute("class");

            Map<String, String> params = XmlHelper.getParams(interceptorElement);
            InterceptorConfig config = new InterceptorConfig.Builder(name, className)
                    .addParams(params)
                    .location(DomHelper.getLocationObject(interceptorElement))
                    .build();

            context.addInterceptorConfig(config);
        }

        loadInterceptorStacks(element, context);
    }

    private List<Document> loadConfigurationFiles(String fileName, Element includeElement) {
        List<Document> docs = new ArrayList<>();
        List<Document> finalDocs = new ArrayList<>();
        if (!includedFileNames.contains(fileName)) {
            LOG.debug("Loading action configurations from: {}", fileName);

            includedFileNames.add(fileName);

            Iterator<URL> urls = null;
            InputStream is = null;

            IOException ioException = null;
            try {
                urls = getConfigurationUrls(fileName);
            } catch (IOException ex) {
                ioException = ex;
            }

            if (urls == null || !urls.hasNext()) {
                if (errorIfMissing) {
                    throw new ConfigurationException("Could not open files of the name " + fileName, ioException);
                } else {
                    LOG.trace("Unable to locate configuration files of the name {}, skipping", fileName);
                    return docs;
                }
            }

            URL url = null;
            while (urls.hasNext()) {
                try {
                    url = urls.next();
                    is = fileManager.loadFile(url);

                    InputSource in = new InputSource(is);

                    in.setSystemId(url.toString());

                    docs.add(DomHelper.parse(in, dtdMappings));
                    loadedFileUrls.add(url.toString());
                } catch (StrutsException e) {
                    if (includeElement != null) {
                        throw new ConfigurationException("Unable to load " + url, e, includeElement);
                    } else {
                        throw new ConfigurationException("Unable to load " + url, e);
                    }
                } catch (Exception e) {
                    throw new ConfigurationException("Caught exception while loading file " + fileName, e, includeElement);
                } finally {
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException e) {
                            LOG.error("Unable to close input stream", e);
                        }
                    }
                }
            }

            //sort the documents, according to the "order" attribute
            Collections.sort(docs, new Comparator<Document>() {
                public int compare(Document doc1, Document doc2) {
                    return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2));
                }
            });

            for (Document doc : docs) {
                Element rootElement = doc.getDocumentElement();
                NodeList children = rootElement.getChildNodes();
                int childSize = children.getLength();

                for (int i = 0; i < childSize; i++) {
                    Node childNode = children.item(i);

                    if (childNode instanceof Element) {
                        Element child = (Element) childNode;

                        final String nodeName = child.getNodeName();

                        if ("include".equals(nodeName)) {
                            String includeFileName = child.getAttribute("file");
                            if (includeFileName.indexOf('*') != -1) {
                                // handleWildCardIncludes(includeFileName, docs, child);
                                ClassPathFinder wildcardFinder = new ClassPathFinder();
                                wildcardFinder.setPattern(includeFileName);
                                Vector<String> wildcardMatches = wildcardFinder.findMatches();
                                for (String match : wildcardMatches) {
                                    finalDocs.addAll(loadConfigurationFiles(match, child));
                                }
                            } else {
                                finalDocs.addAll(loadConfigurationFiles(includeFileName, child));
                            }
                        }
                    }
                }
                finalDocs.add(doc);
            }

            LOG.debug("Loaded action configuration from: {}", fileName);
        }
        return finalDocs;
    }

    protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException {
        return ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false);
    }

    /**
     * Allows subclasses to load extra information from the document
     *
     * @param doc The configuration document
     */
    protected void loadExtraConfiguration(Document doc) {
        // no op
    }

    /**
     * Looks up the Interceptor Class from the interceptor-ref name and creates an instance, which is added to the
     * provided List, or, if this is a ref to a stack, it adds the Interceptor instances from the List to this stack.
     *
     * @param context               The PackageConfig to lookup the interceptor from
     * @param interceptorRefElement Element to pull interceptor ref data from
     * @return A list of Interceptor objects
     * @throws ConfigurationException in case of configuration errors
     */
    private List<InterceptorMapping> lookupInterceptorReference(PackageConfig.Builder context, Element interceptorRefElement) throws ConfigurationException {
        String refName = interceptorRefElement.getAttribute("name");
        Map<String, String> refParams = XmlHelper.getParams(interceptorRefElement);

        Location loc = LocationUtils.getLocation(interceptorRefElement);
        return InterceptorBuilder.constructInterceptorReference(context, refName, refParams, loc, objectFactory);
    }

    List<Document> getDocuments() {
        return documents;
    }

    @Override
    public String toString() {
        return "XmlConfigurationProvider{" +
                "configFileName='" + configFileName + '\'' +
                '}';
    }
}
