package com.amalto.workbench.widgets.xmlviewer.validator; /***************************************************************************** * 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/> ****************************************************************************/ import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; import org.eclipse.swt.widgets.Display; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import com.amalto.workbench.widgets.xmlviewer.model.XMLNode; import com.amalto.workbench.widgets.xmlviewer.utils.XMLTreeModelUtilities; public class XMLValidator { CheckThread checkthread = new CheckThread(); private final ProjectionAnnotationModel annotationModel; public static final String TYPE = "org.eclipse.ui.workbench.texteditor.error"; //$NON-NLS-1$ private final IDocument document; class CheckThread implements Runnable { private ErrorHandler errorHandler; public CheckThread() { factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setValidating(true); this.errorHandler = new ErrorHandler() { private int getCharStart(int lineNumber, int columnNumber) { try { int lineStartChar = document.getLineOffset(lineNumber - 1); Integer charEnd = getCharEnd(lineNumber, columnNumber); if (charEnd != null) { ITypedRegion typedRegion = document.getPartition(charEnd.intValue() - 2); int partitionStartChar = typedRegion.getOffset(); return partitionStartChar; } else return lineStartChar; } catch (BadLocationException e) { return 0; } } private Integer getCharEnd(int lineNumber, int columnNumber) { try { return Integer.valueOf(document.getLineOffset(lineNumber - 1) + columnNumber); } catch (BadLocationException e) { e.printStackTrace(); return null; } } private Annotation createNewAnnotaion(SAXParseException exception) { String message = exception.getMessage(); message = message.substring(message.indexOf(":") + 1).trim(); //$NON-NLS-1$ // REVISARME para ver si hay otra forma de hacer esto if (!"no grammar found.".equals(message) && !message.endsWith("must match DOCTYPE root \"null\".")) { //$NON-NLS-1$ //$NON-NLS-2$ return new Annotation(TYPE, false, message); } return null; } private void updateAnnotation(SAXParseException exception) { Annotation annotation = createNewAnnotaion(exception); if (annotation != null) { int offset = getCharStart(exception.getLineNumber(), exception.getColumnNumber()); XMLNode activeNode = XMLTreeModelUtilities.getActiveNode(document, offset); if (annotationModel != null) { lastAnnotation = annotation; Position position = new Position(offset); if (activeNode != null) { position.setLength(activeNode.getLength()); } annotationModel.addAnnotation(annotation, position); } } } public void warning(SAXParseException exception) throws SAXException { exception.printStackTrace(); } public void fatalError(SAXParseException exception) throws SAXException { updateAnnotation(exception); } public void error(SAXParseException exception) throws SAXException { updateAnnotation(exception); } }; } private String xml; private DocumentBuilderFactory factory; /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ public void run() { if (xml == null || xml.trim().length() == 0) return; try { // clear clearLastAnnotaion(); // DocumentBuilder builder = factory.newDocumentBuilder(); builder.setErrorHandler(errorHandler); builder.parse(new InputSource(new StringReader(xml))); } catch (Exception e) { // do nothing because already has errHandler to handle it } } public void setXML(String xml) { this.xml = xml; } } /** * DOC hbhong XMLValidator constructor comment. * * @param document * * @param annotationModel */ public XMLValidator(IDocument document, ProjectionAnnotationModel annotationModel) { this.document = document; this.annotationModel = annotationModel; } Annotation lastAnnotation; private void clearLastAnnotaion() { if (annotationModel != null) { if (lastAnnotation != null) { annotationModel.removeAnnotation(lastAnnotation); } } } /** * DOC hbhong Comment method "validate". * * @param document */ public void validate(IDocument document) { checkthread.setXML(document.get()); Display.getDefault().asyncExec(checkthread); } }