/***************************************************************************** * This file is part of Rinzo * * Author: Claudio Cancinos * WWW: https://sourceforge.net/projects/editorxml * Copyright (C): 2008, Claudio Cancinos * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; If not, see <http://www.gnu.org/licenses/> ****************************************************************************/ package ar.com.tadp.xml.rinzo.core.resources.validation; import java.io.StringReader; import java.net.URI; import java.util.Collection; import java.util.Map; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import org.apache.commons.lang.StringUtils; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import ar.com.tadp.xml.rinzo.XMLEditorPlugin; import ar.com.tadp.xml.rinzo.core.RinzoXMLEditor; import ar.com.tadp.xml.rinzo.core.resources.cache.DocumentCache; import ar.com.tadp.xml.rinzo.core.resources.cache.DocumentStructureDeclaration; import ar.com.tadp.xml.rinzo.core.utils.FileUtils; /** * Validates if the content of an editor is a well formed XML file. * If the file defines a DTD or XSD the file is validated against it. * * @author ccancinos */ public class XMLStringValidator implements XmlValidator { private MarkersErrorHandler errorHandler; private ExternalResolver resolver = new ExternalResolver(); public void validate(RinzoXMLEditor editor) { this.errorHandler = new MarkersErrorHandler(editor); this.errorHandler.setFile(editor.getEditorInputIFile()); String fileName = editor.getFileName(); String fileContent = editor.getSourceViewerEditor().getDocument().get(); if(!StringUtils.isEmpty(fileContent.trim())) { Collection<DocumentStructureDeclaration> schemaDefinitions = editor.getModel().getSchemaDefinitions(); if(schemaDefinitions != null && !schemaDefinitions.isEmpty()) { this.saxSchemaValidate(fileName, fileContent, schemaDefinitions); } else { DocumentStructureDeclaration dtdDefinition = editor.getModel().getDTDDefinition(); if(dtdDefinition != null) { this.saxDTDValidate(fileName, fileContent, dtdDefinition); } else { this.plainTextValidate(fileName, fileContent); } } } } private void plainTextValidate(String fileName, String fileContent) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(false); try { DocumentBuilder builder = factory.newDocumentBuilder(); builder.setErrorHandler(this.errorHandler); builder.parse(new InputSource(new StringReader(fileContent))); } catch (Exception e) { //Do nothing because the errorHandler informs the error } } private void saxDTDValidate(String fileName, String fileContent, DocumentStructureDeclaration structureDeclaration) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(true); try { DocumentBuilder builder = factory.newDocumentBuilder(); URI resolverURI = FileUtils.resolveURI(fileName, structureDeclaration.getSystemId()); if(resolverURI != null) { this.resolver.setBaseURL(fileName); this.resolver.setSystemId(structureDeclaration.getSystemId()); builder.setEntityResolver(this.resolver); } builder.setErrorHandler(this.errorHandler); builder.parse(new InputSource(new StringReader(fileContent))); } catch (Exception e) { //Do nothing because the errorHandler informs the error } } private void saxSchemaValidate(String fileName, String fileContent, Collection<DocumentStructureDeclaration> schemaDefinitions) { try { Validator validator; Map<Collection<DocumentStructureDeclaration>, Validator> schemaValidatorsCache = XMLEditorPlugin.getDefault().getSchemaValidatorsCache(); validator = schemaValidatorsCache.get(schemaDefinitions); if(validator == null) { StreamSource[] sources = new StreamSource[schemaDefinitions.size()]; int pos = 0; Map<String, String> fileLocations = DocumentCache.getInstance().getAllLocations(schemaDefinitions, fileName); for (Map.Entry<String, String> fileLocation : fileLocations.entrySet()) { StreamSource streamSource = new StreamSource(fileLocation.getValue()); streamSource.setPublicId(fileLocation.getKey()); sources[pos++] = streamSource; } validator = this.createValidator(sources); schemaValidatorsCache.put(schemaDefinitions, validator); } validator.reset(); validator.setErrorHandler(this.errorHandler); validator.validate(new StreamSource(new StringReader(fileContent))); } catch (SAXParseException saxE) { try { this.errorHandler.error(saxE); } catch (SAXException e) { } } catch (Exception exception) { //Do nothing because the errorHandler informs the error } } private Validator createValidator(StreamSource[] sources) throws Exception { SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); sf.setFeature("http://apache.org/xml/features/xinclude", true); Schema schema = sf.newSchema(sources); return schema.newValidator(); } /** * @return Returns the errorHandler. */ public ErrorHandler getErrorHandler() { return this.errorHandler; } /** * @param errorHandler The errorHandler to set. */ public void setErrorHandler(MarkersErrorHandler errorHandler) { this.errorHandler = errorHandler; } }