/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.myfaces.util;

import org.apache.myfaces.util.lang.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.context.ExternalContext;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.apache.myfaces.util.lang.ClassUtils;

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;

public class WebXmlParser
{
    private static final Logger LOGGER = Logger.getLogger(WebXmlParser.class.getName());

    private static final String ERROR_PAGE_EXCEPTION_TYPE_EXPRESSION =
            "*[local-name() = 'error-page']/*[local-name() = 'exception-type']";
    private static final String LOCATION_EXPRESSION =
            "*[local-name() = 'location']";
    private static final String ERROR_CODE_500_LOCATION_EXPRESSION =
            "*[local-name() = 'error-page'][*[local-name() = 'error-code'] = '500'] / *[local-name() = 'location']";
    private static final String ERROR_PAGE_NO_CODE_AND_TYPE_EXPRESSION =
            "*[local-name() = 'error-page'][not(*[local-name() = 'error-code']) and not"
            + "(*[local-name() = 'exception-type'])]/*[local-name() = 'location']";

    private static final String KEY_ERROR_PAGES = WebXmlParser.class.getName() + ".errorpages";
    
    private WebXmlParser()
    {
    }

    /**
     * Parses the web.xml and web-fragements.xml for error pages.
     * "null" as key represents the default error page. Otherwise the key is the exception class.
     * 
     * @param context
     * @return 
     */
    public static Map<String, String> getErrorPages(ExternalContext context)
    {
        // it would be nicer if the cache would probably directly in DefaultWebConfigProvider
        // as its currently the only caller of the method
        // however it's recreated every request, we have to refactor the SPI thing a bit probably.
        Map<String, String> cached = (Map<String, String>) context.getApplicationMap().get(KEY_ERROR_PAGES);
        if (cached != null)
        {
            return cached;
        }
        
        Map<String, String> webXmlErrorPages = getWebXmlErrorPages(context);
        Map<String, String> webFragmentXmlsErrorPages = getWebFragmentXmlsErrorPages(context);

        Map<String, String> errorPages = webXmlErrorPages;
        if (errorPages == null)
        {
            errorPages = webFragmentXmlsErrorPages;
        }
        else if (webFragmentXmlsErrorPages != null)
        {
            for (Map.Entry<String, String> entry : webFragmentXmlsErrorPages.entrySet())
            {
                if (!errorPages.containsKey(entry.getKey()))
                {
                    errorPages.put(entry.getKey(), entry.getValue());
                }
            }
        }

        context.getApplicationMap().put(KEY_ERROR_PAGES, errorPages);
        
        return errorPages;
    }

    private static Map<String, String> getWebXmlErrorPages(ExternalContext context)
    {
        try
        {
            Document webXml = toDocument(context.getResource("/WEB-INF/web.xml"));
            
            if (webXml == null)
            {
                // Quarkus
                webXml = toDocument(ClassUtils.getCurrentLoader(WebXmlParser.class).getResource("META-INF/web.xml"));
            }
            
            if (webXml != null)
            {
                return parseErrorPages(webXml.getDocumentElement());
            }
        }
        catch (Throwable e)
        {
            LOGGER.log(Level.SEVERE, "Could not load or parse web.xml", e);
        }

        return null;
    }

    private static Map<String, String> getWebFragmentXmlsErrorPages(ExternalContext context)
    {
        Map<String, String> webFragmentXmlsErrorPages = null;

        try
        {
            Enumeration<URL> webFragments = Thread.currentThread().getContextClassLoader()
                    .getResources("META-INF/web-fragment.xml");
            while (webFragments.hasMoreElements())
            {
                try
                {
                    URL url = webFragments.nextElement();
                    Document webFragmentXml = toDocument(url);
                    if (webFragmentXml != null)
                    {
                        if (webFragmentXmlsErrorPages == null)
                        {
                            webFragmentXmlsErrorPages = parseErrorPages(webFragmentXml.getDocumentElement());
                        }
                        else
                        {
                            Map<String, String> temp = parseErrorPages(webFragmentXml.getDocumentElement());
                            for (Map.Entry<String, String> entry : temp.entrySet())
                            {
                                if (!webFragmentXmlsErrorPages.containsKey(entry.getKey()))
                                {
                                    webFragmentXmlsErrorPages.put(entry.getKey(), entry.getValue());
                                }
                            }
                        }
                    }
                }
                catch (Throwable e)
                {
                    LOGGER.log(Level.SEVERE, "Could not load or parse web-fragment.xml", e);
                }
            }
        }
        catch (IOException e)
        {
            LOGGER.log(Level.SEVERE, "Could not get web-fragment.xml\'s from ClassLoader", e);
        }

        return webFragmentXmlsErrorPages;
    }

    private static Document toDocument(URL url) throws Exception
    {
        InputStream is = null;

        try
        {
            // web.xml is optional
            if (url == null)
            {
                return null;
            }

            is = url.openStream();

            if (is == null)
            {
                return null;
            }

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(false);
            factory.setNamespaceAware(false);
            factory.setExpandEntityReferences(false);
            factory.setIgnoringElementContentWhitespace(true);
            factory.setIgnoringComments(true);

            try
            {
                factory.setFeature("http://xml.org/sax/features/namespaces", false);
                factory.setFeature("http://xml.org/sax/features/validation", false);
                factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
                factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
            }
            catch (Throwable e)
            {
                LOGGER.warning("DocumentBuilderFactory#setFeature not implemented. Skipping...");
            }

            boolean absolute = false;
            try
            {
                absolute = url.toURI().isAbsolute();
            }
            catch (URISyntaxException e)
            {
                // noop
            }

            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document;

            if (absolute)
            {
                InputSource source = new InputSource(url.toExternalForm());
                source.setByteStream(is);
                document = builder.parse(source);
            }
            else
            {
                document = builder.parse(is);
            }

            return document;
        }
        finally
        {
            if (is != null)
            {
                try
                {
                    is.close();
                }
                catch (IOException e)
                {
                    // ignore
                }
            }
        }
    }

    private static Map<String, String> parseErrorPages(Element webXml) throws Exception
    {
        Map<String, String> errorPages = new HashMap<>();

        XPath xpath = XPathFactory.newInstance().newXPath();

        NodeList exceptionTypes = (NodeList) xpath.compile(ERROR_PAGE_EXCEPTION_TYPE_EXPRESSION)
                .evaluate(webXml, XPathConstants.NODESET);

        for (int i = 0; i < exceptionTypes.getLength(); i++)
        {
            Node node = exceptionTypes.item(i);

            String exceptionType = node.getTextContent().trim();
            String key = Throwable.class.getName().equals(exceptionType) ? null : exceptionType;

            String location = xpath.compile(LOCATION_EXPRESSION).evaluate(node.getParentNode()).trim();

            if (!errorPages.containsKey(key))
            {
                errorPages.put(key, location);
            }
        }

        if (!errorPages.containsKey(null))
        {
            String defaultLocation = xpath.compile(ERROR_CODE_500_LOCATION_EXPRESSION).evaluate(webXml).trim();

            if (StringUtils.isBlank(defaultLocation))
            {
                defaultLocation = xpath.compile(ERROR_PAGE_NO_CODE_AND_TYPE_EXPRESSION).evaluate(webXml).trim();
            }

            if (!StringUtils.isBlank(defaultLocation))
            {
                errorPages.put(null, defaultLocation);
            }
        }

        return errorPages;
    }
    
}
