Skip to content

Commit

Permalink
Use file temp to download XML Schema, DTD + add warning message when
Browse files Browse the repository at this point in the history
validation is done and XML Schema is downloading (see #159)
  • Loading branch information
angelozerr committed Oct 19, 2018
1 parent 2bbe54b commit 6f50788
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.CompletionParams;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.DidCloseTextDocumentParams;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
Expand All @@ -47,6 +48,7 @@
import org.eclipse.lsp4j.FoldingRangeRequestParams;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.RenameParams;
import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.TextDocumentClientCapabilities;
Expand All @@ -61,11 +63,14 @@
import org.eclipse.lsp4xml.commons.LanguageModelCache;
import org.eclipse.lsp4xml.commons.TextDocument;
import org.eclipse.lsp4xml.commons.TextDocuments;
import org.eclipse.lsp4xml.dom.Element;
import org.eclipse.lsp4xml.dom.XMLDocument;
import org.eclipse.lsp4xml.dom.XMLParser;
import org.eclipse.lsp4xml.services.XMLLanguageService;
import org.eclipse.lsp4xml.services.extensions.CompletionSettings;
import org.eclipse.lsp4xml.settings.XMLFormattingOptions;
import org.eclipse.lsp4xml.uriresolver.CacheResourceDownloadingException;
import org.eclipse.lsp4xml.utils.XMLPositionUtility;

/**
* XML text document service.
Expand Down Expand Up @@ -302,10 +307,25 @@ private void triggerValidation(String uri, int version, BasicCancelChecker monit
TextDocument currDocument = getDocument(uri);
if (currDocument != null && currDocument.getVersion() == version) {
XMLDocument xmlDocument = getXMLDocument(currDocument);
List<Diagnostic> diagnostics = getXMLLanguageService().doDiagnostics(xmlDocument, monitor);
monitor.checkCanceled();
xmlLanguageServer.getLanguageClient()
.publishDiagnostics(new PublishDiagnosticsParams(uri, diagnostics));
try {
List<Diagnostic> diagnostics = getXMLLanguageService().doDiagnostics(xmlDocument, monitor);
monitor.checkCanceled();
xmlLanguageServer.getLanguageClient()
.publishDiagnostics(new PublishDiagnosticsParams(uri, diagnostics));
} catch (CacheResourceDownloadingException e) {
// An XML Schema, DTD is downloading with cache, but it takes too time. In this
// case:
// - 1) we add a warning in the document element to tell that validation cannot be
// occurred because an XML Schema/DTD is downloading.
Element documentElement = xmlDocument.getDocumentElement();
Range range = XMLPositionUtility.selectStartTag(documentElement);
List<Diagnostic> diagnostics = new ArrayList<>();
diagnostics.add(new Diagnostic(range, e.getMessage(), DiagnosticSeverity.Warning, "XML"));
xmlLanguageServer.getLanguageClient()
.publishDiagnostics(new PublishDiagnosticsParams(uri, diagnostics));
// - 2) we restart the validation only when the XML Schema, DTD is downloaded.
e.getFuture().thenAccept((path) -> triggerValidation(uri, version, monitor));
}
}
}, 500, TimeUnit.MILLISECONDS);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.eclipse.lsp4xml.extensions.contentmodel.uriresolver.XMLCatalogResolverExtension;
import org.eclipse.lsp4xml.extensions.contentmodel.uriresolver.XMLFileAssociationResolverExtension;
import org.eclipse.lsp4xml.extensions.contentmodel.xsd.XSDDocument;
import org.eclipse.lsp4xml.uriresolver.CacheResourceLoadingException;
import org.eclipse.lsp4xml.uriresolver.CacheResourceDownloadingException;
import org.eclipse.lsp4xml.uriresolver.URIResolverExtensionManager;
import org.w3c.dom.DOMError;
import org.w3c.dom.DOMErrorHandler;
Expand Down Expand Up @@ -63,8 +63,8 @@ public ContentModelManager() {

@Override
public boolean handleError(DOMError error) {
if (error.getRelatedException() instanceof CacheResourceLoadingException) {
throw ((CacheResourceLoadingException) error.getRelatedException());
if (error.getRelatedException() instanceof CacheResourceDownloadingException) {
throw ((CacheResourceDownloadingException) error.getRelatedException());
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import org.eclipse.lsp4xml.services.extensions.CompletionParticipantAdapter;
import org.eclipse.lsp4xml.services.extensions.ICompletionRequest;
import org.eclipse.lsp4xml.services.extensions.ICompletionResponse;
import org.eclipse.lsp4xml.uriresolver.CacheResourceLoadingException;
import org.eclipse.lsp4xml.uriresolver.CacheResourceDownloadingException;

/**
* Extension to support XML completion based on content model (XML Schema
Expand Down Expand Up @@ -70,7 +70,7 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response)
}
}
}
} catch (CacheResourceLoadingException e) {
} catch (CacheResourceDownloadingException e) {
addCacheWarningItem(e, response);
}
}
Expand Down Expand Up @@ -146,7 +146,7 @@ public void onAttributeName(boolean generateValue, Range fullRange, ICompletionR
}
}
}
} catch (CacheResourceLoadingException e) {
} catch (CacheResourceDownloadingException e) {
addCacheWarningItem(e, response);
}
}
Expand All @@ -172,12 +172,12 @@ public void onAttributeValue(String valuePrefix, Range fullRange, boolean addQuo
});
}
}
} catch (CacheResourceLoadingException e) {
} catch (CacheResourceDownloadingException e) {
addCacheWarningItem(e, response);
}
}

private void addCacheWarningItem(CacheResourceLoadingException e, ICompletionResponse response) {
private void addCacheWarningItem(CacheResourceDownloadingException e, ICompletionResponse response) {
// Here cache is enabled and some XML Schema, DTD, etc are loading
CompletionItem item = new CompletionItem(
"Cannot process " + (e.isDTD() ? "DTD" : "XML Schema") + " completion: " + e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import org.eclipse.lsp4xml.extensions.contentmodel.model.ContentModelManager;
import org.eclipse.lsp4xml.services.extensions.HoverParticipantAdapter;
import org.eclipse.lsp4xml.services.extensions.IHoverRequest;
import org.eclipse.lsp4xml.uriresolver.CacheResourceLoadingException;
import org.eclipse.lsp4xml.uriresolver.CacheResourceDownloadingException;

/**
* Extension to support XML hover based on content model (XML Schema completion,
Expand All @@ -42,7 +42,7 @@ public Hover onTag(IHoverRequest hoverRequest) throws Exception {
return new Hover(content, hoverRequest.getTagRange());
}
}
} catch (CacheResourceLoadingException e) {
} catch (CacheResourceDownloadingException e) {
return getCacheWarningHover(e);
}
return null;
Expand All @@ -67,13 +67,13 @@ public Hover onAttributeName(IHoverRequest hoverRequest) throws Exception {
}
}
}
} catch (CacheResourceLoadingException e) {
} catch (CacheResourceDownloadingException e) {
return getCacheWarningHover(e);
}
return null;
}

private Hover getCacheWarningHover(CacheResourceLoadingException e) {
private Hover getCacheWarningHover(CacheResourceDownloadingException e) {
// Here cache is enabled and some XML Schema, DTD, etc are loading
MarkupContent content = new MarkupContent();
content.setKind(MarkupKind.PLAINTEXT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4xml.dom.XMLDocument;
import org.eclipse.lsp4xml.uriresolver.CacheResourceLoadingException;
import org.eclipse.lsp4xml.uriresolver.CacheResourceDownloadingException;
import org.eclipse.lsp4xml.uriresolver.IExternalSchemaLocationProvider;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
Expand Down Expand Up @@ -79,8 +79,10 @@ public static void doDiagnostics(XMLDocument document, XMLEntityResolver entityR
inputSource.setSystemId(uri);
reader.parse(inputSource);

} catch (IOException | SAXException | CancellationException | CacheResourceLoadingException exception) {
} catch (IOException | SAXException | CancellationException exception) {
// ignore error
} catch(CacheResourceDownloadingException e) {
throw e;
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Unexpected XMLValidator error", e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/**
* Copyright (c) 2018 Angelo ZERR
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Angelo Zerr <[email protected]> - initial API and implementation
*/
package org.eclipse.lsp4xml.extensions.contentmodel.uriresolver;

import java.io.IOException;
Expand All @@ -10,19 +20,32 @@
import org.eclipse.lsp4xml.uriresolver.CacheResourcesManager;
import org.eclipse.lsp4xml.uriresolver.URIResolverExtension;

/**
* URI resolver which download the first time the XML Schema, DTD from "http" or
* "ftp" in the file system. The second time, teh downloaded file is used
* instead of accessing from "http" or "ftp". This cache improves drastically
* the performance of some XML Schema (ex: xml.xsd)
*
*/
public class XMLCacheResolverExtension implements URIResolverExtension {

@Override
public String resolve(String baseLocation, String publicId, String systemId) {
// Don't resolve the URI
return null;
}

@Override
public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) throws XNIException, IOException {
String url = resourceIdentifier.getExpandedSystemId();
// Cache is used only for resource coming from "http" or "ftp".
if (CacheResourcesManager.getInstance().canUseCache(url)) {
Path file = CacheResourcesManager.getInstance().getResources(url);
// Try to get the downloaded resource. In the case of the resource is
// downloading and takes so many time,
// the exception CacheResourceDownloadingException is thrown.
Path file = CacheResourcesManager.getInstance().getResource(url);
if (file != null) {
// The resource is downloaded in the file system, use it.
XMLInputSource source = new XMLInputSource(resourceIdentifier);
source.setByteStream(Files.newInputStream(file));
return source;
Expand All @@ -31,6 +54,11 @@ public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) th
return null;
}

/**
* Set true if cache must be used and false otherwise.
*
* @param useCache true if cache must be used and false otherwise.
*/
public void setUseCache(boolean useCache) {
CacheResourcesManager.getInstance().setUseCache(useCache);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright (c) 2018 Angelo ZERR
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Angelo Zerr <[email protected]> - initial API and implementation
*/
package org.eclipse.lsp4xml.uriresolver;

import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.concurrent.CompletableFuture;

/**
* Exception thrown when a resource (XML Schema, DTD) is downloading.
*
*/
public class CacheResourceDownloadingException extends RuntimeException {

private static final long serialVersionUID = 1L;

private static final String RESOURCE_LOADING_MSG = "The resource ''{0}'' is downloading.";

private final String resourceURI;

private final CompletableFuture<Path> future;

public CacheResourceDownloadingException(String resourceURI, CompletableFuture<Path> future) {
super(MessageFormat.format(RESOURCE_LOADING_MSG, resourceURI));
this.resourceURI = resourceURI;
this.future = future;
}

/**
* Returns the resource URI which is downloading.
*
* @return the resource URI which is downloading.
*/
public String getResourceURI() {
return resourceURI;
}

/**
* Returns true if it's a DTD which id downloading and false otherwise.
*
* @return true if it's a DTD which id downloading and false otherwise.
*/
public boolean isDTD() {
return resourceURI != null && resourceURI.endsWith(".dtd");
}

public CompletableFuture<Path> getFuture() {
return future;
}
}

This file was deleted.

Loading

0 comments on commit 6f50788

Please sign in to comment.