Skip to content

Commit

Permalink
XSD 1.1 working
Browse files Browse the repository at this point in the history
Fix #363

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Jul 17, 2019
1 parent 2c6d46a commit 2ee7159
Show file tree
Hide file tree
Showing 13 changed files with 223 additions and 44 deletions.
5 changes: 3 additions & 2 deletions org.eclipse.lsp4xml/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,11 @@
<artifactId>org.eclipse.lsp4j.jsonrpc</artifactId>
</dependency>
<dependency>
<groupId>xerces</groupId>
<groupId>org.exist-db.thirdparty.xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.12.0</version>
</dependency>
<classifier>xml-schema-1.1</classifier>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,17 @@ public class ContentModelPlugin implements IXMLExtension {

private final IHoverParticipant hoverParticipant;

private final ContentModelDiagnosticsParticipant diagnosticsParticipant;
private ContentModelDiagnosticsParticipant diagnosticsParticipant;

private final ContentModelCodeActionParticipant codeActionParticipant;

private final ContentModelDocumentLinkParticipant documentLinkParticipant;

ContentModelManager contentModelManager;

private ContentModelSettings cmSettings;

public ContentModelPlugin() {
completionParticipant = new ContentModelCompletionParticipant();
hoverParticipant = new ContentModelHoverParticipant();
diagnosticsParticipant = new ContentModelDiagnosticsParticipant(this);
codeActionParticipant = new ContentModelCodeActionParticipant();
documentLinkParticipant = new ContentModelDocumentLinkParticipant();
}
Expand Down Expand Up @@ -75,10 +72,12 @@ public void doSave(ISaveContext context) {

private void updateSettings(ISaveContext saveContext) {
Object initializationOptionsSettings = saveContext.getSettings();
cmSettings = ContentModelSettings.getContentModelXMLSettings(initializationOptionsSettings);
ContentModelSettings cmSettings = ContentModelSettings
.getContentModelXMLSettings(initializationOptionsSettings);
if (cmSettings != null) {
updateSettings(cmSettings, saveContext);
}
contentModelManager.setSettings(cmSettings);
}

private void updateSettings(ContentModelSettings settings, ISaveContext context) {
Expand All @@ -99,8 +98,7 @@ private void updateSettings(ContentModelSettings settings, ISaveContext context)
}
if (settings.getFileAssociations() != null) {
// Update XML file associations
boolean fileAssociationsChanged = contentModelManager
.setFileAssociations(settings.getFileAssociations());
boolean fileAssociationsChanged = contentModelManager.setFileAssociations(settings.getFileAssociations());
if (fileAssociationsChanged) {
// Validate all opened XML files
context.collectDocumentToValidate(d -> {
Expand All @@ -119,6 +117,7 @@ private void updateSettings(ContentModelSettings settings, ISaveContext context)

@Override
public void start(InitializeParams params, XMLExtensionsRegistry registry) {
diagnosticsParticipant = new ContentModelDiagnosticsParticipant(registry);
URIResolverExtensionManager resolverManager = registry.getComponent(URIResolverExtensionManager.class);
contentModelManager = new ContentModelManager(resolverManager);
registry.registerComponent(contentModelManager);
Expand All @@ -140,8 +139,4 @@ public void stop(XMLExtensionsRegistry registry) {
registry.unregisterCodeActionParticipant(codeActionParticipant);
registry.unregisterDocumentLinkParticipant(documentLinkParticipant);
}

public ContentModelSettings getContentModelSettings() {
return cmSettings;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.dom.DOMElement;
import org.eclipse.lsp4xml.extensions.contentmodel.settings.ContentModelSettings;
import org.eclipse.lsp4xml.extensions.contentmodel.settings.XMLFileAssociation;
import org.eclipse.lsp4xml.extensions.contentmodel.uriresolver.XMLCacheResolverExtension;
import org.eclipse.lsp4xml.extensions.contentmodel.uriresolver.XMLCatalogResolverExtension;
Expand All @@ -42,6 +43,8 @@ public class ContentModelManager {
private final XMLCatalogResolverExtension catalogResolverExtension;
private final XMLFileAssociationResolverExtension fileAssociationResolver;

private ContentModelSettings settings;

public ContentModelManager(URIResolverExtensionManager resolverManager) {
this.resolverManager = resolverManager;
modelProviders = new ArrayList<>();
Expand All @@ -56,6 +59,14 @@ public ContentModelManager(URIResolverExtensionManager resolverManager) {
setUseCache(true);
}

public void setSettings(ContentModelSettings settings) {
this.settings = settings;
}

public ContentModelSettings getSettings() {
return settings;
}

public CMElementDeclaration findCMElement(DOMElement element) throws Exception {
return findCMElement(element, element.getNamespaceURI());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4xml.dom.DOMDocument;
import org.eclipse.lsp4xml.extensions.contentmodel.ContentModelPlugin;
import org.eclipse.lsp4xml.extensions.contentmodel.model.ContentModelManager;
import org.eclipse.lsp4xml.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lsp4xml.services.extensions.diagnostics.IDiagnosticsParticipant;
import org.eclipse.lsp4xml.utils.DOMUtils;

Expand All @@ -26,11 +27,10 @@
*
*/
public class ContentModelDiagnosticsParticipant implements IDiagnosticsParticipant {
private final XMLExtensionsRegistry registry;

private final ContentModelPlugin contentModelPlugin;

public ContentModelDiagnosticsParticipant(ContentModelPlugin contentModelPlugin) {
this.contentModelPlugin = contentModelPlugin;
public ContentModelDiagnosticsParticipant(XMLExtensionsRegistry registry) {
this.registry = registry;
}

@Override
Expand All @@ -43,8 +43,8 @@ public void doDiagnostics(DOMDocument xmlDocument, List<Diagnostic> diagnostics,
// associations settings., ...)
XMLEntityResolver entityResolver = xmlDocument.getResolverExtensionManager();
// Process validation
XMLValidator.doDiagnostics(xmlDocument, entityResolver, diagnostics,
contentModelPlugin.getContentModelSettings(), monitor);
ContentModelManager manager = registry.getComponent(ContentModelManager.class);
XMLValidator.doDiagnostics(xmlDocument, entityResolver, diagnostics, manager.getSettings(), monitor);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2019 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.lsp4xml.extensions.contentmodel.participants.diagnostics;

import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.xs.XMLSchemaValidator;
import org.apache.xerces.parsers.XIncludeAwareParserConfiguration;

/**
* Custom Xerces configuration to configure XSD version.
*
*/
class LSPXMLParserConfiguration extends XIncludeAwareParserConfiguration {

private static final String XML_SCHEMA_VERSION = Constants.XERCES_PROPERTY_PREFIX
+ Constants.XML_SCHEMA_VERSION_PROPERTY;

private static final String SCHEMA_VALIDATOR = Constants.XERCES_PROPERTY_PREFIX
+ Constants.SCHEMA_VALIDATOR_PROPERTY;

private final String namespaceSchemaVersion;

public LSPXMLParserConfiguration(String namespaceSchemaVersion) {
this.namespaceSchemaVersion = namespaceSchemaVersion;
}

@Override
protected void configurePipeline() {
super.configurePipeline();
configureSchemaVersion();
}

@Override
protected void configureXML11Pipeline() {
super.configureXML11Pipeline();
configureSchemaVersion();
}

private void configureSchemaVersion() {
if (namespaceSchemaVersion != null) {
XMLSchemaValidator validator = (XMLSchemaValidator) super.getProperty(SCHEMA_VALIDATOR);
if (validator != null) {
validator.setProperty(XML_SCHEMA_VERSION, namespaceSchemaVersion);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

import org.apache.xerces.impl.XMLEntityManager;
import org.apache.xerces.parsers.SAXParser;
import org.apache.xerces.parsers.XIncludeAwareParserConfiguration;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLInputSource;
Expand Down Expand Up @@ -59,15 +58,17 @@ public class XMLValidator {
private static final String DTD_NOT_FOUND = "Cannot find DTD ''{0}''.\nCreate the DTD file or configure an XML catalog for this DTD.";

public static void doDiagnostics(DOMDocument document, XMLEntityResolver entityResolver,
List<Diagnostic> diagnostics, ContentModelSettings contentModelSettings, CancelChecker monitor) {
List<Diagnostic> diagnostics, ContentModelSettings settings, CancelChecker monitor) {
try {
// it should be better to cache XML Schema with XMLGrammarCachingConfiguration,
// It should be better to cache XML Schema with XMLGrammarCachingConfiguration,
// but we cannot use
// XMLGrammarCachingConfiguration because cache is done with target namespaces.
// There are conflicts when
// 2 XML Schemas don't define target namespaces.
XMLParserConfiguration configuration = new XIncludeAwareParserConfiguration(); // new
// XMLGrammarCachingConfiguration();

// Configure the XSD schema version
String namespaceSchemaVersion = XMLValidationSettings.getNamespaceSchemaVersion(settings);
XMLParserConfiguration configuration = new LSPXMLParserConfiguration(namespaceSchemaVersion); // XMLGrammarCachingConfiguration();

if (entityResolver != null) {
configuration.setProperty("http://apache.org/xml/properties/internal/entity-resolver", entityResolver); //$NON-NLS-1$
Expand All @@ -89,17 +90,15 @@ public static void doDiagnostics(DOMDocument document, XMLEntityResolver entityR
boolean hasGrammar = document.hasGrammar();

// If diagnostics for Schema preference is enabled
XMLValidationSettings validationSettings = contentModelSettings != null
? contentModelSettings.getValidation()
: null;
XMLValidationSettings validationSettings = settings != null ? settings.getValidation() : null;
if ((validationSettings == null) || validationSettings.isSchema()) {

checkExternalSchema(document.getExternalSchemaLocation(), parser);

parser.setFeature("http://apache.org/xml/features/validation/schema", hasGrammar); //$NON-NLS-1$

// warn if XML document is not bound to a grammar according the settings
warnNoGrammar(document, diagnostics, contentModelSettings);
warnNoGrammar(document, diagnostics, settings);
} else {
hasGrammar = false; // validation for Schema was disabled
}
Expand Down Expand Up @@ -143,7 +142,7 @@ private static boolean checkExternalDTD(DOMDocument document, LSPErrorReporterFo
if (docType.getKindNode() == null) {
return true;
}

// When XML is bound with a DTD path which doesn't exist, Xerces throws an
// IOException which breaks the validation of XML syntax instead of reporting it
// (like XML Schema). Here we parse only the
Expand All @@ -154,12 +153,10 @@ private static boolean checkExternalDTD(DOMDocument document, LSPErrorReporterFo
// of DTD for validation)

// Parse only the DOCTYPE of the DOM document

int end = document.getDoctype().getEnd();
String xml = document.getText().substring(0, end);
xml += "<root/>";
try {

// Customize the entity manager to collect the error when DTD doesn't exist.
XMLEntityManager entityManager = new XMLEntityManager() {
@Override
Expand All @@ -185,7 +182,7 @@ public String setupCurrentEntity(String name, XMLInputSource xmlInputSource, boo
}
};
entityManager.reset(configuration);

SAXParser parser = new SAXParser(configuration);
parser.setProperty("http://apache.org/xml/properties/internal/entity-manager", entityManager);
InputSource inputSource = new InputSource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,37 @@

package org.eclipse.lsp4xml.extensions.contentmodel.settings;

import org.apache.xerces.impl.Constants;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4xml.utils.StringUtils;

/**
* XMLValidationSettings
*/
public class XMLValidationSettings {

public enum SchemaVersion {

V10("1.0"), V11("1.1"), V10EX("1.0EX");

private final String version;

private SchemaVersion(String version) {
this.version = version;
}

public String getVersion() {
return version;
}

}

private Boolean schema;

private Boolean enabled;

private String schemaVersion;

/**
* This severity preference to mark the root element of XML document which is
* not bound to a XML Schema/DTD.
Expand All @@ -31,7 +51,7 @@ public class XMLValidationSettings {
private String noGrammar;

public XMLValidationSettings() {
//set defaults
// set defaults
schema = true;
enabled = true;
}
Expand Down Expand Up @@ -64,6 +84,30 @@ public void setSchema(boolean schema) {
this.schema = schema;
}

/**
* Returns the schema version.
*
* <p>
* Supported version by Xerces are 1.0, 1.1 and 1.0EX.
* </p>
*
* @see https://github.com/apache/xerces2-j/blob/xml-schema-1.1-dev/src/org/apache/xerces/impl/Constants.java#L42
*
* @return the schema version
*/
public String getSchemaVersion() {
return schemaVersion;
}

/**
* Set the schema version
*
* @param schemaVersion the schema version
*/
public void setSchemaVersion(String schemaVersion) {
this.schemaVersion = schemaVersion;
}

public void setNoGrammar(String noGrammar) {
this.noGrammar = noGrammar;
}
Expand Down Expand Up @@ -100,12 +144,35 @@ public static DiagnosticSeverity getNoGrammarSeverity(ContentModelSettings setti
return defaultSeverity;
}

/**
* Returns the Xerces namespace of the schema version to use and 1.0 otherwise.
*
* @param settings the settings
* @return the Xerces namespace of the schema version to use and 1.0 otherwise.
*/
public static String getNamespaceSchemaVersion(ContentModelSettings settings) {
if (settings == null || settings.getValidation() == null) {
return Constants.W3C_XML_SCHEMA10_NS_URI;
}
String schemaVersion = settings.getValidation().getSchemaVersion();
if (StringUtils.isEmpty(schemaVersion)) {
return Constants.W3C_XML_SCHEMA10_NS_URI;
}
if (SchemaVersion.V11.getVersion().equals(schemaVersion)) {
return Constants.W3C_XML_SCHEMA11_NS_URI;
}
if (SchemaVersion.V10EX.getVersion().equals(schemaVersion)) {
return Constants.W3C_XML_SCHEMA10EX_NS_URI;
}
return Constants.W3C_XML_SCHEMA10_NS_URI;
}

public XMLValidationSettings merge(XMLValidationSettings settings) {
if(settings != null) {
if (settings != null) {
this.schema = settings.schema;
this.enabled = settings.enabled;
}
return this;
}

}
Loading

0 comments on commit 2ee7159

Please sign in to comment.