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

org.vfny.geoserver.util.SLDValidator Maven / Gradle / Ivy

The newest version!
/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org.  All rights reserved.
 * This code is licensed under the GPL 2.0 license, availible at the root
 * application directory.
 */

/*
 * Created on April 20, 2005
 *
 */
package org.vfny.geoserver.util;

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;


public class SLDValidator {
    static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.vfny.geoserver");

    public SLDValidator() {
    }

    /**
     * validates against the "normal" location of the schema (ie.
     * ".../schemas/sld/StyleLayerDescriptor.xsd" uses the geoserver_home
     * patch
     *
     * @param xml
     * @param servContext servlet context
     *
     * @return
     */
    public List validateSLD(InputStream xml, ServletContext servContext) {
        // a riminder not to use the data directory for the schemas
        //String url = GeoserverDataDirectory.getGeoserverDataDirectory(servContext).toString();
        return validateSLD(new InputSource(xml), servContext);

        /*try {
                     URL schemaFile = servContext.getResource("/schemas/sld/StyledLayerDescriptor.xsd");
                     LOGGER.info("Validating SLD with " + schemaFile.toString());

            return validateSLD(xml, schemaFile.toString());
        } catch (Exception e) {
                LOGGER.severe(e.getLocalizedMessage());
                ArrayList al = new ArrayList();
            al.add(new SAXException(e));

            return al;
        }*/
    }

    public static String getErrorMessage(InputStream xml, List errors) {
        return getErrorMessage(new InputStreamReader(xml), errors);
    }

    /**
     * returns a better formated error message - suitable for framing. There's
     * a more complex version in StylesEditorAction. This will kick out a VERY
     * LARGE errorMessage.
     *
     * @param xml
     * @param errors
     *
     * @return DOCUMENT ME!
     */
    public static String getErrorMessage(Reader xml, List errors) {
        BufferedReader reader = null;
        StringBuffer result = new StringBuffer();
        result.append("Your SLD is not valid.\n");
        result.append(
            "Most common problems are: \n(1) no namespaces - use , , ,   - the part before the ':' is important\n");
        result.append("(2) capitialization - use '' not '' \n");
        result.append("(3) Order - The order of elements is important \n");
        result.append(
            "(4) Make sure your first tag imports the correct namespaces.  ie. xmlns:sld=\"http://www.opengis.net/sld\" for EVERY NAMESPACE \n");
        result.append("\n");

        try {
            reader = new BufferedReader(xml);

            String line = reader.readLine();
            int linenumber = 1;
            int exceptionNum = 0;

            //check for lineNumber -1 errors  --> invalid XML
            if (errors.size() > 0) {
                SAXParseException sax = (SAXParseException) errors.get(0);

                if (sax.getLineNumber() < 0) {
                    result.append("   INVALID XML: " + sax.getLocalizedMessage() + "\n");
                    result.append(" \n");
                    exceptionNum = 1; // skip ahead (you only ever get one error in this case)
                }
            }

            while (line != null) {
                line.replace('\n', ' ');
                line.replace('\r', ' ');

                String header = linenumber + ": ";
                result.append(header + line + "\n"); // record the current line

                boolean keep_going = true;

                while (keep_going) {
                    if ((exceptionNum < errors.size())) {
                        SAXParseException sax = (SAXParseException) errors.get(exceptionNum);

                        if (sax.getLineNumber() <= linenumber) {
                            String head = "---------------------".substring(0, header.length() - 1);
                            String body = "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";

                            int colNum = sax.getColumnNumber(); //protect against col 0 problems

                            if (colNum < 1) {
                                colNum = 1;
                            }

                            if (colNum > body.length()) {
                                body = body + body + body + body + body + body; // make it longer (not usually required, but might be for SLD_BODY=... which is all one line)

                                if (colNum > body.length()) {
                                    colNum = body.length();
                                }
                            }

                            result.append(head + body.substring(0, colNum - 1) + "^\n");
                            result.append("       (line " + sax.getLineNumber() + ", column "
                                + sax.getColumnNumber() + ")" + sax.getLocalizedMessage() + "\n");
                            exceptionNum++;
                        } else {
                            keep_going = false; //report later (sax.getLineNumber() > linenumber)
                        }
                    } else {
                        keep_going = false; // no more errors to report
                    }
                }

                line = reader.readLine(); //will be null at eof
                linenumber++;
            }

            for (int t = exceptionNum; t < errors.size(); t++) {
                SAXParseException sax = (SAXParseException) errors.get(t);
                result.append("       (line " + sax.getLineNumber() + ", column "
                    + sax.getColumnNumber() + ")" + sax.getLocalizedMessage() + "\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return result.toString();
    }

    /*public List validateSLD(InputStream xml, String SchemaUrl) {
        return validateSLD(new InputSource(xml), SchemaUrl);
    }*/

    /*public List validateSLD(InputSource xml, ServletContext servContext) {
        File schemaFile = new File(servContext.getRealPath("/"),
        "/schemas/sld/StyledLayerDescriptor.xsd");

        try {
            return validateSLD(xml, schemaFile.toURL().toString());
        } catch (Exception e) {
            ArrayList al = new ArrayList();
            al.add(new SAXException(e));

            return al;
        }
    }*/

    /**
     * validate a .sld against the schema
     *
     * @param xml input stream representing the .sld file
     * @param SchemaUrl location of the schemas. Normally use
     *        ".../schemas/sld/StyleLayerDescriptor.xsd"
     *
     * @return list of SAXExceptions (0 if the file's okay)
     */
    public List validateSLD(InputSource xml, ServletContext servContext) {
        SAXParser parser = new SAXParser();

        try {
            // this takes care of spaces in the path to the file
            URL schemaFile = servContext.getResource("/schemas/sld/StyledLayerDescriptor.xsd");

            if (LOGGER.isLoggable(Level.INFO)) {
                LOGGER.info(new StringBuffer("Validating SLD with ").append(schemaFile.toString())
                                                                    .toString());
            }

            String schemaUrl = schemaFile.toString();

            //     1. tell the parser to validate the XML document vs the schema
            //     2. does not validate the schema (the GML schema is *not* valid.  This is
            //        			an OGC blunder)
            //     3. tells the validator that the tags without a namespace are actually
            //        			SLD tags.
            //     4. tells the validator to 'override' the SLD schema that a user may
            //        			include with the one inside geoserver.
            parser.setFeature("http://xml.org/sax/features/validation", true);
            parser.setFeature("http://apache.org/xml/features/validation/schema", true);
            parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking",
                false);

            parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",
                schemaUrl);
            parser.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",
                "http://www.opengis.net/sld " + schemaUrl);

            //parser.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation","http://www.opengis.net/ows "+SchemaUrl);
            Validator handler = new Validator();
            parser.setErrorHandler(handler);
            parser.parse(xml);

            return handler.errors;
        } catch (java.io.IOException ioe) {
            ArrayList al = new ArrayList();
            al.add(new SAXParseException(ioe.getLocalizedMessage(), null));

            return al;
        } catch (SAXException e) {
            ArrayList al = new ArrayList();
            al.add(new SAXParseException(e.getLocalizedMessage(), null));

            return al;
        }
    }

    // errors in the document will be put in "errors".
    // if errors.size() ==0  then there were no errors.
    private class Validator extends DefaultHandler {
        public ArrayList errors = new ArrayList();

        public void error(SAXParseException exception)
            throws SAXException {
            errors.add(exception);
        }

        public void fatalError(SAXParseException exception)
            throws SAXException {
            errors.add(exception);
        }

        public void warning(SAXParseException exception)
            throws SAXException {
            //do nothing
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy