org.sonar.plugins.xml.schemas.SchemaResolver.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.plugins.xml.schemas.SchemaResolver.java

Source

/*
 * Sonar XML Plugin
 * Copyright (C) 2010 Matthijs Galesloot
 * dev@sonar.codehaus.org
 *
 * Licensed 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.sonar.plugins.xml.schemas;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.utils.SonarException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;

/**
 * Resolves references to XML schema's, if possible built-in.
 * 
 * @author Matthijs Galesloot
 * @since 1.
 */
public final class SchemaResolver implements LSResourceResolver {

    private static final Logger LOG = LoggerFactory.getLogger(SchemaResolver.class);
    private static final Map<String, String> SCHEMAS_BUILTIN = new HashMap<String, String>();
    private static final Map<String, String> DTD_BUILTIN = new HashMap<String, String>();

    // SCHEMA's
    static {

        // XML
        SCHEMAS_BUILTIN.put("http://www.w3.org/2001/xml.xsd", "xml.xsd");

        // XHTML 1.0 - by Doctype
        SCHEMAS_BUILTIN.put("-//W3C//DTD XHTML 1.0 Strict//EN", "xhtml1/xhtml1-strict.xsd");
        SCHEMAS_BUILTIN.put("-//W3C//DTD XHTML 1.0 Transitional//EN", "xhtml1/xhtml1-transitional.xsd");
        SCHEMAS_BUILTIN.put("-//W3C//DTD XHTML 1.0 Frameset//EN", "xhtml1/xhtml1-frameset.xsd");

        // XHTML 1.0 - by namespace
        SCHEMAS_BUILTIN.put("http://www.w3.org/1999/xhtml", "xhtml1/xhtml1-strict.xsd");

        // XHTML 1.0 - by shortname
        SCHEMAS_BUILTIN.put("xhtml1-strict", "xhtml1/xhtml1-strict.xsd");
        SCHEMAS_BUILTIN.put("xhtml1-transitional", "xhtml1/xhtml1-transitional.xsd");
        SCHEMAS_BUILTIN.put("xhtml1-frameset", "xhtml1/xhtml1-frameset.xsd");

        // XHTML 1.1 - by Doctype
        SCHEMAS_BUILTIN.put("-//W3C//DTD XHTML 1.1 Strict//EN", "xhtml11/xhtml11.xsd");

        // JSF Taglib to XSD conversions
        // (from http://blogger.ziesemer.com/2008/03/facelets-and-xsd-converted-tlds.html)
        SCHEMAS_BUILTIN.put("http://java.sun.com/jsf/core", "jsf/jsf-core-2.0.xsd");
        SCHEMAS_BUILTIN.put("http://java.sun.com/jsf/html", "jsf/html-basic-2.0.xsd");
        SCHEMAS_BUILTIN.put("http://java.sun.com/jsf/facelets", "jsf/facelets-ui-2.0.xsd");

        // MAVEN
        SCHEMAS_BUILTIN.put("http://maven.apache.org/POM/4.0.0", "maven/maven-4.0.0.xsd");
    }

    // DTDs
    static {
        // HTML 3.2
        DTD_BUILTIN.put("-//W3C//DTD HTML 3.2//EN", "html32/html32.dtd");
        DTD_BUILTIN.put("-//W3C//DTD HTML 3.2 Final//EN", "html32/html32.dtd");

        // HTML 4.0
        DTD_BUILTIN.put("-//W3C//DTD HTML 4.0//EN", "html4/strict.dtd");
        DTD_BUILTIN.put("-//W3C//DTD HTML 4.0 Transitional//EN", "html4/loose.dtd");
        DTD_BUILTIN.put("-//W3C//DTD HTML 4.0 Frameset//EN", "html4/frameset.dtd");

        // HTML 4.01
        DTD_BUILTIN.put("-//W3C//DTD HTML 4.01//EN", "html4/strict.dtd");
        DTD_BUILTIN.put("-//W3C//DTD HTML 4.01 Transitional//EN", "html4/loose.dtd");
        DTD_BUILTIN.put("-//W3C//DTD HTML 4.01 Frameset//EN", "html4/frameset.dtd");

        // XHTML 1.0
        DTD_BUILTIN.put("-//W3C//DTD XHTML 1.0 Strict//EN", "xhtml1/xhtml1-strict.dtd");
        DTD_BUILTIN.put("-//W3C//DTD XHTML 1.0 Transitional//EN", "xhtml1/xhtml1-transitional.dtd");
        DTD_BUILTIN.put("-//W3C//DTD XHTML 1.0 Frameset//EN", "xhtml1/xhtml1-frameset.dtd");

        // XHTML 1.1
        DTD_BUILTIN.put("//W3C//DTD XHTML 1.1//EN", "xhtml1/xhtml11.dtd");
    }

    private static final String[] SCHEMA_FOLDERS = new String[] { "xhtml1", "jsf" };

    private static LSInput createLSInput(InputStream inputStream) {
        if (inputStream != null) {
            System.setProperty(DOMImplementationRegistry.PROPERTY,
                    "org.apache.xerces.dom.DOMImplementationSourceImpl");

            try {
                DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
                DOMImplementation impl = registry.getDOMImplementation("XML 1.0 LS 3.0");
                DOMImplementationLS implls = (DOMImplementationLS) impl;
                LSInput lsInput = implls.createLSInput();
                lsInput.setByteStream(inputStream);
                return lsInput;
            } catch (ClassNotFoundException e) {
                throw new SonarException(e);
            } catch (InstantiationException e) {
                throw new SonarException(e);
            } catch (IllegalAccessException e) {
                throw new SonarException(e);
            }
        }
        return null;
    }

    /**
     * Gets a built-in DTD.
     */
    private static InputStream getBuiltinDTD(String publicId) {
        String fileName = DTD_BUILTIN.get(publicId);
        if (fileName != null) {
            return getBuiltinDTDByFileName(fileName);
        }
        return null;
    }

    /**
     * Gets a built-in DTD by filename.
     */
    private static InputStream getBuiltinDTDByFileName(String fileName) {
        return SchemaResolver.class.getResourceAsStream("/org/sonar/plugins/xml/dtd/" + fileName);
    }

    /**
     * Get a built-in XML schema.
     */
    public static InputStream getBuiltinSchema(String systemId) {
        InputStream input;

        // try as namespace
        input = getBuiltinSchemaByNamespace(systemId);

        // try as built-in resource
        if (input == null) {
            input = getBuiltinSchemaByFileName(systemId);

            // try as file system resource
            if (input == null) {
                try {
                    input = new FileInputStream(systemId);
                } catch (FileNotFoundException e) {
                    LOG.warn("Could not find schema " + systemId);
                    return null;
                }
            }
        }

        return input;
    }

    /**
     * Gets a built-in XML schema by filename.
     */
    private static InputStream getBuiltinSchemaByFileName(String fileName) {
        InputStream input = SchemaResolver.class.getResourceAsStream(fileName);
        if (input == null) {
            for (String folder : SCHEMA_FOLDERS) {
                input = SchemaResolver.class.getResourceAsStream(folder + "/" + fileName);
                if (input != null) {
                    break;
                }
            }
        }
        return input;
    }

    /**
     * Gets a built-in XML schema by nameSpace.
     */
    private static InputStream getBuiltinSchemaByNamespace(String nameSpace) {
        String fileName = SCHEMAS_BUILTIN.get(nameSpace);
        if (fileName != null) {
            return getBuiltinSchemaByFileName(fileName);
        }
        return null;
    }

    /**
     * ResourceResolver tries to resolve schema's and dtd's with built-in resources or external files.
     */
    public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId,
            String baseURI) {

        InputStream input = null;

        // try as DTD
        if (publicId != null && publicId.contains("//DTD")) {
            input = getBuiltinDTD(publicId);
        } else {

            // try as namespace
            input = getBuiltinSchemaByNamespace(systemId);

            // try as built-in XML schema
            if (input == null) {
                input = getBuiltinSchemaByFileName(systemId);
            }

            // try as built-in entity
            if (input == null) {
                if (StringUtils.startsWithIgnoreCase(systemId, "html")) {
                    input = getBuiltinDTDByFileName("html4/" + systemId);
                } else {
                    input = getBuiltinDTDByFileName("xhtml1/" + systemId);
                }
            }
        }

        if (input == null) {
            LOG.debug("Could not resolve resource: " + systemId);
            return null;
        } else {
            return createLSInput(input);
        }
    }
}