All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.config.ConfigFilesXmlValidationUtils Maven / Gradle / Ivy

Go to download

The private implementation classes of the Apache MyFaces Core JSF-2.3-next Implementation

There is a newer version: 4.1.0-RC2
Show newest version
/*
 * 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.config;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.faces.context.ExternalContext;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.myfaces.util.lang.ClassUtils;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

public class ConfigFilesXmlValidationUtils
{
    public final static LSResourceResolver JAVAEE_5_LS_RESOURCE_RESOLVER = new ValidatorLSResourceResolver();
    public final static ErrorHandler VALIDATION_ERROR_HANDLER = new ValidationErrorHandler(); 

    private final static String FACES_CONFIG_SCHEMA_PATH_12 = "org/apache/myfaces/resource/web-facesconfig_1_2.xsd";
    private final static String FACES_CONFIG_SCHEMA_PATH_20 = "org/apache/myfaces/resource/web-facesconfig_2_0.xsd";
    private final static String FACES_CONFIG_SCHEMA_PATH_21 = "org/apache/myfaces/resource/web-facesconfig_2_1.xsd";
    private final static String FACES_CONFIG_SCHEMA_PATH_22 = "org/apache/myfaces/resource/web-facesconfig_2_2.xsd";
    private final static String FACES_CONFIG_SCHEMA_PATH_23 = "org/apache/myfaces/resource/web-facesconfig_2_3.xsd";
    private final static String FACES_TAGLIB_SCHEMA_PATH = "org/apache/myfaces/resource/web-facelettaglibrary_2_0.xsd";

    public static class LSInputImpl implements LSInput
    {
        private final String _publicId;
        private final String _systemId;
        private final String _baseURI;
        private final InputStream _input;
        
        public LSInputImpl(String publicId,String systemId, String baseURI, InputStream input)
        {
            super();
            _publicId = publicId;
            _systemId = systemId;
            _baseURI = baseURI;
            _input = input;
        }

        @Override
        public String getBaseURI()
        {
            return _baseURI;
        }

        @Override
        public InputStream getByteStream()
        {
            return _input;
        }

        @Override
        public boolean getCertifiedText()
        {
            return false;
        }

        @Override
        public Reader getCharacterStream()
        {
            return null;
        }

        @Override
        public String getEncoding()
        {
            return null;
        }

        @Override
        public String getPublicId()
        {
            return _publicId;
        }

        @Override
        public String getStringData()
        {
            return null;
        }

        @Override
        public String getSystemId()
        {
            return _systemId;
        }

        @Override
        public void setBaseURI(String baseURI)
        {
        }

        @Override
        public void setByteStream(InputStream byteStream)
        {
        }

        @Override
        public void setCertifiedText(boolean certifiedText)
        {
        }

        @Override
        public void setCharacterStream(Reader characterStream)
        {
        }

        @Override
        public void setEncoding(String encoding)
        {
        }

        @Override
        public void setPublicId(String publicId)
        {
        }

        @Override
        public void setStringData(String stringData)
        {
        }

        @Override
        public void setSystemId(String systemId)
        {
        }
    }
    
    public static class ValidatorLSResourceResolver implements LSResourceResolver
    {
        @Override
        public LSInput resolveResource(String type, String namespaceURI,
                String publicId, String systemId, String baseURI)
        {
            if ("http://www.w3.org/TR/REC-xml".equals(type) && "datatypes.dtd".equals(systemId))
            {
                return new LSInputImpl(publicId, systemId, baseURI,
                        ClassUtils.getResourceAsStream("org/apache/myfaces/resource/datatypes.dtd"));
            }
            if ("-//W3C//DTD XMLSCHEMA 200102//EN".equals(publicId) && "XMLSchema.dtd".equals(systemId))
            {
                return new LSInputImpl(publicId, systemId, baseURI,
                        ClassUtils.getResourceAsStream("org/apache/myfaces/resource/XMLSchema.dtd"));
            }
            if ("http://java.sun.com/xml/ns/javaee".equals(namespaceURI))
            {
                if ("javaee_5.xsd".equals(systemId))
                {
                    return new LSInputImpl(publicId, systemId, baseURI,
                            ClassUtils.getResourceAsStream("org/apache/myfaces/resource/javaee_5.xsd"));
                }
            }
            if ("http://www.w3.org/XML/1998/namespace".equals(namespaceURI))
            {
                return new LSInputImpl(publicId, systemId, baseURI,
                        ClassUtils.getResourceAsStream("org/apache/myfaces/resource/xml.xsd"));
            }
            return null;
        }
        
    } 
    
    public static class ValidationErrorHandler implements ErrorHandler
    {
        @Override
        public void fatalError(SAXParseException exception) throws SAXException
        {
            throw exception;
        }
        
        @Override
        public void error(SAXParseException exception) throws SAXException
        {
            Logger log = Logger.getLogger(ConfigFilesXmlValidationUtils.class.getName());
            log.log(Level.SEVERE, exception.getMessage(), exception);
        }

        @Override
        public void warning(SAXParseException exception) throws SAXException
        {
            Logger log = Logger.getLogger(ConfigFilesXmlValidationUtils.class.getName());
            log.log(Level.WARNING, exception.getMessage(), exception);
        }
    }
    
    public static void validateFacesConfigFile(URL xmlFile,ExternalContext externalContext, String version)
            throws SAXException, IOException
    {
        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

        Source schemaFile = getFacesConfigSchemaFileAsSource(externalContext, version);
        if (schemaFile == null)
        {
            throw new IOException("Could not find schema file for validation.");
        }
        
        schemaFactory.setResourceResolver(JAVAEE_5_LS_RESOURCE_RESOLVER);
        Schema schema = schemaFactory.newSchema(schemaFile);

        Validator validator = schema.newValidator();
        URLConnection conn = xmlFile.openConnection();
        conn.setUseCaches(false);
        try (InputStream is = conn.getInputStream())
        {
            Source source = new StreamSource(is);
            validator.setErrorHandler(VALIDATION_ERROR_HANDLER);
            validator.validate(source);
        }
    }

    private static Source getFacesConfigSchemaFileAsSource(ExternalContext externalContext, String version)
    {
        String xmlSchema = "1.2".equals(version)
                            ? FACES_CONFIG_SCHEMA_PATH_12
                            : ("2.0".equals(version) ? FACES_CONFIG_SCHEMA_PATH_20 
                            : ("2.1".equals(version) ? FACES_CONFIG_SCHEMA_PATH_21
                            : ("2.2".equals(version) ? FACES_CONFIG_SCHEMA_PATH_22 : FACES_CONFIG_SCHEMA_PATH_23)));
        
        InputStream stream = ClassUtils.getResourceAsStream(xmlSchema);
        
        if (stream == null)
        {
           stream = externalContext.getResourceAsStream(xmlSchema);
        }

        if (stream == null)
        {
            return null;
        }
        
        return new StreamSource(stream);
    }

    public static final String getFacesConfigVersion(URL url)
    {
        String result = "2.0";

        try
        {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser;
            FacesConfigVersionCheckHandler handler = new FacesConfigVersionCheckHandler();

            // We need to create a non-validating, non-namespace aware parser used to simply check
            // which version of the facelets taglib document we are dealing with.

            factory.setNamespaceAware(false);
            factory.setFeature("http://xml.org/sax/features/validation", false);
            factory.setValidating(false);

            parser = factory.newSAXParser();

            URLConnection conn = url.openConnection();
            conn.setUseCaches(false);
            try (InputStream input = conn.getInputStream())
            {
                try
                {
                    parser.parse(input, handler);
                }
                catch (SAXException e)
                {
                    // This is as a result of our aborted parse, so ignore.
                }
            }

            result = handler.isVersion23OrLater() ? "2.3" : (handler.isVersion22() ? "2.2" : 
                        (handler.isVersion21() ? "2.1" : (handler.isVersion20() ? "2.0" : 
                        (handler.isVersion12() ? "1.2" : "1.1"))));
        }
        catch (Throwable e)
        {
            // Most likely a result of our aborted parse, so ignore.
        }

        return result;
    }

    private static class FacesConfigVersionCheckHandler extends DefaultHandler
    {
        private boolean version12;
        private boolean version20;
        private boolean version21;
        private boolean version22;
        private boolean version23OrLater;

        public boolean isVersion12()
        {
            return this.version12;
        }

        public boolean isVersion20()
        {
            return this.version20;
        }

        public boolean isVersion21()
        {
            return this.version21;
        }

        public boolean isVersion22()
        {
            return this.version22;
        }
        
        public boolean isVersion23OrLater()
        {
            return this.version23OrLater;
        }

        @Override
        public void startElement(String uri, String localName, String name,
                Attributes attributes) throws SAXException
        {
            if (name.equals("faces-config"))
            {
                int length = attributes.getLength();

                for (int i = 0; i < length; i++)
                {
                    String attrName = attributes.getLocalName(i);
                    attrName = (attrName != null) ? ((attrName.length() > 0) ? attrName
                            : attributes.getQName(i))
                            : attributes.getQName(i);
                    if (attrName.equals("version"))
                    {
                        if (attributes.getValue(i).equals("1.2"))
                        {
                            this.version12 = true;
                            this.version20 = false;
                            this.version21 = false;
                            this.version22 = false;
                            this.version23OrLater = false;
                        }
                        else if (attributes.getValue(i).equals("2.0"))
                        {
                            this.version12 = false;
                            this.version20 = true;
                            this.version21 = false;
                            this.version22 = false;
                            this.version23OrLater = false;
                        }
                        else if (attributes.getValue(i).equals("2.1"))
                        {
                            this.version12 = false;
                            this.version20 = false;
                            this.version21 = true;
                            this.version22 = false;
                            this.version23OrLater = false;
                        }
                        else if (attributes.getValue(i).equals("2.2"))
                        {
                            this.version12 = false;
                            this.version20 = false;
                            this.version21 = false;
                            this.version22 = true;
                            this.version23OrLater = false;
                        }
                        else
                        {
                            this.version12 = false;
                            this.version20 = false;
                            this.version21 = false;
                            this.version22 = false;
                            this.version23OrLater = true;
                        }
                    }
                }
            }
        }
    }
    
    public static void validateFaceletTagLibFile(URL xmlFile, ExternalContext externalContext, String version)
        throws SAXException, IOException, ParserConfigurationException
    {
        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        
        Source schemaFile = getFaceletSchemaFileAsSource(externalContext);
        if (schemaFile == null)
        {
            throw new IOException("Could not find schema file for validation.");
        }
        schemaFactory.setResourceResolver(ConfigFilesXmlValidationUtils.JAVAEE_5_LS_RESOURCE_RESOLVER);
        Schema schema = schemaFactory.newSchema(schemaFile);
    
        Validator validator = schema.newValidator();
        URLConnection conn = xmlFile.openConnection();
        conn.setUseCaches(false);
        try (InputStream is = conn.getInputStream())
        {
            Source source = new StreamSource(is);
            validator.setErrorHandler(VALIDATION_ERROR_HANDLER);
            validator.validate(source);
        }
    }
    
    private static Source getFaceletSchemaFileAsSource(ExternalContext externalContext)
    {
        InputStream stream = ClassUtils.getResourceAsStream(FACES_TAGLIB_SCHEMA_PATH);
        
        if (stream == null)
        {
           stream = externalContext.getResourceAsStream(FACES_TAGLIB_SCHEMA_PATH);
        }
    
        if (stream == null)
        {
            return null;
        }
        
        return new StreamSource(stream);
    }
    
    public static final String getFaceletTagLibVersion(URL url)
    {
        if (isTaglibDocument20OrLater(url))
        {
            return "2.0";
        }
        else
        {
            return "1.0";
        }
    }

    private static boolean isTaglibDocument20OrLater(URL url)
    {
        try
        {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser;
            VersionCheckHandler handler = new VersionCheckHandler();
            
            // We need to create a non-validating, non-namespace aware parser used to simply check
            // which version of the facelets taglib document we are dealing with.
            factory.setNamespaceAware(false);
            factory.setFeature("http://xml.org/sax/features/validation", false);
            factory.setValidating(false);
            
            parser = factory.newSAXParser();
            
            URLConnection conn = url.openConnection();
            conn.setUseCaches(false);
            try (InputStream input = conn.getInputStream())
            {
                try
                {
                    parser.parse (input, handler);
                }
                catch (SAXException e)
                {
                    // This is as a result of our aborted parse, so ignore.
                }
            }
            
            return handler.isVersion20OrLater();
        }
        catch (Throwable e)
        {
            // Most likely a result of our aborted parse, so ignore.
        }
        
        return false;
    }

    
    /*
     * We need this class to do a quick check on a facelets taglib document to see if it's
     * a pre-2.0 document.  If it is, we really need to construct a DTD validating, non-namespace
     * aware parser. Otherwise, we have to construct a schema validating, namespace-aware parser.
     */
    private static class VersionCheckHandler extends DefaultHandler
    {
        private boolean version20OrLater;
        
        public boolean isVersion20OrLater()
        {
            return this.version20OrLater;
        }
        
        @Override
        public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException
        {
            if (name.equals("facelet-taglib"))
            {
                int length = attributes.getLength();
                
                for (int i = 0; i < length; i++)
                {
                    String attrName = attributes.getLocalName(i);
                    attrName = attrName != null
                            ? ((attrName.length() > 0) ? attrName : attributes.getQName(i))
                            : attributes.getQName(i);
                    if (attrName.equals("version"))
                    {
                        // This document has a "version" attribute in the  element, so
                        // it must be a 2.0 or later document as this attribute was never required before.
                        this.version20OrLater = true;
                    }
                }
                
                // Throw a dummy parsing exception to terminate parsing as there really isn't any need to go any
                // further.
                // -= Leonardo Uribe =- THIS IS NOT GOOD PRACTICE! It is better to let the checker continue that
                // throw an exception, and run this one only when project stage != production.
                //throw new SAXException();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy