matthiasblaesing commented on PR #6160: URL: https://github.com/apache/netbeans/pull/6160#issuecomment-1634748996
@asbachb as I feared, in offline mode this was problematic. I removed the `jsf-impl` artifact from the local repository and cut the network connections. I got two error cases: **The first issue** is, that the check if the maven artifact is present is not correct/incomplete. The maven resolver gives back a path, but the path point to a non-existing file. I got this exception: <details> <summary>Exception</summary> ``` WARNING [org.netbeans.modules.csl.editor.semantic.SemanticHighlighter]: SemanticAnalyzer = org.netbeans.modules.html.editor.gsf.HtmlSemanticAnalyzer@13bbb006; Language = org.netbeans.modules.csl.core.Language@541b0c9[text/html (mimetype = text/html; ParserResult = org.netbeans.modules.html.editor.api.gsf.HtmlParserResult$Lkp@66b7c8cd(mimepath = MimePath[text/xhtml/text/html]) java.lang.NullPointerException: Cannot invoke "org.openide.filesystems.FileObject.isValid()" because "fo" is null at org.openide.filesystems.JarArchiveRootProvider.isArchiveFile(JarArchiveRootProvider.java:72) at org.openide.filesystems.FileUtil.getArchiveRoot(FileUtil.java:1918) at org.netbeans.modules.web.jsf.editor.facelets.DefaultFaceletLibraries.init(DefaultFaceletLibraries.java:80) at org.netbeans.modules.web.jsf.editor.facelets.DefaultFaceletLibraries.<init>(DefaultFaceletLibraries.java:67) at org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport.parseLibraries(FaceletsLibrarySupport.java:368) at org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport._findLibraries(FaceletsLibrarySupport.java:327) at org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport.findLibraries(FaceletsLibrarySupport.java:272) at org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport.getNamespaceLibraryMapping(FaceletsLibrarySupport.java:175) at org.netbeans.modules.web.jsf.editor.JsfSupportImpl.getLibrary(JsfSupportImpl.java:224) at org.netbeans.modules.web.jsf.editor.JsfPageMetadataProvider.getMetadataMap(JsfPageMetadataProvider.java:74) at org.netbeans.modules.web.common.api.WebPageMetadata.getMetadata(WebPageMetadata.java:54) at org.netbeans.modules.web.common.api.WebPageMetadata.getMetadata(WebPageMetadata.java:113) at org.netbeans.modules.web.common.api.WebPageMetadata.getContentMimeType(WebPageMetadata.java:87) at org.netbeans.modules.html.editor.gsf.HtmlSemanticAnalyzer.run(HtmlSemanticAnalyzer.java:60) ``` </details> I suggest to adjust the contract of the provider to require the provider to only return valid paths. <details> <summary>Suggested fix</summary> ```diff --- a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/spi/JsfReferenceImplementationProvider.java +++ b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/spi/JsfReferenceImplementationProvider.java @@ -27,5 +27,11 @@ */ public interface JsfReferenceImplementationProvider { + /** + * Determine the path to the JSF reference implementation JAR. + * + * @param jsfVersion + * @return path to the JAR or {@code null} if not found + */ Path artifactPathFor(JsfVersion jsfVersion); } --- a/enterprise/maven.j2ee/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProvider.java +++ b/enterprise/maven.j2ee/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProvider.java @@ -18,11 +18,12 @@ */ package org.netbeans.modules.maven.j2ee; +import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collections; import java.util.EnumMap; import java.util.Map; +import java.util.Optional; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; @@ -82,6 +83,10 @@ return null; } - return Paths.get(jsfRIArtifact.getFile().toURI()); + return Optional.ofNullable(jsfRIArtifact) + .map(artifact -> artifact.getFile()) + .map(file -> file.toPath()) + .filter(file -> Files.exists(file)) + .orElse(null); } } ``` </details> **The second issue** is that the schemas in the reference implementation JARs are not optimal. They contain this: ```xml <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/> ``` The schema parse will then try to load the XSD from network. This is a privacy and performance problem. NetBeans has a solution for this: We carry the schemas and can use the NetBeans `UserCatalog` to resolve them. In offline mode I see an exception: <details> <summary>Exception</summary> ``` INFO [null]: Error parsing facelets library descriptor org.xml.sax.SAXParseException; systemId: jar:file:/home/matthias/src/netbeans/nbbuild/netbeans/enterprise/modules/ext/jsf-2_2/javax.faces.jar!/com/sun/faces/javaee_5.xsd; lineNumber: 182; columnNumber: 33; src-resolve: Name 'xml:lang' kann nicht als 'attribute declaration'-Komponente aufgelöst werden. at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204) at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:135) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:396) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:4254) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:4237) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl(XSDHandler.java:1728) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDAttributeTraverser.traverseLocal(XSDAttributeTraverser.java:90) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDAbstractTraverser.traverseAttrsAndAttrGrps(XSDAbstractTraverser.java:760) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDComplexTypeTraverser.traverseSimpleContent(XSDComplexTypeTraverser.java:656) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDComplexTypeTraverser.traverseComplexTypeDecl(XSDComplexTypeTraverser.java:304) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDComplexTypeTraverser.traverseGlobal(XSDComplexTypeTraverser.java:191) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.traverseSchemas(XSDHandler.java:1480) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:663) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:618) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:577) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:543) at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:281) at java.xml/javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:612) at java.xml/javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:644) at org.netbeans.modules.web.jsf.editor.facelets.mojarra.ConfigManager$ParseTask.getSchema(ConfigManager.java:1216) at org.netbeans.modules.web.jsf.editor.facelets.mojarra.ConfigManager$ParseTask.getDocument(ConfigManager.java:1140) at org.netbeans.modules.web.jsf.editor.facelets.mojarra.ConfigManager$ParseTask.call(ConfigManager.java:1045) Caused: com.sun.faces.config.ConfigurationException: Unable to parse document 'jar:file:/home/matthias/.m2/repository/org/primefaces/primefaces/11.0.0/primefaces-11.0.0.jar!/META-INF/primefaces-p.taglib.xml': src-resolve: Name 'xml:lang' kann nicht als 'attribute declaration'-Komponente aufgelöst werden. at org.netbeans.modules.web.jsf.editor.facelets.mojarra.ConfigManager$ParseTask.call(ConfigManager.java:1054) at org.netbeans.modules.web.jsf.editor.facelets.mojarra.ConfigManager$ParseTask.call(ConfigManager.java:971) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at org.netbeans.modules.web.jsf.editor.facelets.mojarra.ConfigManager.getConfigDocuments(ConfigManager.java:775) Caused: java.util.concurrent.ExecutionException at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) [catch] at org.netbeans.modules.web.jsf.editor.facelets.mojarra.ConfigManager.getConfigDocuments(ConfigManager.java:792) at org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport.parseLibraries(FaceletsLibrarySupport.java:408) at org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport._findLibraries(FaceletsLibrarySupport.java:327) at org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport.findLibraries(FaceletsLibrarySupport.java:272) at org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport.getNamespaceLibraryMapping(FaceletsLibrarySupport.java:175) at org.netbeans.modules.web.jsf.editor.JsfSupportImpl.getLibrary(JsfSupportImpl.java:224) at org.netbeans.modules.web.jsf.editor.JsfPageMetadataProvider.getMetadataMap(JsfPageMetadataProvider.java:74) at org.netbeans.modules.web.common.api.WebPageMetadata.getMetadata(WebPageMetadata.java:54) at org.netbeans.modules.web.common.api.WebPageMetadata.getMetadata(WebPageMetadata.java:113) at org.netbeans.modules.web.common.api.WebPageMetadata.getContentMimeType(WebPageMetadata.java:87) at org.netbeans.modules.html.editor.gsf.HtmlSemanticAnalyzer.run(HtmlSemanticAnalyzer.java:60) at org.netbeans.modules.csl.editor.semantic.SemanticHighlighter.process(SemanticHighlighter.java:278) at org.netbeans.modules.csl.editor.semantic.SemanticHighlighter.access$000(SemanticHighlighter.java:57) at org.netbeans.modules.csl.editor.semantic.SemanticHighlighter$1.run(SemanticHighlighter.java:108) at org.netbeans.modules.csl.editor.semantic.SemanticHighlighter$1.run(SemanticHighlighter.java:117) at org.netbeans.modules.parsing.impl.TaskProcessor.callUserTask(TaskProcessor.java:586) at org.netbeans.modules.parsing.api.ParserManager$UserTaskAction.run(ParserManager.java:132) at org.netbeans.modules.parsing.api.ParserManager$UserTaskAction.run(ParserManager.java:116) at org.netbeans.modules.parsing.impl.TaskProcessor$2.call(TaskProcessor.java:181) at org.netbeans.modules.parsing.impl.TaskProcessor$2.call(TaskProcessor.java:178) at org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager.priorityIO(FileChangedManager.java:153) at org.netbeans.modules.masterfs.providers.ProvidedExtensions.priorityIO(ProvidedExtensions.java:335) at org.netbeans.modules.parsing.nb.DataObjectEnvFactory.runPriorityIO(DataObjectEnvFactory.java:118) at org.netbeans.modules.parsing.impl.Utilities.runPriorityIO(Utilities.java:67) at org.netbeans.modules.parsing.impl.TaskProcessor.runUserTask(TaskProcessor.java:178) at org.netbeans.modules.parsing.api.ParserManager.parse(ParserManager.java:83) at org.netbeans.modules.csl.editor.semantic.SemanticHighlighter.run(SemanticHighlighter.java:98) at org.netbeans.modules.csl.editor.semantic.SemanticHighlighter.run(SemanticHighlighter.java:57) at org.netbeans.modules.parsing.impl.TaskProcessor.callParserResultTask(TaskProcessor.java:561) at org.netbeans.modules.parsing.impl.TaskProcessor$RequestPerformer.run(TaskProcessor.java:786) at org.openide.util.lookup.Lookups.executeWith(Lookups.java:288) at org.netbeans.modules.parsing.impl.TaskProcessor$RequestPerformer.execute(TaskProcessor.java:702) at org.netbeans.modules.parsing.impl.TaskProcessor$CompilationJob.run(TaskProcessor.java:663) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1419) at org.netbeans.modules.openide.util.GlobalLookup.execute(GlobalLookup.java:45) at org.openide.util.lookup.Lookups.executeWith(Lookups.java:287) at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2034) INFO [null]: Error parsing facelets library descriptor ``` </details> <details> <summary>Suggested fix</summary> ```diff # This patch file was generated by NetBeans IDE # It uses platform neutral UTF-8 encoding and \n newlines. --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/mojarra/ConfigManager.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/mojarra/ConfigManager.java @@ -68,6 +68,8 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.Reader; +import java.io.StringWriter; import java.lang.annotation.Annotation; import java.lang.ref.WeakReference; import java.net.MalformedURLException; @@ -120,9 +122,13 @@ import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; +import org.netbeans.api.xml.services.UserCatalog; import org.netbeans.modules.web.jsf.editor.facelets.DefaultFaceletLibraries; import org.netbeans.modules.web.jsfapi.api.JsfNamespaces; +import org.openide.util.Exceptions; import org.w3c.dom.*; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; @@ -1180,6 +1186,31 @@ WeakReference<Schema> schema = SCHEMA_CACHE.get(id); if (schema == null || schema.get() == null) { SchemaFactory schemaFactory = SchemaFactory.newDefaultInstance(); + schemaFactory.setResourceResolver(new LSResourceResolver() { + @Override + public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { + try { + InputSource is = UserCatalog.getDefault(). + getEntityResolver(). + resolveEntity(publicId, systemId); + if (is != null) { + return new LSInputFromInputSource(is); + } + } catch (SAXException | IOException ex) { + LOGGER.log( + Level.FINE, + "Failed to resolve namespaceURI: {}, publicId: {}, systemId: {}, baseURI: {}", + new Object[] { + namespaceURI, + publicId, + systemId, + baseURI + } + ); + } + return null; + } + }); schema = new WeakReference<>(schemaFactory.newSchema(jsfRIClassLoader.getResource(schemaResourceName))); SCHEMA_CACHE.put(id, schema); @@ -1345,4 +1376,96 @@ } // END URITask + /** + * Helperclass to supply the SchemaFactory with XSDs from the NB catalog + */ + private static class LSInputFromInputSource implements LSInput { + + private final InputSource is; + + public LSInputFromInputSource(InputSource is) { + this.is = is; + } + + @Override + public Reader getCharacterStream() { + return is.getCharacterStream(); + } + + @Override + public void setCharacterStream(Reader characterStream) { + } + + @Override + public InputStream getByteStream() { + return is.getByteStream(); + } + + @Override + public void setByteStream(InputStream byteStream) { + } + + @Override + public String getStringData() { + try (Reader r = getCharacterStream()) { + if (r == null) { + return null; + } + StringWriter sw = new StringWriter(); + getCharacterStream().transferTo(sw); + return sw.toString(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void setStringData(String stringData) { + } + + @Override + public String getSystemId() { + return is.getSystemId(); + } + + @Override + public void setSystemId(String systemId) { + } + + @Override + public String getPublicId() { + return is.getPublicId(); + } + + @Override + public void setPublicId(String publicId) { + } + + @Override + public String getBaseURI() { + return ""; + } + + @Override + public void setBaseURI(String baseURI) { + } + + @Override + public String getEncoding() { + return is.getEncoding(); + } + + @Override + public void setEncoding(String encoding) { + } + + @Override + public boolean getCertifiedText() { + return false; + } + + @Override + public void setCertifiedText(boolean certifiedText) { + } + } } ``` </details> -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@netbeans.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@netbeans.apache.org For additional commands, e-mail: notifications-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists