From 69d750b1db2baf952e7fab3b4f4b1e502214c36c Mon Sep 17 00:00:00 2001 From: Benjamin Asbach Date: Mon, 3 Jul 2023 02:35:54 +0800 Subject: [PATCH] Feature: Added support for JSF 4.0 namespaces Previously NetBeans bundles the JSF reference implementation Mojarra in order to provide several functionality (like namespaces) based on the parsed taglib xml files from that jar. This is somehow problematic as: 1) The dependency needs to be updated on every new JSF release 2) NetBeans needs to fulfil the expectations of Mojarra This leads to the problem that we currently cannot update and bundle the latest Mojarra version as Java 11 is required. This change wants to get less dependant on that bundled JSF implementation by resolving the reference implementation using maven. Instead of reading the taglib xml files from that bundled jar NetBeans now gets in from the local maven repository or downloads it from maven central. If this is not possible we fallback to the bundled version. This change also improves the situation when autosuggestion is invoked in the namespace part of JSF xhtml documents by ordering the suggested namespace with the one on top which is most likely to be used. --- enterprise/maven.j2ee/nbproject/project.xml | 4 +- ...venJsfReferenceImplementationProvider.java | 91 +++++++ ...sfReferenceImplementationProviderTest.java | 45 ++++ .../web.bootsfaces/nbproject/project.xml | 4 +- .../modules/web/wizards/PageIterator.java | 9 +- enterprise/web.freeform/nbproject/project.xml | 4 +- enterprise/web.jsf.editor/manifest.mf | 2 +- .../web.jsf.editor/nbproject/project.xml | 8 +- .../jsf/editor/InjectCompositeComponent.java | 6 +- .../web/jsf/editor/JsfNavigationHelper.java | 2 +- .../web/jsf/editor/JsfSupportImpl.java | 4 +- .../modules/web/jsf/editor/JsfUtils.java | 12 +- .../actions/FixNamespacesPerformer.java | 2 +- .../web/jsf/editor/actions/ImportData.java | 1 - .../editor/actions/NamespaceProcessor.java | 16 -- .../JsfAttributesCompletionHelper.java | 66 +++-- .../editor/completion/JsfCompletionItem.java | 7 +- .../jsf/editor/el/JsfELVariableResolver.java | 18 +- .../web/jsf/editor/el/JsfVariablesModel.java | 2 +- .../facelets/AbstractFaceletsLibrary.java | 1 - .../facelets/CompositeComponentLibrary.java | 6 +- .../facelets/DefaultFaceletLibraries.java | 44 ++-- .../jsf/editor/facelets/FaceletsLibrary.java | 23 +- .../facelets/FaceletsLibrarySupport.java | 148 +++++++----- .../facelets/JarFileFaceletLibrary.java | 27 +++ .../facelets/JsfNamespaceComparator.java | 54 +++++ .../PureCompositeComponentLibrary.java | 4 +- .../facelets/mojarra/ConfigManager.java | 225 ++++++++++-------- .../FaceletsTaglibConfigProcessor.java | 30 ++- .../jsf/editor/hints/FixLibDeclaration.java | 13 +- .../hints/LibraryDeclarationChecker.java | 73 +++--- .../editor/index/CompositeComponentModel.java | 7 +- .../editor/index/ResourcesMappingModel.java | 8 +- .../facelets/FaceletsLibrarySupportTest.java | 9 +- .../web.jsf.icefaces/nbproject/project.xml | 8 +- enterprise/web.jsf.kit/nbproject/project.xml | 4 +- .../web.jsf.navigation/nbproject/project.xml | 4 +- .../web.jsf.richfaces/nbproject/project.xml | 8 +- enterprise/web.jsf/manifest.mf | 2 +- .../org-netbeans-modules-web-jsf.sig | 7 +- .../web.jsf/nbproject/project.properties | 2 +- enterprise/web.jsf/nbproject/project.xml | 4 +- .../editor/JsfFacesComponentsProvider.java | 5 +- .../templates/simpleFacelets.template | 7 +- .../palette/items/JsfLibrariesSupport.java | 22 +- .../web/jsf/palette/items/PrefixResolver.java | 2 +- .../wizards/TemplateClientPanelVisual.java | 36 ++- enterprise/web.jsf20/nbproject/project.xml | 4 +- enterprise/web.jsfapi/manifest.mf | 5 +- .../org-netbeans-modules-web-jsfapi.sig | 44 +++- .../web/jsfapi/api/DefaultLibraryInfo.java | 139 ++++++++--- .../modules/web/jsfapi/api/JsfNamespaces.java | 69 ++++++ .../modules/web/jsfapi/api/LibraryInfo.java | 11 +- .../web/jsfapi/api/NamespaceUtils.java | 63 ++--- .../JsfReferenceImplementationProvider.java | 31 +++ .../modules/web/jsfapi/spi/LibraryUtils.java | 39 ++- .../web.primefaces/nbproject/project.xml | 8 +- .../api/completion/HtmlCompletionItem.java | 20 +- 58 files changed, 1016 insertions(+), 503 deletions(-) create mode 100644 enterprise/maven.j2ee/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProvider.java create mode 100644 enterprise/maven.j2ee/test/unit/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProviderTest.java create mode 100644 enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/JarFileFaceletLibrary.java create mode 100644 enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/JsfNamespaceComparator.java create mode 100644 enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/JsfNamespaces.java create mode 100644 enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/spi/JsfReferenceImplementationProvider.java diff --git a/enterprise/maven.j2ee/nbproject/project.xml b/enterprise/maven.j2ee/nbproject/project.xml index 9fde5ea0bf09..abc3f913c338 100644 --- a/enterprise/maven.j2ee/nbproject/project.xml +++ b/enterprise/maven.j2ee/nbproject/project.xml @@ -376,8 +376,8 @@ - 0-1 - 1.13 + 2 + 2.0 diff --git a/enterprise/maven.j2ee/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProvider.java b/enterprise/maven.j2ee/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProvider.java new file mode 100644 index 000000000000..8bb9feb37e0f --- /dev/null +++ b/enterprise/maven.j2ee/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProvider.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.maven.j2ee; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.EnumMap; +import java.util.Map; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import static org.apache.maven.repository.RepositorySystem.DEFAULT_REMOTE_REPO_ID; +import static org.apache.maven.repository.RepositorySystem.DEFAULT_REMOTE_REPO_URL; +import org.netbeans.modules.maven.embedder.EmbedderFactory; +import org.netbeans.modules.maven.embedder.MavenEmbedder; +import org.netbeans.modules.web.jsfapi.api.JsfVersion; +import org.netbeans.modules.web.jsfapi.spi.JsfReferenceImplementationProvider; +import org.openide.util.Exceptions; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author Benjamin Asbach + */ +@ServiceProvider(service = JsfReferenceImplementationProvider.class) +public class MavenJsfReferenceImplementationProvider implements JsfReferenceImplementationProvider { + + static final Map JSF_VERSION_MAVEN_COORDINATES_MAPPING; + static { + EnumMap map = new EnumMap<>(JsfVersion.class); + map.put(JsfVersion.JSF_1_0, "javax.faces:jsf-impl:1.1_02"); //seems to be not available in maven central + map.put(JsfVersion.JSF_1_1, "javax.faces:jsf-impl:1.1_02"); + map.put(JsfVersion.JSF_1_2, "javax.faces:jsf-impl:1.2"); + map.put(JsfVersion.JSF_2_0, "com.sun.faces:jsf-impl:2.0.11"); + map.put(JsfVersion.JSF_2_1, "com.sun.faces:jsf-impl:2.1.29"); + map.put(JsfVersion.JSF_2_2, "com.sun.faces:jsf-impl:2.2.20"); + map.put(JsfVersion.JSF_2_3, "org.glassfish:jakarta.faces:2.3.19"); + map.put(JsfVersion.JSF_3_0, "org.glassfish:jakarta.faces:3.0.4"); + map.put(JsfVersion.JSF_4_0, "org.glassfish:jakarta.faces:4.0.2"); + JSF_VERSION_MAVEN_COORDINATES_MAPPING = Collections.unmodifiableMap(map); + } + + @Override + public Path of(JsfVersion jsfVersion) { + String mavenCoordinates[] = JSF_VERSION_MAVEN_COORDINATES_MAPPING.get(jsfVersion).split(":"); + if (mavenCoordinates.length != 3) { + return null; + } + String groupId = mavenCoordinates[0]; + String artifactId = mavenCoordinates[1]; + String version = mavenCoordinates[2]; + + MavenEmbedder mavenEmbedder = EmbedderFactory.getOnlineEmbedder(); + + ArtifactRepository localRepository = mavenEmbedder.getLocalRepository(); + ArtifactRepository remoteRepository = mavenEmbedder.createRemoteRepository(DEFAULT_REMOTE_REPO_URL, DEFAULT_REMOTE_REPO_ID); + Artifact jsfRIArtifact = mavenEmbedder.createArtifact(groupId, artifactId, version, "jar"); + + try { + mavenEmbedder.resolve(jsfRIArtifact, Collections.singletonList(remoteRepository), localRepository); + } catch (ArtifactResolutionException ex) { + Exceptions.printStackTrace(ex); + + return null; + } catch (ArtifactNotFoundException ex) { + Exceptions.printStackTrace(ex); + + return null; + } + + return Paths.get(jsfRIArtifact.getFile().toURI()); + } +} diff --git a/enterprise/maven.j2ee/test/unit/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProviderTest.java b/enterprise/maven.j2ee/test/unit/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProviderTest.java new file mode 100644 index 000000000000..ca309d0b2ff4 --- /dev/null +++ b/enterprise/maven.j2ee/test/unit/src/org/netbeans/modules/maven/j2ee/MavenJsfReferenceImplementationProviderTest.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.maven.j2ee; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; +import org.junit.Test; +import org.netbeans.modules.web.jsfapi.api.JsfVersion; + +/** + * + * @author Benjamin Asbach + */ +public class MavenJsfReferenceImplementationProviderTest { + + @Test + public void testAllJsfVersionsAreMapped() { + for (JsfVersion jsfVersion : JsfVersion.values()) { + assertTrue(MavenJsfReferenceImplementationProvider.JSF_VERSION_MAVEN_COORDINATES_MAPPING.containsKey(jsfVersion)); + } + } + + @Test + public void testAllMavenCoordinatesAreWellFormatted() { + for (String mavenCoordinates : MavenJsfReferenceImplementationProvider.JSF_VERSION_MAVEN_COORDINATES_MAPPING.values()) { + assertEquals(3, mavenCoordinates.split(":").length); + } + } +} diff --git a/enterprise/web.bootsfaces/nbproject/project.xml b/enterprise/web.bootsfaces/nbproject/project.xml index ea09ca779af8..078bea05b42f 100644 --- a/enterprise/web.bootsfaces/nbproject/project.xml +++ b/enterprise/web.bootsfaces/nbproject/project.xml @@ -83,8 +83,8 @@ - 1 - 1.14 + 2 + 2.0 diff --git a/enterprise/web.core/src/org/netbeans/modules/web/wizards/PageIterator.java b/enterprise/web.core/src/org/netbeans/modules/web/wizards/PageIterator.java index d79dccc8f585..6136e3f848d4 100644 --- a/enterprise/web.core/src/org/netbeans/modules/web/wizards/PageIterator.java +++ b/enterprise/web.core/src/org/netbeans/modules/web/wizards/PageIterator.java @@ -198,6 +198,11 @@ private static boolean isJSF30(WebModule wm) { return classpath != null && classpath.findResource("jakarta/faces/flow/Flow.class") != null; //NOI18N } + private static boolean isJSF40(WebModule wm) { + ClassPath classpath = ClassPath.getClassPath(wm.getDocumentBase(), ClassPath.COMPILE); + return classpath != null && classpath.findResource("jakarta/faces/lifecycle/ClientWindowScoped.class") != null; //NOI18N + } + public Set instantiate(TemplateWizard wiz) throws IOException { // Here is the default plain behavior. Simply takes the selected // template (you need to have included the standard second panel @@ -231,7 +236,9 @@ public Set instantiate(TemplateWizard wiz) throws IOException { template = templateParent.getFileObject("JSP", "xhtml"); //NOI18N WebModule wm = WebModule.getWebModule(df.getPrimaryFile()); if (wm != null) { - if (isJSF30(wm)) { + if (isJSF40(wm)) { + wizardProps.put("isJSF40", Boolean.TRUE); + } else if (isJSF30(wm)) { wizardProps.put("isJSF30", Boolean.TRUE); } else if (isJSF22(wm)) { wizardProps.put("isJSF22", Boolean.TRUE); diff --git a/enterprise/web.freeform/nbproject/project.xml b/enterprise/web.freeform/nbproject/project.xml index 0ab6e4266063..e6f9498675bd 100644 --- a/enterprise/web.freeform/nbproject/project.xml +++ b/enterprise/web.freeform/nbproject/project.xml @@ -177,8 +177,8 @@ - 0-1 - 1.0 + 2 + 2.0 diff --git a/enterprise/web.jsf.editor/manifest.mf b/enterprise/web.jsf.editor/manifest.mf index c484f2268ecc..5e0c1c4d89f1 100644 --- a/enterprise/web.jsf.editor/manifest.mf +++ b/enterprise/web.jsf.editor/manifest.mf @@ -2,5 +2,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.modules.web.jsf.editor OpenIDE-Module-Layer: org/netbeans/modules/web/jsf/editor/resources/layer.xml OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/web/jsf/editor/resources/Bundle.properties -OpenIDE-Module-Specification-Version: 1.72 +OpenIDE-Module-Specification-Version: 2.0 AutoUpdate-Show-In-Client: false diff --git a/enterprise/web.jsf.editor/nbproject/project.xml b/enterprise/web.jsf.editor/nbproject/project.xml index e3832f3a336b..792af88df009 100644 --- a/enterprise/web.jsf.editor/nbproject/project.xml +++ b/enterprise/web.jsf.editor/nbproject/project.xml @@ -386,8 +386,8 @@ - 1 - 1.51 + 2 + 2.0 @@ -404,8 +404,8 @@ - 1 - 1.34 + 2 + 2.0 diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/InjectCompositeComponent.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/InjectCompositeComponent.java index 18ed99a29665..92c786918622 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/InjectCompositeComponent.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/InjectCompositeComponent.java @@ -209,14 +209,14 @@ public void run() { //but since the library has just been created by adding an xhtml file //to the resources/xxx/ folder we need to wait until the files //get indexed and the library is created - final String compositeLibURL = LibraryUtils.getCompositeLibraryURL(compFolder, jsfs.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + final String compositeLibURL = LibraryUtils.getCompositeLibraryURL(compFolder, jsfs.getJsfVersion()); Source documentSource = Source.create(document); ParserManager.parseWhenScanFinished(Collections.singletonList(documentSource), new UserTask() { //NOI18N @Override public void run(ResultIterator resultIterator) throws Exception { Library lib = jsfs.getLibrary(compositeLibURL); if (lib != null) { - if (!LibraryUtils.importLibrary(document, lib, prefix, jsfs.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2))) { //XXX: fix the damned static prefix !!! + if (!LibraryUtils.importLibrary(document, lib, prefix)) { //XXX: fix the damned static prefix !!! logger.log(Level.WARNING, "Cannot import composite components library {0}", compositeLibURL); //NOI18N } } else { @@ -249,7 +249,7 @@ public void run() { ((BaseDocument) templateInstanceDoc).runAtomic(new Runnable() { @Override public void run() { - LibraryUtils.importLibrary(templateInstanceDoc, importsMap, jsfs.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + LibraryUtils.importLibrary(templateInstanceDoc, importsMap); } }); try { diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfNavigationHelper.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfNavigationHelper.java index 25a0cba21a26..592b7740c67a 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfNavigationHelper.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfNavigationHelper.java @@ -127,7 +127,7 @@ public void run(ResultIterator resultIterator) throws Exception { Parser.Result result = resultIterator.getParserResult(caretOffset); if (result instanceof HtmlParserResult) { HtmlParserResult hresult = (HtmlParserResult) result; - Element root = hresult.root(LibraryUtils.COMPOSITE_LIBRARY_NS); + Element root = hresult.root(LibraryUtils.COMPOSITE_LIBRARY_JCP_NS); ElementUtils.visitChildren(root, new ElementVisitor() { @Override public void visit(Element node) { diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfSupportImpl.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfSupportImpl.java index d9c44cc120f8..297685a69936 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfSupportImpl.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfSupportImpl.java @@ -221,7 +221,7 @@ public Lookup getLookup() { @Override public Library getLibrary(String namespace) { - return NamespaceUtils.getForNs(faceletsLibrarySupport.getLibraries(), namespace); + return NamespaceUtils.getForNs(faceletsLibrarySupport.getNamespaceLibraryMapping(), namespace); } /** Library's uri to library map @@ -230,7 +230,7 @@ public Library getLibrary(String namespace) { */ @Override public Map getLibraries() { - return faceletsLibrarySupport.getLibraries(); + return faceletsLibrarySupport.getNamespaceLibraryMapping(); } public boolean isFileOnClasspath(FileObject file) { diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfUtils.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfUtils.java index eb6443ed4797..b24183f2c884 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfUtils.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/JsfUtils.java @@ -100,11 +100,13 @@ public static Result getEmbeddedParserResult(ResultIterator resultIterator, Stri } public static Node getRoot(HtmlParserResult parserResult, LibraryInfo library) { - Node rootNode = parserResult.root(library.getNamespace()); - if ((rootNode == null || rootNode.children().isEmpty()) && library.getLegacyNamespace() != null) { - rootNode = parserResult.root(library.getLegacyNamespace()); + for (String namespace : library.getValidNamespaces()) { + Node rootNode = parserResult.root(namespace); + if (rootNode != null && !rootNode.children().isEmpty()) { + return rootNode; + } } - return rootNode; + + return null; } - } diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/FixNamespacesPerformer.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/FixNamespacesPerformer.java index 9131efa0a799..690e3a87bd23 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/FixNamespacesPerformer.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/FixNamespacesPerformer.java @@ -96,7 +96,7 @@ private void removeUnusedNamespaces() { private void includeMissingNamespaces() { for (VariantItem variant : selections) { - LibraryUtils.importLibrary(baseDocument, variant.getLibrary(), variant.getPrefix(), importData.isJsf22); + LibraryUtils.importLibrary(baseDocument, variant.getLibrary(), variant.getPrefix()); } } } diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/ImportData.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/ImportData.java index 2cd7e363d205..516d42833a0a 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/ImportData.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/ImportData.java @@ -31,7 +31,6 @@ public class ImportData { public volatile boolean shouldShowNamespacesPanel; - public volatile boolean isJsf22; private final List dataItems = new ArrayList<>(); private final List dataItemsToReplace = new ArrayList<>(); diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/NamespaceProcessor.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/NamespaceProcessor.java index 3488b8c64fc2..570f08eab66f 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/NamespaceProcessor.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/actions/NamespaceProcessor.java @@ -78,9 +78,6 @@ class NamespaceProcessor { ImportData computeImportData() { final ImportData importData = new ImportData(); - // use JSF 2.2 namespaces? - importData.isJsf22 = jsfSupport == null ? false : jsfSupport.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2); - // unused declarations for (Attribute namespaceAttribute : resultCollector.getUnusedNamespaces()) { importData.addToRemove(namespaceAttribute); @@ -98,19 +95,6 @@ ImportData computeImportData() { return importData; } - private static Node getTopRoot(HtmlParserResult parserResult) { - Node root = parserResult.root(); - if (root.children().isEmpty()) { - Node faceletsRoot = parserResult.root(DefaultLibraryInfo.FACELETS.getLegacyNamespace()); - if (!faceletsRoot.children().isEmpty()) { - return faceletsRoot; - } else { - return parserResult.root(DefaultLibraryInfo.FACELETS.getNamespace()); - } - } - return root; - } - private List getDeclaredLibraries() { List result = new ArrayList<>(); for (String namespace : parserResult.getNamespaces().keySet()) { diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/completion/JsfAttributesCompletionHelper.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/completion/JsfAttributesCompletionHelper.java index 2569f3d5ea5e..1c3624824804 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/completion/JsfAttributesCompletionHelper.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/completion/JsfAttributesCompletionHelper.java @@ -31,7 +31,10 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; +import static java.util.function.Predicate.not; import javax.lang.model.element.NestingKind; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -74,11 +77,12 @@ import org.netbeans.modules.web.jsf.editor.JsfUtils; import org.netbeans.modules.web.jsf.editor.facelets.CompositeComponentLibrary; import org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibraryMetadata; +import org.netbeans.modules.web.jsf.editor.facelets.JsfNamespaceComparator; import org.netbeans.modules.web.jsf.editor.index.CompositeComponentModel; import org.netbeans.modules.web.jsf.editor.index.JsfPageModelFactory; import org.netbeans.modules.web.jsfapi.api.Attribute; import org.netbeans.modules.web.jsfapi.api.DefaultLibraryInfo; -import org.netbeans.modules.web.jsfapi.api.JsfVersion; +import org.netbeans.modules.web.jsfapi.api.JsfSupport; import org.netbeans.modules.web.jsfapi.api.Library; import org.netbeans.modules.web.jsfapi.api.LibraryComponent; import org.netbeans.modules.web.jsfapi.api.NamespaceUtils; @@ -307,12 +311,11 @@ public void run(ResultIterator resultIterator) throws Exception { } private static String getPrefixForFaceletsNs(HtmlParserResult result) { - String prefix = result.getNamespaces().get(DefaultLibraryInfo.FACELETS.getNamespace()); - if (prefix != null) { - return prefix; - } - - return result.getNamespaces().get(DefaultLibraryInfo.FACELETS.getLegacyNamespace()); + return DefaultLibraryInfo.FACELETS.getValidNamespaces().stream() + .map(result.getNamespaces()::get) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } private static List findValue(Collection nodes, String tagName, List foundNodes) { @@ -373,7 +376,11 @@ private static void handleContracts(FileObject parent, String path, List // //offsers facet declarations only from within this document public static void completeFacetsInCCImpl(CompletionContext context, List items, String ns, OpenTag openTag, JsfSupportImpl jsfs) { - if ("http://java.sun.com/jsf/composite".equalsIgnoreCase(ns) || "http://xmlns.jcp.org/jsf/composite".equalsIgnoreCase(ns)) { + if (ns == null) { + return; + } + + if (DefaultLibraryInfo.COMPOSITE.getValidNamespaces().contains(ns.toLowerCase())) { String tagName = openTag.unqualifiedName().toString(); if ("renderFacet".equalsIgnoreCase(tagName) || "insertFacet".equalsIgnoreCase(tagName)) { //NOI18N if ("name".equalsIgnoreCase(context.getAttributeName())) { //NOI18N @@ -392,7 +399,11 @@ public static void completeFacetsInCCImpl(CompletionContext context, List //offsers all facetes public static void completeFacets(CompletionContext context, List items, String ns, OpenTag openTag, JsfSupportImpl jsfs) { - if ("http://java.sun.com/jsf/core".equalsIgnoreCase(ns) || "http://xmlns.jcp.org/jsf/core".equalsIgnoreCase(ns)) { + if (ns == null) { + return; + } + + if (DefaultLibraryInfo.COMPOSITE.getValidNamespaces().contains(ns.toLowerCase())) { String tagName = openTag.unqualifiedName().toString(); if ("facet".equalsIgnoreCase(tagName)) { //NOI18N if ("name".equalsIgnoreCase(context.getAttributeName())) { //NOI18N @@ -459,18 +470,39 @@ public static void completeFaceletsFromProject(CompletionContext context, List items, JsfSupportImpl jsfs) { - if (context.getAttributeName().toLowerCase(Locale.ENGLISH).startsWith("xmlns")) { //NOI18N + public static void completeXMLNSAttribute(CompletionContext context, List items, JsfSupport jsfs) { + String xmlns = context.getAttributeName().toLowerCase(Locale.ENGLISH); + + if (xmlns.startsWith("xmlns:")) { //NOI18N + Set preferredNamespaces = Collections.emptySet(); + + int preferredNamespaceSortPriority = 10; + + String xmlnsPrefix = xmlns.substring(6); + if (!"".equals(xmlnsPrefix)) { + Optional preferedLibrary = jsfs.getLibraries().values().stream().filter(lib -> lib.getDefaultPrefix().equals(xmlnsPrefix)).findFirst(); + if (preferedLibrary.isPresent()) { + preferredNamespaces = preferedLibrary.get().getValidNamespaces(); + for (String preferredNamespace : preferredNamespaces) { + items.add(HtmlCompletionItem.createAttributeValue(preferredNamespace, context.getCCItemStartOffset(), !context.isValueQuoted(), preferredNamespaceSortPriority++)); + } + } + } + //xml namespace completion for facelets namespaces - Set nss = NamespaceUtils.getAvailableNss(jsfs.getLibraries(), jsfs.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + List otherNamespaces = new ArrayList<>(jsfs.getLibraries().keySet()); + Collections.sort(otherNamespaces, JsfNamespaceComparator.getInstance()); - //add also xhtml ns to the completion - nss.add(LibraryUtils.XHTML_NS); - for (String namespace : nss) { - if (namespace.startsWith(context.getPrefix())) { - items.add(HtmlCompletionItem.createAttributeValue(namespace, context.getCCItemStartOffset(), !context.isValueQuoted())); + int otherNamespaceSortPriority = 20; + for (String namespace : otherNamespaces) { + if (preferredNamespaces.contains(namespace)) { + continue; } + + items.add(HtmlCompletionItem.createAttributeValue(namespace, context.getCCItemStartOffset(), !context.isValueQuoted(), otherNamespaceSortPriority++)); } + } else if (xmlns.startsWith("xmlns")) { //NOI18N + items.add(HtmlCompletionItem.createAttributeValue(LibraryUtils.XHTML_NS, context.getCCItemStartOffset(), !context.isValueQuoted())); } } diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/completion/JsfCompletionItem.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/completion/JsfCompletionItem.java index bb151e689e0b..5917d37eb29b 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/completion/JsfCompletionItem.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/completion/JsfCompletionItem.java @@ -139,7 +139,7 @@ public void defaultAction(JTextComponent component) { private void autoimportLibrary(JTextComponent component) { final BaseDocument doc = (BaseDocument) component.getDocument(); Library lib = JsfTag.this.component.getLibrary(); - LibraryUtils.importLibrary(doc, lib, null, isJsf22Plus); + LibraryUtils.importLibrary(doc, lib, null); } //use bold font @@ -317,10 +317,7 @@ private static String getLibraryHelpHeader(Library library) { sb.append("
"); //NOI18N sb.append(NbBundle.getMessage(JsfCompletionItem.class, "MSG_Library")); sb.append(": "); //NOI18N - sb.append(library.getNamespace()); - if (library.getLegacyNamespace() != null) { - sb.append(", ").append(library.getLegacyNamespace()); //NOI18N - } + sb.append(String.join(", ", library.getValidNamespaces())); if (library.getDisplayName() != null && !library.getDisplayName().equals(library.getNamespace())) { sb.append(" ("); //NOI18N sb.append(library.getDisplayName()); diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/el/JsfELVariableResolver.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/el/JsfELVariableResolver.java index 0ed7e1357ff8..108e5e541b71 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/el/JsfELVariableResolver.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/el/JsfELVariableResolver.java @@ -24,6 +24,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; @@ -266,10 +268,11 @@ public void run(final ResultIterator resultIterator) throws Exception { if (parserResult == null) { continue; } - Node root = parserResult.root(DefaultLibraryInfo.FACELETS.getNamespace()); - if (root == null || root.children().isEmpty()) { - root = parserResult.root(DefaultLibraryInfo.FACELETS.getLegacyNamespace()); - } + Node root = DefaultLibraryInfo.FACELETS.getValidNamespaces().stream() + .map(parserResult::root) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); ElementUtils.visitChildren(root, new ElementVisitor() { @Override public void visit(Element node) { @@ -313,8 +316,11 @@ public void run(ResultIterator resultIterator) throws Exception { Result parseResult = JsfUtils.getEmbeddedParserResult(resultIterator, "text/html"); //NOI18N if (parseResult instanceof HtmlParserResult) { HtmlParserResult result = (HtmlParserResult) parseResult; - Node root = result.root(DefaultLibraryInfo.COMPOSITE.getNamespace()); - if (root.children().isEmpty()) root = result.root(DefaultLibraryInfo.COMPOSITE.getLegacyNamespace()); + Node root = DefaultLibraryInfo.COMPOSITE.getValidNamespaces().stream() + .map(result::root) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); Collection children = root.children(ElementType.OPEN_TAG); for (Element child : children) { OpenTag ot = (OpenTag) child; diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/el/JsfVariablesModel.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/el/JsfVariablesModel.java index 66230e2fca9c..47589c52ce05 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/el/JsfVariablesModel.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/el/JsfVariablesModel.java @@ -94,7 +94,7 @@ private void initModel() { if(sup == null) { return ; } - Set faceletsLibsNamespaces = NamespaceUtils.getAvailableNss(sup.getLibraries(), sup.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + Set faceletsLibsNamespaces = sup.getLibraries().keySet(); Collection declaredNamespaces = result.getNamespaces().keySet(); for (String namespace : declaredNamespaces) { diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/AbstractFaceletsLibrary.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/AbstractFaceletsLibrary.java index c44f32181e4b..cd0d62e35a33 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/AbstractFaceletsLibrary.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/AbstractFaceletsLibrary.java @@ -23,7 +23,6 @@ import java.net.URL; import java.util.Collection; import java.util.Map; -import java.util.Objects; import org.netbeans.modules.web.jsfapi.api.Library; import org.netbeans.modules.web.jsfapi.api.LibraryComponent; import org.netbeans.modules.web.jsfapi.api.Tag; diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/CompositeComponentLibrary.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/CompositeComponentLibrary.java index ccb27250e088..0e10c42a792d 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/CompositeComponentLibrary.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/CompositeComponentLibrary.java @@ -25,13 +25,13 @@ import java.util.LinkedList; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.StringTokenizer; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.netbeans.modules.web.jsf.editor.index.CompositeComponentModel; import org.netbeans.modules.web.jsf.editor.index.JsfIndex; import org.netbeans.modules.web.jsfapi.api.Attribute; -import org.netbeans.modules.web.jsfapi.api.JsfVersion; import org.netbeans.modules.web.jsfapi.api.LibraryType; import org.netbeans.modules.web.jsfapi.api.Tag; import org.netbeans.modules.web.jsfapi.spi.LibraryUtils; @@ -57,7 +57,7 @@ public class CompositeComponentLibrary extends FaceletsLibrary { private Map compositeComponentsMap; //for cc libraries with facelets library descriptor, the constructor is called by Mojarra - public CompositeComponentLibrary(FaceletsLibrarySupport support, String compositeLibraryName, String namespace, URL libraryDescriptorURL) { + public CompositeComponentLibrary(FaceletsLibrarySupport support, String compositeLibraryName, Set namespace, URL libraryDescriptorURL) { super(support, namespace, libraryDescriptorURL); this.compositeLibraryResourceFolderName = compositeLibraryName; @@ -90,7 +90,7 @@ public LibraryType getType() { @Override public String getDefaultNamespace() { - return LibraryUtils.getCompositeLibraryURL(getLibraryName(), support.getJsfSupport().getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + return LibraryUtils.getCompositeLibraryURL(getLibraryName(), support.getJsfSupport().getJsfVersion()); } @Override diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/DefaultFaceletLibraries.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/DefaultFaceletLibraries.java index 3f81e85dc08d..6567bc0aa8a0 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/DefaultFaceletLibraries.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/DefaultFaceletLibraries.java @@ -26,6 +26,9 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import static java.util.function.Predicate.not; import java.util.logging.Level; import java.util.logging.Logger; import org.netbeans.modules.web.jsfapi.api.DefaultLibraryInfo; @@ -33,7 +36,6 @@ import org.netbeans.modules.web.jsfapi.api.LibraryComponent; import org.netbeans.modules.web.jsfapi.api.LibraryInfo; import org.netbeans.modules.web.jsfapi.api.LibraryType; -import org.netbeans.modules.web.jsfapi.api.NamespaceUtils; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.modules.InstalledFileLocator; @@ -48,6 +50,7 @@ public class DefaultFaceletLibraries { private static DefaultFaceletLibraries INSTANCE; + private File jsfImplJar; private Collection libraryDescriptorsFiles; private Map librariesDescriptors; private static Map jsf22FaceletPseudoLibraries; @@ -59,14 +62,20 @@ public static synchronized DefaultFaceletLibraries getInstance() { return INSTANCE; } - public DefaultFaceletLibraries() { - init(); + public DefaultFaceletLibraries(File jsfImplJar) { + this.jsfImplJar = jsfImplJar; + + init(jsfImplJar); } - private void init() { - File jsfImplJar = InstalledFileLocator.getDefault().locate( + public DefaultFaceletLibraries() { + this(InstalledFileLocator.getDefault().locate( "modules/ext/jsf-2_2/javax.faces.jar", //NOI18N - "org.netbeans.modules.web.jsf20", false); //NOI18N + "org.netbeans.modules.web.jsf20", false) //NOI18N + ); + } + + private void init(File jsfImplJar) { assert jsfImplJar != null; FileObject jsfImplJarFo = FileUtil.getArchiveRoot(FileUtil.toFileObject(jsfImplJar)); @@ -74,6 +83,10 @@ private void init() { } + public File getJsfImplJar() { + return jsfImplJar; + } + public Collection getLibrariesDescriptorsFiles() { return this.libraryDescriptorsFiles; } @@ -129,20 +142,24 @@ private static Collection findLibraryDescriptors(FileObject classpat protected static synchronized Map getJsf22FaceletPseudoLibraries(FaceletsLibrarySupport support) { if (jsf22FaceletPseudoLibraries == null) { jsf22FaceletPseudoLibraries = new HashMap<>(2); - jsf22FaceletPseudoLibraries.put(DefaultLibraryInfo.JSF.getLegacyNamespace(), new JsfFaceletPseudoLibrary(support, DefaultLibraryInfo.JSF)); - jsf22FaceletPseudoLibraries.put(DefaultLibraryInfo.PASSTHROUGH.getLegacyNamespace(), new JsfFaceletPseudoLibrary(support, DefaultLibraryInfo.PASSTHROUGH)); + DefaultLibraryInfo.JSF.getValidNamespaces().stream() + .filter(not(jsf22FaceletPseudoLibraries::containsKey)) + .forEach(namespace -> jsf22FaceletPseudoLibraries.put(namespace, new JsfFaceletPseudoLibrary(support, DefaultLibraryInfo.JSF))); + DefaultLibraryInfo.PASSTHROUGH.getValidNamespaces().stream() + .filter(not(jsf22FaceletPseudoLibraries::containsKey)) + .forEach(namespace -> jsf22FaceletPseudoLibraries.put(namespace, new JsfFaceletPseudoLibrary(support, DefaultLibraryInfo.PASSTHROUGH))); } return jsf22FaceletPseudoLibraries; } private static class JsfFaceletPseudoLibrary implements Library { - private final String namespace; + private final Set validNamespaces; private final String prefix; private final String displayName; public JsfFaceletPseudoLibrary(FaceletsLibrarySupport support, DefaultLibraryInfo defaultLibraryInfo) { - this.namespace = defaultLibraryInfo.getNamespace(); + this.validNamespaces = defaultLibraryInfo.getValidNamespaces(); this.prefix = defaultLibraryInfo.getDefaultPrefix(); this.displayName = defaultLibraryInfo.getDisplayName(); } @@ -164,7 +181,7 @@ public LibraryType getType() { @Override public String getNamespace() { - return namespace; + return validNamespaces.iterator().next(); } @Override @@ -183,9 +200,8 @@ public String getDisplayName() { } @Override - public String getLegacyNamespace() { - return NamespaceUtils.NS_MAPPING.get(namespace); + public Set getValidNamespaces() { + return validNamespaces; } - } } diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrary.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrary.java index fdc9b4695a07..f16b5234a3ca 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrary.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrary.java @@ -22,8 +22,8 @@ import java.net.URL; import java.util.HashMap; import java.util.Map; +import java.util.Set; import org.netbeans.modules.web.jsfapi.api.LibraryType; -import org.netbeans.modules.web.jsfapi.api.NamespaceUtils; import org.netbeans.modules.web.jsfapi.spi.LibraryUtils; import org.openide.filesystems.FileObject; import org.openide.filesystems.URLMapper; @@ -42,17 +42,18 @@ public class FaceletsLibrary extends AbstractFaceletsLibrary { /** * The namespace declared in the facelets library descriptor */ - private final String declaredNamespace; + private final Set validNamespaces; - private final Map components = new HashMap(); + private final Map components = new HashMap<>(); private LibraryDescriptor libraryDescriptor, faceletsLibraryDescriptor; private String defaultPrefix; private final URL libraryDescriptorSource; - public FaceletsLibrary(FaceletsLibrarySupport support, String namespace, URL libraryDescriptorSourceURL) { - super(support, namespace); - declaredNamespace = namespace; - libraryDescriptorSource = libraryDescriptorSourceURL; + public FaceletsLibrary(FaceletsLibrarySupport support, Set allValidNamespaces, URL libraryDescriptorSourceURL) { + super(support, allValidNamespaces.iterator().next()); + + this.validNamespaces = allValidNamespaces; + this.libraryDescriptorSource = libraryDescriptorSourceURL; } protected synchronized LibraryDescriptor getFaceletsLibraryDescriptor() throws LibraryDescriptorException { @@ -70,7 +71,7 @@ protected synchronized LibraryDescriptor getFaceletsLibraryDescriptor() throws L @Override public String getNamespace() { - return declaredNamespace; + return validNamespaces.iterator().next(); } @Override @@ -201,9 +202,7 @@ public Function createFunction(String name, Method method) { } @Override - public String getLegacyNamespace() { - return NamespaceUtils.NS_MAPPING.get(declaredNamespace); + public Set getValidNamespaces() { + return validNamespaces; } - - } diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrarySupport.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrarySupport.java index f8a5c5afe8b4..80478285034b 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrarySupport.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrarySupport.java @@ -18,16 +18,18 @@ */ package org.netbeans.modules.web.jsf.editor.facelets; +import com.sun.faces.config.DocumentInfo; +import com.sun.faces.spi.ConfigurationResourceProvider; import java.io.IOException; +import java.net.MalformedURLException; import java.util.Enumeration; import org.netbeans.modules.web.api.webmodule.WebModule; import org.netbeans.modules.web.jsf.editor.facelets.mojarra.FaceletsTaglibConfigProcessor; -import com.sun.faces.config.DocumentInfo; -import com.sun.faces.spi.ConfigurationResourceProvider; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -38,17 +40,18 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; import javax.servlet.ServletContext; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.netbeans.modules.web.jsf.api.editor.JsfFacesComponentsProvider; -import org.netbeans.modules.web.jsf.api.facesmodel.JsfVersionUtils; import org.netbeans.modules.web.jsf.editor.JsfSupportImpl; import org.netbeans.modules.web.jsf.editor.facelets.mojarra.ConfigManager; import org.netbeans.modules.web.jsf.editor.index.IndexedFile; import org.netbeans.modules.web.jsfapi.api.JsfVersion; import org.netbeans.modules.web.jsfapi.api.Library; import org.netbeans.modules.web.jsfapi.api.LibraryType; +import org.netbeans.modules.web.jsfapi.spi.JsfReferenceImplementationProvider; import org.openide.filesystems.FileChangeAdapter; import org.openide.filesystems.FileChangeListener; import org.openide.filesystems.FileEvent; @@ -56,6 +59,7 @@ import org.openide.filesystems.FileStateInvalidException; import org.openide.filesystems.URLMapper; import org.openide.util.Exceptions; +import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.RequestProcessor; @@ -77,7 +81,9 @@ public class FaceletsLibrarySupport { * the default and the declared one when * there is a tag library descriptor for the composite library */ - private Map faceletsLibraries; + private Map namespaceLibraryMapping; + + private Map defaultPrefixLibraryMapping; private long libraries_hash; @@ -146,7 +152,7 @@ public JsfSupportImpl getJsfSupport() { } private synchronized void invalidateLibrariesCache() { - faceletsLibraries = null; + namespaceLibraryMapping = null; // !!! Can't be used here - leads to issues like issue #230198 !!! // IndexingManager.getDefault().refreshAllIndices(getJsfSupport().getClassPathRoots()); @@ -155,31 +161,43 @@ private synchronized void invalidateLibrariesCache() { /* * Called via the JsfSupport from the JSF indexers when their source roots have been rescanned. * that can mean the files related to the JSF libraries might have changed so we need to re-check - * the libraries up-to-date status next time when one calls getLibraries(). + * the libraries up-to-date status next time when one calls getNamespaceLibraryMapping(). */ public void indexedContentPossiblyChanged() { checkLibraryDescriptorsUpToDate(); } /** @return URI -> library map */ - public synchronized Map getLibraries() { - if (faceletsLibraries == null) { + public synchronized Map getNamespaceLibraryMapping() { + if (namespaceLibraryMapping == null) { // preload FacesComponents refreshFacesComponentsCache(0); //not initialized yet, or invalidated by checkLibraryDescriptorsUpToDate() - faceletsLibraries = findLibraries(); + namespaceLibraryMapping = findLibraries(); - if (faceletsLibraries == null) { + if (namespaceLibraryMapping == null) { //an error when scanning libraries, return no libraries, but give it a next try return Collections.emptyMap(); } - updateCompositeLibraries(faceletsLibraries); + updateCompositeLibraries(namespaceLibraryMapping); + } + updateFacesComponentLibraries(namespaceLibraryMapping); + + return namespaceLibraryMapping; + } + + public synchronized Map getDefaultPrefixLibraryMapping() { + if (defaultPrefixLibraryMapping == null) { + Map gotNamespaceLibraryMapping = getNamespaceLibraryMapping(); + Map map = new HashMap<>(); + gotNamespaceLibraryMapping.values().forEach(value -> map.put(value.getDefaultPrefix(), value)); + + defaultPrefixLibraryMapping = Collections.unmodifiableMap(map); } - updateFacesComponentLibraries(faceletsLibraries); - return faceletsLibraries; + return defaultPrefixLibraryMapping; } private void checkLibraryDescriptorsUpToDate() { @@ -359,38 +377,66 @@ public Collection getResources(ServletContext sc) { } }); - //3. last add a provider for default jsf libs - // - //Add a facelet taglib provider which provides the libraries from - //netbeans jsf2.0 library - // - //This is needed for the standart JSF 2.0 libraries since it may - //happen that there is no javax-faces.jar with the .taglib.xml files - //on the compile classpath and we still want the features like code - //completion work. This happens for example in Maven web projects. - // - //The provider is last in the list so the provided libraries will - //be overridden if the descriptors are found in any of the jars - //on compile classpath. - Collection libraryDescriptorFiles = DefaultFaceletLibraries.getInstance().getLibrariesDescriptorsFiles(); - final Collection libraryURIs = new ArrayList<>(); - for(FileObject fo : libraryDescriptorFiles) { - try { - libraryURIs.add(fo.toURL().toURI()); - } catch (URISyntaxException ex) { - LOGGER.log(Level.INFO, null, ex); + + // try to find reference implementation based on jsf version + JsfVersion jsfVersion = getJsfSupport().getJsfVersion(); + JsfReferenceImplementationProvider jsfRIProvider = Lookup.getDefault().lookup(JsfReferenceImplementationProvider.class); + Path jsfReferenceImplementation = jsfRIProvider.of(jsfVersion); + + List jsfRIJars = new ArrayList<>(); + try { + if (jsfReferenceImplementation != null) { + DefaultFaceletLibraries jsfRIFaceletLibraries = new DefaultFaceletLibraries(jsfReferenceImplementation.toFile()); + List jsfRIDescriptors = jsfRIFaceletLibraries.getLibrariesDescriptorsFiles().stream() + .map(FileObject::toURI) + .collect(Collectors.toList()); + faceletTaglibProviders.add(new ConfigurationResourceProvider() { + @Override + public Collection getResources(ServletContext sc) { + return jsfRIDescriptors; + } + }); + + jsfRIJars.add(jsfReferenceImplementation.toUri().toURL()); + } else { + // if no reference implementation could be found fallback to bundled one + + //Add a facelet taglib provider which provides the libraries from + //netbeans jsf2.0 library + // + //This is needed for the standart JSF 2.0 libraries since it may + //happen that there is no javax-faces.jar with the .taglib.xml files + //on the compile classpath and we still want the features like code + //completion work. This happens for example in Maven web projects. + + DefaultFaceletLibraries defaultFaceletLibraries = DefaultFaceletLibraries.getInstance(); + Collection libraryDescriptorFiles = defaultFaceletLibraries.getLibrariesDescriptorsFiles(); + final Collection libraryURIs = new ArrayList<>(); + for (FileObject fo : libraryDescriptorFiles) { + try { + libraryURIs.add(fo.toURL().toURI()); + } catch (URISyntaxException ex) { + LOGGER.log(Level.INFO, null, ex); + } + } + faceletTaglibProviders.add(new ConfigurationResourceProvider() { + @Override + public Collection getResources(ServletContext sc) { + return libraryURIs; + } + }); + + jsfRIJars.add(defaultFaceletLibraries.getJsfImplJar().toURI().toURL()); } + } catch (MalformedURLException ex) { + Exceptions.printStackTrace(ex); } - faceletTaglibProviders.add(new ConfigurationResourceProvider() { - @Override - public Collection getResources(ServletContext sc) { - return libraryURIs; - } - }); + + URLClassLoader jsfRIClassLoader = new URLClassLoader(jsfRIJars.toArray(new URL[]{})); //parse the libraries ServletContext sc = new EmptyServletContext(); - DocumentInfo[] documents = ConfigManager.getConfigDocuments(sc, faceletTaglibProviders, null, true); + DocumentInfo[] documents = ConfigManager.getConfigDocuments(jsfRIClassLoader, sc, faceletTaglibProviders, null, true); if (documents == null) { return null; //error???? } @@ -401,24 +447,18 @@ public Collection getResources(ServletContext sc) { Map libsMap = new HashMap<>(); for (Library lib : processor.compiler.libraries) { - if (lib.getLegacyNamespace() != null) { - libsMap.put(lib.getLegacyNamespace(), lib); - } else { - libsMap.put(lib.getNamespace(), lib); - } + lib.getValidNamespaces().forEach(namespace -> libsMap.put(namespace, lib)); //TODO ASBACHB: This might be wrong } //4. in case of JSF2.2 include pseudo-libraries (http://java.sun.com/jsf/passthrough, http://java.sun.com/jsf) // right now, we have no idea whether such libraries will be included into the JSF bundle or not if (webModule != null) { - JsfVersion jsfVersion = JsfVersionUtils.forWebModule(webModule); if (jsfVersion != null && jsfVersion.isAtLeast(JsfVersion.JSF_2_2)) { libsMap.putAll(DefaultFaceletLibraries.getJsf22FaceletPseudoLibraries(this)); } } return libsMap; - } private synchronized void refreshFacesComponentsCache(int timeToWait) { @@ -427,20 +467,6 @@ private synchronized void refreshFacesComponentsCache(int timeToWait) { } } - -// private void debugLibraries() { -// System.out.println("Facelets Libraries:"); //NOI18N -// System.out.println("===================="); //NOI18N -// for (FaceletsLibrary lib : faceletsLibraries.values()) { -// System.out.println("Library: " + lib.getNamespace()); //NOI18N -// System.out.println("----------------------------------------------------"); //NOI18N -// for (FaceletsLibrary.NamedComponent comp : lib.getComponents()) { -// System.out.println(comp.getName() + "(" + comp.getClass().getSimpleName() + ")"); //NOI18N -// } -// System.out.println(); -// } -// } - public static class Compiler { private Collection libraries = new HashSet<>(); diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/JarFileFaceletLibrary.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/JarFileFaceletLibrary.java new file mode 100644 index 000000000000..a0f396ebad22 --- /dev/null +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/JarFileFaceletLibrary.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.web.jsf.editor.facelets; + +/** + * + * @author asbachb + */ +public class JarFileFaceletLibrary { + +} diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/JsfNamespaceComparator.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/JsfNamespaceComparator.java new file mode 100644 index 000000000000..9e05212af0bf --- /dev/null +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/JsfNamespaceComparator.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.web.jsf.editor.facelets; + +import java.util.Comparator; + +/** + * + * @author Benjamin Asbach + */ +public class JsfNamespaceComparator implements Comparator { + + private static final JsfNamespaceComparator INSTANCE = new JsfNamespaceComparator(); + + private JsfNamespaceComparator() { + } + + public static JsfNamespaceComparator getInstance() { + return INSTANCE; + } + + @Override + public int compare(String namespace1, String namespace2) { + return rate(namespace1).compareTo(rate(namespace2)); + } + + private Integer rate(String namespace) { + if (namespace.startsWith("jakarta")) { + return 1; + } else if (namespace.startsWith("http://xmlns.jcp.org")) { + return 2; + } else if (namespace.startsWith("http://java.sun.com")) { + return 3; + } else { + return 4; + } + } +} diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/PureCompositeComponentLibrary.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/PureCompositeComponentLibrary.java index e58893d743f4..3245b9726616 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/PureCompositeComponentLibrary.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/PureCompositeComponentLibrary.java @@ -18,6 +18,8 @@ */ package org.netbeans.modules.web.jsf.editor.facelets; +import java.util.Collections; + /** * Represents a composite components library w/o the facelets descriptor * @@ -26,7 +28,7 @@ public class PureCompositeComponentLibrary extends CompositeComponentLibrary { public PureCompositeComponentLibrary(FaceletsLibrarySupport support, String libraryName) { - super(support, libraryName, null, null); + super(support, libraryName, Collections.emptySortedSet(), null); } @Override diff --git 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 index 9995607e2a7c..1bfd06bd8725 100644 --- 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 @@ -65,17 +65,22 @@ import com.sun.faces.util.Timer; import com.sun.faces.util.Util; import java.io.BufferedInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; +import java.lang.ref.WeakReference; +import java.net.MalformedURLException; import java.net.URI; import java.net.URL; +import java.net.URLClassLoader; import java.net.URLConnection; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -93,6 +98,8 @@ import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.el.ELContext; import javax.el.ELContextEvent; import javax.el.ELContextListener; @@ -112,8 +119,12 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import org.netbeans.modules.web.jsf.editor.facelets.DefaultFaceletLibraries; +import org.netbeans.modules.web.jsfapi.api.JsfNamespaces; import org.w3c.dom.*; import org.xml.sax.InputSource; +import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /** @@ -672,6 +683,39 @@ void publishPostConfigEvent() { } + /** + *

+ * Obtains an array of Documents to be processed by + * {@link ConfigManager#FACES_CONFIG_PROCESSOR_CHAIN}. + *

+ * + * @param sc the ServletContext for the application to be + * processed + * @param providers List of + * ConfigurationResourceProvider instances that provide the URL + * of the documents to parse. + * @param executor the ExecutorService used to dispatch parse + * request to + * @param validating flag indicating whether or not the documents should be + * validated + * @return an array of DocumentInfos + */ + public static DocumentInfo[] getConfigDocuments(ServletContext sc, + List providers, + ExecutorService executor, + boolean validating) { + DefaultFaceletLibraries defaultFaceletLibraries = DefaultFaceletLibraries.getInstance(); + File jsfImplJar = defaultFaceletLibraries.getJsfImplJar(); + + URLClassLoader jsfImplJarClassLoader = null; + try { + jsfImplJarClassLoader = new URLClassLoader(new URL[]{jsfImplJar.toURI().toURL()}); + } catch (MalformedURLException ex) { + // should only happen when bundleling a broken JSF implementation, so ignore + } + + return getConfigDocuments(jsfImplJarClassLoader, sc, providers, executor, validating); + } /** *

@@ -689,7 +733,7 @@ void publishPostConfigEvent() { * should be validated * @return an array of DocumentInfos */ - public static DocumentInfo[] getConfigDocuments(ServletContext sc, + public static DocumentInfo[] getConfigDocuments(URLClassLoader jsfRIClassLoader, ServletContext sc, List providers, ExecutorService executor, boolean validating) { @@ -715,7 +759,7 @@ public static DocumentInfo[] getConfigDocuments(ServletContext sc, Collection l = t.get(); for (URI u : l) { FutureTask d = - new FutureTask(new ParseTask(sc, validating, u)); + new FutureTask(new ParseTask(jsfRIClassLoader, sc, validating, u)); docTasks.add(d); if (executor != null) { executor.execute(d); @@ -765,25 +809,6 @@ private static ExecutorService createExecutorService() { } - -// /** -// * @param throwable Throwable -// * @return the root cause of this error -// */ -// private Throwable unwind(Throwable throwable) { -// -// Throwable t = null; -// if (throwable != null) { -// t = unwind(throwable.getCause()); -// if (t == null) { -// t = throwable; -// } -// } -// return t; -// -// } - - /** * Calls through to {@link javax.faces.FactoryFinder#releaseFactories()} * ignoring any exceptions. @@ -936,12 +961,37 @@ public Map,Set>> call() throws Exception { *

*/ private static class ParseTask implements Callable { - private static final String JAVAEE_SCHEMA_LEGACY_DEFAULT_NS = - "http://java.sun.com/xml/ns/javaee"; - private static final String JAVAEE_SCHEMA_DEFAULT_NS = - "http://xmlns.jcp.org/xml/ns/javaee"; - private static final String EMPTY_FACES_CONFIG = - "com/sun/faces/empty-faces-config.xml"; + + private static final String EMPTY_FACES_CONFIG = "com/sun/faces/empty-faces-config.xml"; + + private static final Map VERSION_FACES_SCHEMA_FACES_MAPPING; + static { + Map map = new HashMap<>(); + map.put("4.0", "com/sun/faces/web-facesconfig_4_0.xsd"); + map.put("3.0", "com/sun/faces/web-facesconfig_3_0.xsd"); + map.put("2.3", "com/sun/faces/web-facesconfig_2_3.xsd"); + map.put("2.2", "com/sun/faces/web-facesconfig_2_2.xsd"); + map.put("2.1", "com/sun/faces/web-facesconfig_2_1.xsd"); + map.put("2.0", "com/sun/faces/web-facesconfig_2_0.xsd"); + map.put("1.2", "com/sun/faces/web-facesconfig_1_2.xsd"); + VERSION_FACES_SCHEMA_FACES_MAPPING = Collections.unmodifiableMap(map); + } + + private static final Map VERSION_FACES_SCHEMA_FACELET_TAGLIB_MAPPING; + static { + Map map = new HashMap<>(); + map.put("4.0", "com/sun/faces/web-facelettaglibrary_4_0.xsd"); + map.put("3.0", "com/sun/faces/web-facelettaglibrary_3_0.xsd"); + map.put("2.3", "com/sun/faces/web-facelettaglibrary_2_3.xsd"); + map.put("2.2", "com/sun/faces/web-facelettaglibrary_2_2.xsd"); + map.put("2.1", "com/sun/faces/web-facelettaglibrary_2_0.xsd"); + map.put("2.0", "com/sun/faces/web-facelettaglibrary_2_0.xsd"); + VERSION_FACES_SCHEMA_FACELET_TAGLIB_MAPPING = Collections.unmodifiableMap(map); + } + + private static final Map> SCHEMA_CACHE = new HashMap<>(); + + private URLClassLoader jsfRIClassLoader; private ServletContext servletContext; private URI documentURI; private DocumentBuilderFactory factory; @@ -960,12 +1010,12 @@ private static class ParseTask implements Callable { * @param documentURI a URL to the configuration resource to be parsed * @throws Exception general error */ - public ParseTask(ServletContext servletContext, boolean validating, URI documentURI) + public ParseTask(URLClassLoader jsfRIClassLoader, ServletContext servletContext, boolean validating, URI documentURI) throws Exception { + this.jsfRIClassLoader = jsfRIClassLoader; this.servletContext = servletContext; this.documentURI = documentURI; this.validating = validating; - } @@ -1059,72 +1109,27 @@ private Document getDocument() throws Exception { * we need to transform it to reference a special 1.1 schema before validating. */ Node documentElement = ((Document) domSource.getNode()).getDocumentElement(); - if (JAVAEE_SCHEMA_DEFAULT_NS.equals(documentNS)) { - Attr version = (Attr) - documentElement.getAttributes().getNamedItem("version"); - Schema schema; - if (version != null) { - String versionStr = version.getValue(); - if ("2.3".equals(versionStr)) { - if ("facelet-taglib".equals(documentElement.getLocalName())) { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACELET_TAGLIB_22); - } else { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACES_23); - } - } else if ("2.2".equals(versionStr)) { - if ("facelet-taglib".equals(documentElement.getLocalName())) { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACELET_TAGLIB_22); - } else { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACES_22); - } - } else { - throw new ConfigurationException("Unknown Schema version: " + versionStr); - } - DocumentBuilder builder = getBuilderForSchema(schema); - if (builder.isValidating()) { - builder.getSchema().newValidator().validate(domSource); - returnDoc = ((Document) domSource.getNode()); - } else { - returnDoc = ((Document) domSource.getNode()); - } - } else { + Schema schema = null; + + if (isKnownNamespace(documentNS)) { + Attr versionAttr = (Attr) documentElement.getAttributes().getNamedItem("version"); + if (versionAttr == null) { // this shouldn't happen, but... throw new ConfigurationException("No document version available."); } - } else if (JAVAEE_SCHEMA_LEGACY_DEFAULT_NS.equals(documentNS)) { - Attr version = (Attr) - documentElement.getAttributes().getNamedItem("version"); - Schema schema; - if (version != null) { - String versionStr = version.getValue(); - if ("2.0".equals(versionStr)) { - if ("facelet-taglib".equals(documentElement.getLocalName())) { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACELET_TAGLIB_20); - } else { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACES_20); - } - } else if ("2.1".equals(versionStr)) { - if ("facelet-taglib".equals(documentElement.getLocalName())) { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACELET_TAGLIB_20); - } else { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACES_21); - } - } else if ("1.2".equals(versionStr)) { - schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACES_12); - } else { - throw new ConfigurationException("Unknown Schema version: " + versionStr); - } - DocumentBuilder builder = getBuilderForSchema(schema); - if (builder.isValidating()) { - builder.getSchema().newValidator().validate(domSource); - returnDoc = ((Document) domSource.getNode()); - } else { - returnDoc = ((Document) domSource.getNode()); - } + String version = versionAttr.getValue(); + + String schemaResourceName; + if ("facelet-taglib".equals(documentElement.getLocalName())) { + schemaResourceName = VERSION_FACES_SCHEMA_FACELET_TAGLIB_MAPPING.get(version); } else { - // this shouldn't happen, but... - throw new ConfigurationException("No document version available."); + schemaResourceName = VERSION_FACES_SCHEMA_FACES_MAPPING.get(version); } + if (schemaResourceName == null) { + throw new ConfigurationException("Unknown Schema version: " + version); + } + + schema = getSchema(schemaResourceName); } else { DOMResult domResult = new DOMResult(); Transformer transformer = getTransformer(documentNS); @@ -1135,22 +1140,21 @@ private Document getDocument() throws Exception { ((Document) domResult.getNode()) .setDocumentURI(((Document) domSource .getNode()).getDocumentURI()); - Schema schemaToApply; if (FACES_CONFIG_1_X_DEFAULT_NS.equals(documentNS)) { - schemaToApply = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACES_11); + schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACES_11); } else if (FACELETS_1_0_DEFAULT_NS.equals(documentNS)) { - schemaToApply = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACELET_TAGLIB_20); + schema = DbfFactory.getSchema(servletContext, DbfFactory.FacesSchema.FACELET_TAGLIB_20); } else { throw new IllegalStateException(); } - DocumentBuilder builder = getBuilderForSchema(schemaToApply); - if (builder.isValidating()) { - builder.getSchema().newValidator().validate(new DOMSource(domResult.getNode())); - returnDoc = (Document) domResult.getNode(); - } else { - returnDoc = (Document) domResult.getNode(); - } } + + DocumentBuilder builder = getBuilderForSchema(schema); + if (builder.isValidating()) { + builder.getSchema().newValidator().validate(domSource); + } + + returnDoc = ((Document) domSource.getNode()); } else { returnDoc = doc; } @@ -1164,7 +1168,28 @@ private Document getDocument() throws Exception { returnDoc.getDocumentElement().getAttributes().setNamedItem(webInf); } return returnDoc; + } + + private Schema getSchema(String schemaResourceName) throws SAXException { + URL[] schemaResourceSource = jsfRIClassLoader.getURLs(); + if (schemaResourceSource.length == 0) { + throw new IllegalArgumentException("Expected URLClassLoader to have only one entry"); + } + + String id = Stream.of(schemaResourceSource).map(URL::toString).collect(Collectors.joining("+")); + WeakReference schema = SCHEMA_CACHE.get(id); + if (schema == null || schema.get() == null) { + SchemaFactory schemaFactory = SchemaFactory.newDefaultInstance(); + schema = new WeakReference<>(schemaFactory.newSchema(jsfRIClassLoader.getResource(schemaResourceName))); + + SCHEMA_CACHE.put(id, schema); + } + + return schema.get(); + } + private boolean isKnownNamespace(String namespace) { + return Stream.of(JsfNamespaces.values()).map(value -> value.getNamespace(JsfNamespaces.Type.TAGLIB)).anyMatch(namespace::equals); } private boolean streamIsZeroLengthOrEmpty(InputStream is) throws IOException { diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/mojarra/FaceletsTaglibConfigProcessor.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/mojarra/FaceletsTaglibConfigProcessor.java index a919bd98b892..9d730b1fd89f 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/mojarra/FaceletsTaglibConfigProcessor.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/facelets/mojarra/FaceletsTaglibConfigProcessor.java @@ -18,12 +18,10 @@ */ package org.netbeans.modules.web.jsf.editor.facelets.mojarra; -import com.sun.faces.config.ConfigurationException; import org.netbeans.modules.web.jsf.editor.facelets.*; import com.sun.faces.config.DocumentInfo; import com.sun.faces.config.processor.AbstractConfigProcessor; import com.sun.faces.facelets.tag.TagLibraryImpl; -import com.sun.faces.facelets.tag.jsf.CompositeComponentTagLibrary; import com.sun.faces.util.FacesLogger; import com.sun.faces.facelets.util.ReflectionUtil; import org.netbeans.modules.web.jsf.editor.facelets.FaceletsLibrarySupport.Compiler; @@ -37,9 +35,13 @@ import java.net.URL; import java.net.MalformedURLException; import java.lang.reflect.Method; +import java.util.LinkedHashSet; +import java.util.Set; import javax.faces.FacesException; import javax.servlet.ServletContext; +import org.netbeans.modules.web.jsfapi.api.DefaultLibraryInfo; +import org.netbeans.modules.web.jsfapi.api.LibraryInfo; import org.w3c.dom.Document; /** @@ -282,9 +284,29 @@ private void processTagLibrary(ServletContext sc, DocumentInfo info, Element doc NodeList tags = documentElement.getElementsByTagNameNS(namespace, TAG); NodeList functions = documentElement.getElementsByTagNameNS(namespace, FUNCTION); + + Set taglibNamespaces = new LinkedHashSet<>(); + taglibNamespaces.add(taglibNamespace); + + // Try to find all prior valid namespaces. This only works since namespaces are stored as + LibraryInfo libraryInfo = DefaultLibraryInfo.forNamespace(taglibNamespace); + if (libraryInfo != null) { + boolean found = false; + for (String validNamespace : libraryInfo.getValidNamespaces()) { + if (validNamespace.equals(taglibNamespace)) { + found = true; + continue; + } + if (found) { + taglibNamespaces.add(validNamespace); + } + } + } + + //TODO ASBACHB: CHECK HOW TO FIX FaceletsLibrary taglibrary = compositeLibraryName != null - ? new CompositeComponentLibrary(support, compositeLibraryName, taglibNamespace, sourceUrl) - : new FaceletsLibrary(support, taglibNamespace, sourceUrl); + ? new CompositeComponentLibrary(support, compositeLibraryName, taglibNamespaces, sourceUrl) + : new FaceletsLibrary(support, taglibNamespaces, sourceUrl); processTags(sc, documentElement, tags, taglibrary); processFunctions(sc, functions, taglibrary); diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/hints/FixLibDeclaration.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/hints/FixLibDeclaration.java index 99b5dd75b3aa..f28c70ba6390 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/hints/FixLibDeclaration.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/hints/FixLibDeclaration.java @@ -34,29 +34,22 @@ public class FixLibDeclaration implements HintFix{ private final String nsPrefix; private final Library lib; private final Document doc; - private final boolean isJsf22Plus; - public FixLibDeclaration(Document doc, String nsPrefix, Library lib, boolean isJsf22Plus) { + public FixLibDeclaration(Document doc, String nsPrefix, Library lib) { this.doc = doc; this.nsPrefix = nsPrefix; this.lib = lib; - this.isJsf22Plus = isJsf22Plus; } @Override public String getDescription() { - String namespace; - if (isJsf22Plus || lib.getLegacyNamespace() == null) { - namespace = lib.getNamespace(); - } else { - namespace = lib.getLegacyNamespace(); - } + String namespace = lib.getNamespace(); return NbBundle.getMessage(FixLibDeclaration.class, "MSG_FixLibDeclaration", nsPrefix, namespace); //NOI18N } @Override public void implement() throws Exception { - LibraryUtils.importLibrary(doc, lib, nsPrefix, isJsf22Plus); + LibraryUtils.importLibrary(doc, lib, nsPrefix); } @Override diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/hints/LibraryDeclarationChecker.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/hints/LibraryDeclarationChecker.java index 1cf2e332ad46..84b117254fa8 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/hints/LibraryDeclarationChecker.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/hints/LibraryDeclarationChecker.java @@ -26,9 +26,12 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; +import static java.util.function.Predicate.not; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Collectors; import javax.swing.text.BadLocationException; import org.netbeans.api.lexer.Language; import org.netbeans.api.lexer.TokenHierarchy; @@ -59,7 +62,6 @@ import org.netbeans.modules.web.jsf.editor.JsfUtils; import org.netbeans.modules.web.jsf.editor.PositionRange; import org.netbeans.modules.web.jsfapi.api.DefaultLibraryInfo; -import org.netbeans.modules.web.jsfapi.api.JsfVersion; import org.netbeans.modules.web.jsfapi.api.Library; import org.netbeans.modules.web.jsfapi.api.NamespaceUtils; import org.openide.util.Exceptions; @@ -115,8 +117,13 @@ private void checkLibraryDeclarations(final List hints, final RuleContext final Map namespace2Attribute = new HashMap<>(); Node root = result.root(); if (root.children().isEmpty()) { - Node faceletsRoot = result.root(DefaultLibraryInfo.FACELETS.getLegacyNamespace()); - root = !faceletsRoot.children().isEmpty() ? faceletsRoot : result.root(DefaultLibraryInfo.FACELETS.getNamespace()); + root = DefaultLibraryInfo.FACELETS.getValidNamespaces().stream() + .filter(not(DefaultLibraryInfo.FACELETS.getNamespace()::equals)) + .map(result::root) + .filter(Objects::nonNull) + .filter(node -> node.children().isEmpty()) + .findFirst() + .orElse(result.root(DefaultLibraryInfo.FACELETS.getNamespace())); } final CharSequence docText = getSourceText(snapshot.getSource()); final String jsfNsPrefix = NamespaceUtils.getForNs(result.getNamespaces(), DefaultLibraryInfo.JSF.getNamespace()); @@ -176,7 +183,7 @@ public void visit(Element node) { List fixes = new ArrayList<>(); Set libs = getLibsByPrefixes(context, getUndeclaredNamespaces(undeclaredNodes)); for (Library lib : libs) { - FixLibDeclaration fix = new FixLibDeclaration(context.doc, lib.getDefaultPrefix(), lib, jsfSupport.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + FixLibDeclaration fix = new FixLibDeclaration(context.doc, lib.getDefaultPrefix(), lib); fixes.add(fix); } @@ -214,7 +221,7 @@ public void visit(Element node) { if (lib != null) { // http://java.sun.com/jsf/passthrough usage needs to be resolved on base of all declared libraries if (!(DefaultLibraryInfo.PASSTHROUGH.getNamespace().equals(lib.getNamespace()) - || DefaultLibraryInfo.PASSTHROUGH.getLegacyNamespace().equals(lib.getNamespace()))) { + || DefaultLibraryInfo.PASSTHROUGH.getValidNamespaces().contains(lib.getNamespace()))) { declaredLibraries.add(lib); } } else { @@ -239,43 +246,45 @@ public void visit(Element node) { final boolean[] passthroughUsage = new boolean[1]; final Collection ranges = new ArrayList<>(); for (Library lib : declaredLibraries) { - Node rootNode = result.root(lib.getNamespace()); - if (lib.getLegacyNamespace() != null && (rootNode == null || rootNode.children().isEmpty())) { - rootNode = result.root(lib.getLegacyNamespace()); - } - if (rootNode == null) { + List nodes = lib.getValidNamespaces().stream() + .map(result::root) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (nodes.isEmpty()) { continue; //no parse result for this namespace, the namespace is not declared } final int[] usages = new int[1]; - ElementUtils.visitChildren(rootNode, new ElementVisitor() { - @Override - public void visit(Element node) { - usages[0]++; - if (declaredPassthroughOrJsf) { - OpenTag ot = (OpenTag) node; - for (Attribute attribute : ot.attributes(new AttributeFilter() { - @Override - public boolean accepts(Attribute attribute) { - return attribute.namespacePrefix() != null; - } - })) { - if (passthroughNsPrefix != null && LexerUtils.equals(passthroughNsPrefix, attribute.namespacePrefix(), true, true)) { - // http://java.sun.com/jsf/passthrough or http://xmlns.jcp.org/jsf/passthrough used - passthroughUsage[0] = true; - } else if (jsfNsPrefix != null && ot.namespacePrefix() != null - && LexerUtils.equals(jsfNsPrefix, attribute.namespacePrefix(), true, true)) { - // http://java.sun.com/jsf used at JSF-aware tag - wrongJsfNsUsages.add(attribute); + for (Node rootNode : nodes) { + ElementUtils.visitChildren(rootNode, new ElementVisitor() { + @Override + public void visit(Element node) { + usages[0]++; + if (declaredPassthroughOrJsf) { + OpenTag ot = (OpenTag) node; + for (Attribute attribute : ot.attributes(new AttributeFilter() { + @Override + public boolean accepts(Attribute attribute) { + return attribute.namespacePrefix() != null; + } + })) { + if (passthroughNsPrefix != null && LexerUtils.equals(passthroughNsPrefix, attribute.namespacePrefix(), true, true)) { + // http://java.sun.com/jsf/passthrough or http://xmlns.jcp.org/jsf/passthrough used + passthroughUsage[0] = true; + } else if (jsfNsPrefix != null && ot.namespacePrefix() != null + && LexerUtils.equals(jsfNsPrefix, attribute.namespacePrefix(), true, true)) { + // http://java.sun.com/jsf used at JSF-aware tag + wrongJsfNsUsages.add(attribute); + } } } } - } - }, ElementType.OPEN_TAG); + }, ElementType.OPEN_TAG); + } usages[0] += isFunctionLibraryPrefixUsedInEL(context, lib, docText) ? 1 : 0; // http://java.sun.com/jsf namespace handling - usages[0] += (DefaultLibraryInfo.JSF.getNamespace().equals(lib.getNamespace()) || DefaultLibraryInfo.JSF.getLegacyNamespace().equals(lib.getNamespace())) && jsfUsage[0] ? 1 : 0; + usages[0] += DefaultLibraryInfo.JSF.getValidNamespaces().contains(lib.getNamespace()) && jsfUsage[0] ? 1 : 0; if (usages[0] == 0) { //unused declaration diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/index/CompositeComponentModel.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/index/CompositeComponentModel.java index c1962c77569b..2ce6784ce4ea 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/index/CompositeComponentModel.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/index/CompositeComponentModel.java @@ -40,6 +40,7 @@ import org.netbeans.modules.parsing.spi.indexing.support.IndexResult; import org.netbeans.modules.web.api.webmodule.WebModule; import org.netbeans.modules.web.common.api.LexerUtils; +import org.netbeans.modules.web.jsfapi.api.JsfVersion; import org.netbeans.modules.web.jsfapi.spi.LibraryUtils; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; @@ -205,7 +206,7 @@ public String storeToIndex(IndexDocument document) { dsb.append(encode(interfaceShortDescription != null ? interfaceShortDescription : NOT_AVAILABLE_VALUE)); document.addPair(INTERFACE_DESCRIPTION_KEY, dsb.toString(), false, true); - return LibraryUtils.getCompositeLibraryURL(libraryName, true); // the return value looks to be used nowhere + return LibraryUtils.getCompositeLibraryURL(libraryName, JsfVersion.JSF_4_0); // the return value looks to be used nowhere } private String getLibraryPath() { @@ -302,9 +303,9 @@ public static class Factory extends JsfPageModelFactory { @Override public JsfPageModel getModel(HtmlParserResult result) { - Node node = result.root(LibraryUtils.COMPOSITE_LIBRARY_NS); + Node node = result.root(LibraryUtils.COMPOSITE_LIBRARY_JCP_NS); if (node == null || node.children().isEmpty()) { - node = result.root(LibraryUtils.COMPOSITE_LIBRARY_LEGACY_NS); + node = result.root(LibraryUtils.COMPOSITE_LIBRARY_SUN_NS); } if (node == null) { return null; //no composite library declaration diff --git a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/index/ResourcesMappingModel.java b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/index/ResourcesMappingModel.java index 50dcd9862781..05cd10e07515 100644 --- a/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/index/ResourcesMappingModel.java +++ b/enterprise/web.jsf.editor/src/org/netbeans/modules/web/jsf/editor/index/ResourcesMappingModel.java @@ -174,10 +174,10 @@ public JsfPageModel loadFromIndex(IndexResult result) { private Collection getResourcesDefinedByJsfComponents(HtmlParserResult result) { final List resources = new ArrayList<>(); - Node node = result.root(DefaultLibraryInfo.HTML.getNamespace()); - if (node == null || node.children().isEmpty()) { - node = result.root(DefaultLibraryInfo.HTML.getLegacyNamespace()); - } + Node node = DefaultLibraryInfo.HTML.getValidNamespaces().stream() + .map(result::root) + .findFirst() + .orElse(null); if (node == null || node.children().isEmpty()) { return resources; //no HTML Basic component in the page } diff --git a/enterprise/web.jsf.editor/test/unit/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrarySupportTest.java b/enterprise/web.jsf.editor/test/unit/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrarySupportTest.java index bb6f8301cbb6..d030f5e4f016 100644 --- a/enterprise/web.jsf.editor/test/unit/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrarySupportTest.java +++ b/enterprise/web.jsf.editor/test/unit/src/org/netbeans/modules/web/jsf/editor/facelets/FaceletsLibrarySupportTest.java @@ -31,7 +31,6 @@ import org.netbeans.modules.web.jsfapi.api.Attribute; import org.netbeans.modules.web.jsfapi.api.Function; import org.netbeans.modules.web.jsfapi.api.JsfSupport; -import org.netbeans.modules.web.jsfapi.api.JsfVersion; import org.netbeans.modules.web.jsfapi.api.Library; import org.netbeans.modules.web.jsfapi.api.LibraryComponent; import org.netbeans.modules.web.jsfapi.api.LibraryType; @@ -67,7 +66,7 @@ protected void setUp() throws Exception { public void testCompositeComponentLibraryWithoutDescriptor() { JsfSupportImpl instance = getJsfSupportImpl(); - String ezCompLibraryNS = LibraryUtils.getCompositeLibraryURL("ezcomp", instance.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + String ezCompLibraryNS = LibraryUtils.getCompositeLibraryURL("ezcomp", instance.getJsfVersion()); Library ezcompLib = instance.getLibrary(ezCompLibraryNS); assertNotNull(String.format("Library %s not found!", ezCompLibraryNS), ezcompLib); @@ -116,7 +115,7 @@ public void testCompositeComponentLibraryWithDescriptor() { assertEquals("ezcomp2", ezcompLib.getDefaultPrefix()); assertSame(LibraryType.COMPOSITE, ezcompLib.getType()); - String ezCompLibraryDefaultNS = LibraryUtils.getCompositeLibraryURL("ezcomp2", instance.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + String ezCompLibraryDefaultNS = LibraryUtils.getCompositeLibraryURL("ezcomp2", instance.getJsfVersion()); assertEquals(ezCompLibraryDefaultNS, ezcompLib.getDefaultNamespace()); assertEquals(ezCompLibraryNS, ezcompLib.getNamespace()); Tag t = cclib.getLibraryDescriptor().getTags().get("test"); @@ -202,7 +201,7 @@ public void testCompositeComponentLibraryWithoutDescriptorFromLibraryProject() { // debugLibraries(instance); - String libNs = LibraryUtils.getCompositeLibraryURL("cclib", instance.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + String libNs = LibraryUtils.getCompositeLibraryURL("cclib", instance.getJsfVersion()); Library lib = instance.getLibrary(libNs); assertNotNull(String.format("Library %s not found!", libNs), lib); @@ -241,7 +240,7 @@ public void testCompositeComponentLibraryWithDescriptorFromLibraryProject() { assertEquals("cclib2", lib.getDefaultPrefix()); assertSame(LibraryType.COMPOSITE, lib.getType()); - String ezCompLibraryDefaultNS = LibraryUtils.getCompositeLibraryURL("cclib2", instance.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + String ezCompLibraryDefaultNS = LibraryUtils.getCompositeLibraryURL("cclib2", instance.getJsfVersion()); assertEquals(ezCompLibraryDefaultNS, lib.getDefaultNamespace()); assertEquals(libNs, lib.getNamespace()); Tag t = cclib.getLibraryDescriptor().getTags().get("cc2"); diff --git a/enterprise/web.jsf.icefaces/nbproject/project.xml b/enterprise/web.jsf.icefaces/nbproject/project.xml index af3ac4c3c8b9..fd6a131b996d 100644 --- a/enterprise/web.jsf.icefaces/nbproject/project.xml +++ b/enterprise/web.jsf.icefaces/nbproject/project.xml @@ -110,8 +110,8 @@ - 1 - 1.44 + 2 + 2.0 @@ -119,8 +119,8 @@ - 1 - 1.17 + 2 + 2.0 diff --git a/enterprise/web.jsf.kit/nbproject/project.xml b/enterprise/web.jsf.kit/nbproject/project.xml index 6b903f3c0eff..83b6f2d9cd77 100644 --- a/enterprise/web.jsf.kit/nbproject/project.xml +++ b/enterprise/web.jsf.kit/nbproject/project.xml @@ -34,8 +34,8 @@ org.netbeans.modules.web.jsf - 1 - 1.51 + 2 + 2.0 diff --git a/enterprise/web.jsf.navigation/nbproject/project.xml b/enterprise/web.jsf.navigation/nbproject/project.xml index b9b624ab24a6..53d4a70c3d65 100644 --- a/enterprise/web.jsf.navigation/nbproject/project.xml +++ b/enterprise/web.jsf.navigation/nbproject/project.xml @@ -108,8 +108,8 @@ - 1 - 1.6.0.1.1 + 2 + 2.0 diff --git a/enterprise/web.jsf.richfaces/nbproject/project.xml b/enterprise/web.jsf.richfaces/nbproject/project.xml index 3c3cb60f2279..34d323be5a56 100644 --- a/enterprise/web.jsf.richfaces/nbproject/project.xml +++ b/enterprise/web.jsf.richfaces/nbproject/project.xml @@ -101,8 +101,8 @@ - 1 - 1.44 + 2 + 2.0 @@ -110,8 +110,8 @@ - 1 - 1.14 + 2 + 2.0 diff --git a/enterprise/web.jsf/manifest.mf b/enterprise/web.jsf/manifest.mf index 1a1da359e2dd..b06f43dc0ee0 100644 --- a/enterprise/web.jsf/manifest.mf +++ b/enterprise/web.jsf/manifest.mf @@ -1,5 +1,5 @@ Manifest-Version: 1.0 -OpenIDE-Module: org.netbeans.modules.web.jsf/1 +OpenIDE-Module: org.netbeans.modules.web.jsf/2 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/web/jsf/resources/Bundle.properties OpenIDE-Module-Layer: org/netbeans/modules/web/jsf/resources/layer.xml OpenIDE-Module-Implementation-Version: 3 diff --git a/enterprise/web.jsf/nbproject/org-netbeans-modules-web-jsf.sig b/enterprise/web.jsf/nbproject/org-netbeans-modules-web-jsf.sig index aad67e3c82bb..59b02c8db47d 100644 --- a/enterprise/web.jsf/nbproject/org-netbeans-modules-web-jsf.sig +++ b/enterprise/web.jsf/nbproject/org-netbeans-modules-web-jsf.sig @@ -1,5 +1,5 @@ #Signature file v4.1 -#Version 1.90.0 +#Version 2.0 CLSS public abstract interface java.beans.PropertyChangeListener intf java.util.EventListener @@ -122,9 +122,9 @@ intf org.netbeans.modules.web.jsfapi.api.Library meth public java.lang.String getDefaultNamespace() meth public java.lang.String getDefaultPrefix() meth public java.lang.String getDisplayName() -meth public java.lang.String getLegacyNamespace() meth public java.lang.String getNamespace() meth public java.util.Collection getComponents() +meth public java.util.Set getValidNamespaces() meth public org.netbeans.modules.web.jsfapi.api.LibraryComponent getComponent(java.lang.String) meth public org.netbeans.modules.web.jsfapi.api.LibraryType getType() meth public void addComponent(org.netbeans.modules.web.jsfapi.api.LibraryComponent) @@ -1683,9 +1683,8 @@ meth public abstract org.netbeans.modules.web.jsfapi.api.Tag getTag() CLSS public abstract interface org.netbeans.modules.web.jsfapi.api.LibraryInfo meth public abstract java.lang.String getDefaultPrefix() meth public abstract java.lang.String getDisplayName() -meth public abstract java.lang.String getLegacyNamespace() - anno 0 org.netbeans.api.annotations.common.CheckForNull() meth public abstract java.lang.String getNamespace() +meth public abstract java.util.Set getValidNamespaces() CLSS public abstract org.netbeans.modules.xml.xam.AbstractModelFactory<%0 extends org.netbeans.modules.xml.xam.Model> cons public init() diff --git a/enterprise/web.jsf/nbproject/project.properties b/enterprise/web.jsf/nbproject/project.properties index bee0dcbbc072..fdcc4ed5b82d 100644 --- a/enterprise/web.jsf/nbproject/project.properties +++ b/enterprise/web.jsf/nbproject/project.properties @@ -17,7 +17,7 @@ javac.compilerargs=-Xlint -Xlint:-serial javac.source=1.8 -spec.version.base=1.90.0 +spec.version.base=2.0 test.config.stable.includes=\ **/JSFSupportSuite.class diff --git a/enterprise/web.jsf/nbproject/project.xml b/enterprise/web.jsf/nbproject/project.xml index f7dcc46e2240..8d2386c67773 100644 --- a/enterprise/web.jsf/nbproject/project.xml +++ b/enterprise/web.jsf/nbproject/project.xml @@ -482,8 +482,8 @@ - 1 - 1.27 + 2 + 2.0 diff --git a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/api/editor/JsfFacesComponentsProvider.java b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/api/editor/JsfFacesComponentsProvider.java index 0131767d0c70..46dbbb6a4b46 100644 --- a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/api/editor/JsfFacesComponentsProvider.java +++ b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/api/editor/JsfFacesComponentsProvider.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.netbeans.api.java.classpath.ClassPath; @@ -168,8 +169,8 @@ public String getDisplayName() { } @Override - public String getLegacyNamespace() { - return null; + public Set getValidNamespaces() { + return Collections.emptySortedSet(); } } diff --git a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/facelets/resources/templates/simpleFacelets.template b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/facelets/resources/templates/simpleFacelets.template index 3d890c22672e..756b9bbfd8e9 100644 --- a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/facelets/resources/templates/simpleFacelets.template +++ b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/facelets/resources/templates/simpleFacelets.template @@ -1,6 +1,9 @@ -<#if isJSF22?? || isJSF30??> +<#if isJSF40??> + +<#elseif isJSF22?? || isJSF30??> <#elseif isJSF20??> @@ -9,7 +12,7 @@ <#else> -<#if isJSF20?? || isJSF22?? || isJSF30??> +<#if isJSF20?? || isJSF22?? || isJSF30?? || isJSF40??> Facelet Title diff --git a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/palette/items/JsfLibrariesSupport.java b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/palette/items/JsfLibrariesSupport.java index 22a971e20447..80a1e652ab6b 100644 --- a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/palette/items/JsfLibrariesSupport.java +++ b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/palette/items/JsfLibrariesSupport.java @@ -23,7 +23,10 @@ import java.util.EnumMap; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; +import static java.util.function.Predicate.not; +import java.util.stream.Collectors; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import org.netbeans.modules.csl.api.DataLoadersBridge; @@ -106,14 +109,13 @@ public void run(ResultIterator resultIterator) throws Exception { Library lib = jsfs.getLibrary(libraryInfo.getNamespace()); libraryimport.lib = lib; - Collection prefixes = ns2prefixes.get(libraryInfo.getNamespace()); - if (prefixes == null && libraryInfo.getLegacyNamespace() != null) { - prefixes = ns2prefixes.get(libraryInfo.getLegacyNamespace()); - } - if (libraryInfo.getLegacyNamespace() != null && ns2prefixes.get(libraryInfo.getLegacyNamespace()) != null) { - prefixes.addAll(ns2prefixes.get(libraryInfo.getLegacyNamespace())); - } - libraryimport.declaredPrefix = prefixes != null && !prefixes.isEmpty() ? prefixes.iterator().next() : null; + libraryimport.declaredPrefix = libraryInfo.getValidNamespaces().stream() + .map(ns2prefixes::get) + .filter(Objects::nonNull) + .filter(not(Collection::isEmpty)) + .map(c -> c.iterator().next()) + .findFirst() + .orElse(null); map.put(libraryInfo, libraryimport); } @@ -122,7 +124,7 @@ public void run(ResultIterator resultIterator) throws Exception { } public void importLibraries(DefaultLibraryInfo... linfos) { - Map toimport = new HashMap(); + Map toimport = new HashMap<>(); for (DefaultLibraryInfo li : linfos) { LibraryImport limport = map.get(li); assert limport != null; @@ -131,7 +133,7 @@ public void importLibraries(DefaultLibraryInfo... linfos) { toimport.put(limport.lib, null); //lets use the default prefix } } - LibraryUtils.importLibrary(tc.getDocument(), toimport, jsfs.getJsfVersion().isAtLeast(JsfVersion.JSF_2_2)); + LibraryUtils.importLibrary(tc.getDocument(), toimport); } /** @return the library default prefix in the case it hasn't been declared yet or the declared prefix */ diff --git a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/palette/items/PrefixResolver.java b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/palette/items/PrefixResolver.java index 6932325ad36d..e836d489a0e4 100644 --- a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/palette/items/PrefixResolver.java +++ b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/palette/items/PrefixResolver.java @@ -34,7 +34,7 @@ public PrefixResolver(JsfLibrariesSupport jls) { public String getPrefixForNS(String namespace, String fallbackPrefix) { for (DefaultLibraryInfo dli : DefaultLibraryInfo.values()) { - if (dli.getNamespace().equals(namespace) || (dli.getLegacyNamespace() != null && dli.getLegacyNamespace().equals(namespace))) { + if (dli.getValidNamespaces().contains(namespace)) { return jls.getLibraryPrefix(dli); } } diff --git a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/wizards/TemplateClientPanelVisual.java b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/wizards/TemplateClientPanelVisual.java index f9b4341a96e3..3abe35ebf0b8 100644 --- a/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/wizards/TemplateClientPanelVisual.java +++ b/enterprise/web.jsf/src/org/netbeans/modules/web/jsf/wizards/TemplateClientPanelVisual.java @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -395,26 +396,23 @@ public void run(ResultIterator resultIterator) throws Exception { Result result = resultIterator.getParserResult(0); if (result.getSnapshot().getMimeType().equals("text/html")) { HtmlParserResult htmlResult = (HtmlParserResult)result; - String ns = null; - if (htmlResult.getNamespaces().containsKey(DefaultLibraryInfo.FACELETS.getNamespace())) { - ns = DefaultLibraryInfo.FACELETS.getNamespace(); - } else if (htmlResult.getNamespaces().containsKey(DefaultLibraryInfo.FACELETS.getLegacyNamespace())) { - ns = DefaultLibraryInfo.FACELETS.getLegacyNamespace(); - } - if (ns != null) { - String faceletsPrefix = htmlResult.getNamespaces().get(ns); - List foundNodes = findValue(htmlResult.root(ns).children(OpenTag.class), faceletsPrefix + ":insert", new ArrayList()); // NOI18N - - for (OpenTag node : foundNodes) { - Attribute attr = node.getAttribute(VALUE_NAME); - if (attr !=null) { - String value = attr.unquotedValue().toString(); - if (value != null && !"".equals(value)) { //NOI18N - templateData.add(value); - } - } - } + String ns = DefaultLibraryInfo.FACELETS.getValidNamespaces().stream() + .filter(htmlResult.getNamespaces()::containsKey) + .findFirst() + .orElse(null); + if (ns == null) { + return; } + String faceletsPrefix = htmlResult.getNamespaces().get(ns); + List foundNodes = findValue(htmlResult.root(ns).children(OpenTag.class), faceletsPrefix + ":insert", new ArrayList()); // NOI18N + + foundNodes.stream() + .map(node -> node.getAttribute(VALUE_NAME)) + .filter(Objects::nonNull) + .map(Attribute::unquotedValue) + .filter(value -> value != null && !"".equals(value)) + .map(CharSequence::toString) + .forEach(templateData::add); } } }); diff --git a/enterprise/web.jsf20/nbproject/project.xml b/enterprise/web.jsf20/nbproject/project.xml index 3acf2fdb840c..f34a3cebcad6 100644 --- a/enterprise/web.jsf20/nbproject/project.xml +++ b/enterprise/web.jsf20/nbproject/project.xml @@ -39,8 +39,8 @@ - 1 - 1.21 + 2 + 2.0 diff --git a/enterprise/web.jsfapi/manifest.mf b/enterprise/web.jsfapi/manifest.mf index 36ea78a83c46..2e0b8ae0ecec 100644 --- a/enterprise/web.jsfapi/manifest.mf +++ b/enterprise/web.jsfapi/manifest.mf @@ -1,6 +1,5 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: false -OpenIDE-Module: org.netbeans.modules.web.jsfapi/1 +OpenIDE-Module: org.netbeans.modules.web.jsfapi/2 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/web/jsfapi/Bundle.properties -OpenIDE-Module-Specification-Version: 1.55 - +OpenIDE-Module-Specification-Version: 2.0.0 diff --git a/enterprise/web.jsfapi/nbproject/org-netbeans-modules-web-jsfapi.sig b/enterprise/web.jsfapi/nbproject/org-netbeans-modules-web-jsfapi.sig index f0fc54ecf99c..6658bc412f37 100644 --- a/enterprise/web.jsfapi/nbproject/org-netbeans-modules-web-jsfapi.sig +++ b/enterprise/web.jsfapi/nbproject/org-netbeans-modules-web-jsfapi.sig @@ -1,5 +1,5 @@ #Signature file v4.1 -#Version 1.55 +#Version 2.0 CLSS public abstract interface java.io.Serializable @@ -109,19 +109,37 @@ fld public final static org.netbeans.modules.web.jsfapi.api.DefaultLibraryInfo P intf org.netbeans.modules.web.jsfapi.api.LibraryInfo meth public java.lang.String getDefaultPrefix() meth public java.lang.String getDisplayName() -meth public java.lang.String getLegacyNamespace() meth public java.lang.String getNamespace() +meth public java.util.Set getValidNamespaces() meth public static org.netbeans.modules.web.jsfapi.api.DefaultLibraryInfo valueOf(java.lang.String) meth public static org.netbeans.modules.web.jsfapi.api.DefaultLibraryInfo[] values() meth public static org.netbeans.modules.web.jsfapi.api.LibraryInfo forNamespace(java.lang.String) supr java.lang.Enum -hfds ALL_INFOS,defaultPrefix,displayName,namespace +hfds allValidNamespaces,defaultPrefix,displayName CLSS public abstract interface org.netbeans.modules.web.jsfapi.api.Function meth public abstract java.lang.String getDescription() meth public abstract java.lang.String getName() meth public abstract java.lang.String getSignature() +CLSS public final !enum org.netbeans.modules.web.jsfapi.api.JsfNamespaces +fld public final static org.netbeans.modules.web.jsfapi.api.JsfNamespaces JAKARTA_EE_NS +fld public final static org.netbeans.modules.web.jsfapi.api.JsfNamespaces JAVA_SUN_COM_NS +fld public final static org.netbeans.modules.web.jsfapi.api.JsfNamespaces XMLNS_JCP_ORG_NS +innr public final static !enum Type +meth public java.lang.String getNamespace(org.netbeans.modules.web.jsfapi.api.JsfNamespaces$Type) +meth public static org.netbeans.modules.web.jsfapi.api.JsfNamespaces valueOf(java.lang.String) +meth public static org.netbeans.modules.web.jsfapi.api.JsfNamespaces[] values() +supr java.lang.Enum +hfds namespaces + +CLSS public final static !enum org.netbeans.modules.web.jsfapi.api.JsfNamespaces$Type + outer org.netbeans.modules.web.jsfapi.api.JsfNamespaces +fld public final static org.netbeans.modules.web.jsfapi.api.JsfNamespaces$Type TAGLIB +meth public static org.netbeans.modules.web.jsfapi.api.JsfNamespaces$Type valueOf(java.lang.String) +meth public static org.netbeans.modules.web.jsfapi.api.JsfNamespaces$Type[] values() +supr java.lang.Enum + CLSS public abstract interface org.netbeans.modules.web.jsfapi.api.JsfSupport meth public abstract java.util.Map getLibraries() meth public abstract org.netbeans.api.java.classpath.ClassPath getClassPath() @@ -181,9 +199,8 @@ meth public abstract org.netbeans.modules.web.jsfapi.api.Tag getTag() CLSS public abstract interface org.netbeans.modules.web.jsfapi.api.LibraryInfo meth public abstract java.lang.String getDefaultPrefix() meth public abstract java.lang.String getDisplayName() -meth public abstract java.lang.String getLegacyNamespace() - anno 0 org.netbeans.api.annotations.common.CheckForNull() meth public abstract java.lang.String getNamespace() +meth public abstract java.util.Set getValidNamespaces() CLSS public final !enum org.netbeans.modules.web.jsfapi.api.LibraryType anno 0 java.lang.Deprecated() @@ -202,7 +219,6 @@ fld public final static java.util.Map NS_MAPP meth public static <%0 extends java.lang.Object> {%%0} getForNs(java.util.Map,java.lang.String) anno 0 org.netbeans.api.annotations.common.CheckForNull() meth public static boolean containsNsOf(java.util.Collection,org.netbeans.modules.web.jsfapi.api.DefaultLibraryInfo) -meth public static java.util.Set getAvailableNss(java.util.Map,boolean) supr java.lang.Object CLSS public abstract interface org.netbeans.modules.web.jsfapi.api.Tag @@ -231,6 +247,9 @@ cons public init() meth public static java.util.Map getInputTextValuesMap(org.openide.filesystems.FileObject) supr java.lang.Object +CLSS public abstract interface org.netbeans.modules.web.jsfapi.spi.JsfReferenceImplementationProvider +meth public abstract java.nio.file.Path of(org.netbeans.modules.web.jsfapi.api.JsfVersion) + CLSS public org.netbeans.modules.web.jsfapi.spi.JsfSupportHandle anno 0 java.lang.Deprecated() cons public init() @@ -249,18 +268,17 @@ hfds CACHE,LOGGER CLSS public org.netbeans.modules.web.jsfapi.spi.LibraryUtils cons public init() -fld public final static java.lang.String COMPOSITE_LIBRARY_LEGACY_NS = "http://java.sun.com/jsf/composite" -fld public final static java.lang.String COMPOSITE_LIBRARY_NS = "http://xmlns.jcp.org/jsf/composite" +fld public final static java.lang.String COMPOSITE_LIBRARY_JAKARTA_NS = "jakarta.faces.composite" +fld public final static java.lang.String COMPOSITE_LIBRARY_JCP_NS = "http://xmlns.jcp.org/jsf/composite" +fld public final static java.lang.String COMPOSITE_LIBRARY_SUN_NS = "http://java.sun.com/jsf/composite" fld public final static java.lang.String XHTML_NS = "http://www.w3.org/1999/xhtml" -meth public static boolean importLibrary(javax.swing.text.Document,org.netbeans.modules.web.jsfapi.api.Library,java.lang.String,boolean) -meth public static boolean isCompositeComponentLibrary(org.netbeans.modules.web.jsfapi.api.Library) - anno 0 java.lang.Deprecated() +meth public static boolean importLibrary(javax.swing.text.Document,org.netbeans.modules.web.jsfapi.api.Library,java.lang.String) meth public static java.lang.String generateDefaultPrefix(java.lang.String) anno 0 org.netbeans.api.annotations.common.NonNull() anno 1 org.netbeans.api.annotations.common.NonNull() -meth public static java.lang.String getCompositeLibraryURL(java.lang.String,boolean) +meth public static java.lang.String getCompositeLibraryURL(java.lang.String,org.netbeans.modules.web.jsfapi.api.JsfVersion) meth public static java.util.Map getDeclaredLibraries(org.netbeans.modules.html.editor.lib.api.HtmlParsingResult) -meth public static java.util.Map importLibrary(javax.swing.text.Document,java.util.Map,boolean) +meth public static java.util.Map importLibrary(javax.swing.text.Document,java.util.Map) meth public static org.netbeans.api.project.Project[] getOpenedJSFProjects() supr java.lang.Object diff --git a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/DefaultLibraryInfo.java b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/DefaultLibraryInfo.java index 70452edbc2f7..6638cb9e577c 100644 --- a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/DefaultLibraryInfo.java +++ b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/DefaultLibraryInfo.java @@ -18,49 +18,121 @@ */ package org.netbeans.modules.web.jsfapi.api; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.stream.Stream; + public enum DefaultLibraryInfo implements LibraryInfo { // JSF 2.0, JSF 2.1 - HTML("http://xmlns.jcp.org/jsf/html", "Html Basic", "h"), //NOI18N - JSF_CORE("http://xmlns.jcp.org/jsf/core", "Jsf Core", "f"), //NOI18N - JSTL_CORE("http://xmlns.jcp.org/jsp/jstl/core", "Jstl Core", "c"), //NOI18N - JSTL_CORE_FUNCTIONS("http://xmlns.jcp.org/jsp/jstl/functions", "Jstl Core Functions", "fn"), //NOI18N - FACELETS("http://xmlns.jcp.org/jsf/facelets", "Facelets", "ui"), //NOI18N - COMPOSITE("http://xmlns.jcp.org/jsf/composite", "Composite Components", "cc"), //NOI18N + HTML( + sortedSet( + "jakarta.faces.html", + "http://xmlns.jcp.org/jsf/html", + "http://java.sun.com/jsf/html" + ), + "Html Basic", + "h" + ), //NOI18N + JSF_CORE( + sortedSet( + "jakarta.faces.core", + "http://xmlns.jcp.org/jsf/core", + "http://java.sun.com/jsf/html" + ), + "Jsf Core", + "f" + ), //NOI18N + JSTL_CORE( + sortedSet( + "jakarta.tags.core", + "http://xmlns.jcp.org/jsp/jstl/core", + "http://java.sun.com/jsp/jstl/core" + ), + "Jstl Core", + "c" + ), //NOI18N + JSTL_CORE_FUNCTIONS( + sortedSet( + "jakarta.tags.functions", + "http://xmlns.jcp.org/jsp/jstl/functions", + "http://java.sun.com/jsp/jstl/functions" + ), + "Jstl Core Functions", + "fn" + ), //NOI18N + FACELETS( + sortedSet( + "jakarta.faces.facelets", + "http://xmlns.jcp.org/jsf/facelets", + "http://java.sun.com/jsf/facelets" + ), + "Facelets", + "ui" + ), //NOI18N + COMPOSITE( + sortedSet( + "jakarta.faces.composite", + "http://xmlns.jcp.org/jsf/composite", + "http://java.sun.com/jsf/composite" + ), + "Composite Components", + "cc" + ), //NOI18N // PrimeFaces - PRIMEFACES("http://primefaces.org/ui", "PrimeFaces", "p"), //NOI18N - PRIMEFACES_MOBILE("http://primefaces.org/mobile", "PrimeFaces Mobile", "pm"), //NOI18N + PRIMEFACES( + sortedSet( + "http://primefaces.org/ui" + ), + "PrimeFaces", + "p" + ), //NOI18N + PRIMEFACES_MOBILE( + sortedSet( + "http://primefaces.org/mobile" + ), + "PrimeFaces Mobile", + "pm" + ), //NOI18N // JSF 2.2+ - JSF("http://xmlns.jcp.org/jsf", "Jsf", "jsf"), //NOI18N - PASSTHROUGH("http://xmlns.jcp.org/jsf/passthrough", "Passthrough", "p"); //NOI18N - - private static final DefaultLibraryInfo[] ALL_INFOS = values(); + JSF( + sortedSet( + "jakarta.faces", + "http://xmlns.jcp.org/jsf" + ), + "Jsf", + "jsf" + ), //NOI18N + PASSTHROUGH( + sortedSet( + "jakarta.faces.passthrough", + "http://xmlns.jcp.org/jsf/passthrough" + ), + "Passthrough", + "p" + ); //NOI18N - private String namespace; - private String displayName; - private String defaultPrefix; + private final Set allValidNamespaces; + private final String displayName; + private final String defaultPrefix; - - private DefaultLibraryInfo(String namespace, String displayName, String defaultPrefix) { - this.namespace = namespace; + private DefaultLibraryInfo(Set allValidNamespaces, String displayName, String defaultPrefix) { + this.allValidNamespaces = allValidNamespaces; this.displayName = displayName; this.defaultPrefix = defaultPrefix; } @Override public String getNamespace() { - return namespace; + return allValidNamespaces.iterator().next(); } - /** - * Second supported namespace by the library. - * @return legacy namespace if any or {@code null} - */ @Override - public String getLegacyNamespace() { - return NamespaceUtils.NS_MAPPING.get(namespace); + public Set getValidNamespaces() { + return allValidNamespaces; } @Override @@ -74,15 +146,16 @@ public String getDisplayName() { } public static LibraryInfo forNamespace(String namespace) { - for (int i = 0; i < ALL_INFOS.length; i++) { - LibraryInfo li = ALL_INFOS[i]; - if (li.getNamespace().equals(namespace) - || (li.getLegacyNamespace() != null && li.getLegacyNamespace().equals(namespace))) { - return li; - } - } - return null; + return Stream.of(values()) + .filter(lib -> lib.getValidNamespaces().contains(namespace)) + .findFirst() + .orElse(null); } + private static Set sortedSet(String... entries) { + Set sortedSet = new LinkedHashSet<>(); + Stream.of(entries).forEach(sortedSet::add); + return Collections.unmodifiableSet(sortedSet); + } } diff --git a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/JsfNamespaces.java b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/JsfNamespaces.java new file mode 100644 index 000000000000..15dde78dac91 --- /dev/null +++ b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/JsfNamespaces.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.web.jsfapi.api; + +import java.util.AbstractMap; +import java.util.Collections; +import java.util.EnumMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.netbeans.modules.web.jsfapi.api.JsfNamespaces.Type.TAGLIB; + +/** + * + * @author Benjamin Asbach + */ +public enum JsfNamespaces { + + JAVA_SUN_COM_NS( + entry(TAGLIB, "http://java.sun.com/xml/ns/javaee") + ), + XMLNS_JCP_ORG_NS( + entry(TAGLIB, "http://xmlns.jcp.org/xml/ns/javaee") + ), + JAKARTA_EE_NS( + entry(TAGLIB, "https://jakarta.ee/xml/ns/jakartaee") + ); + + public enum Type { + TAGLIB; + } + + private final Map namespaces; + + private JsfNamespaces(Entry... entries) { + this.namespaces = Collections.unmodifiableMap(new EnumMap<>(ofEntries(entries))); + } + + public String getNamespace(Type type) { + return namespaces.get(type); + } + + /* This method can be replaced with a static import to Map.entry() when enterprise module release target is Java 11+ */ + private static Entry entry(Type type, String value) { + return new AbstractMap.SimpleEntry<>(type, value); + } + + /* This method can be replaced with a static import to Map.entry() when enterprise module release target is Java 11+ */ + private static Map ofEntries(Entry... additional) { + return Stream.of(additional).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + } +} diff --git a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/LibraryInfo.java b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/LibraryInfo.java index ce2e1cabe479..e4f8ac324d04 100644 --- a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/LibraryInfo.java +++ b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/LibraryInfo.java @@ -18,7 +18,7 @@ */ package org.netbeans.modules.web.jsfapi.api; -import org.netbeans.api.annotations.common.CheckForNull; +import java.util.Set; /** * @@ -28,8 +28,13 @@ public interface LibraryInfo { public String getNamespace(); - @CheckForNull - public String getLegacyNamespace(); + /** + * + * @return all compatible namespaces for that library. + * First namespace is default one. + * The last one is the oldest supported namespace + */ + public Set getValidNamespaces(); public String getDefaultPrefix(); diff --git a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/NamespaceUtils.java b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/NamespaceUtils.java index 900679a4ef59..94448bc69501 100644 --- a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/NamespaceUtils.java +++ b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/api/NamespaceUtils.java @@ -20,9 +20,8 @@ import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; +import java.util.Objects; import org.netbeans.api.annotations.common.CheckForNull; /** @@ -60,29 +59,22 @@ public final class NamespaceUtils { */ @CheckForNull public static T getForNs(Map map, String ns) { - T result = checkMapForNs(map, ns); - - // try out shortened URL without ending slash if available - issue #226002 - if (result == null) { - if (ns.endsWith("/")) { //NOI18N - ns = ns.substring(0, ns.length() - 1); - return checkMapForNs(map, ns); + LibraryInfo libraryInfo = DefaultLibraryInfo.forNamespace(ns); + if (libraryInfo == null) { + ns = DefaultLibraryInfo.COMPOSITE.getValidNamespaces().stream() + .filter(ns::startsWith) + .findFirst() + .orElse(null); + if (ns == null) { + return null; } } - return result; - } - - private static T checkMapForNs(Map map, String ns) { - T result = map.get(ns); - if (result == null) { - if (NS_MAPPING.containsKey(ns)) { - result = map.get(NS_MAPPING.get(ns)); - } else if (ns.startsWith(DefaultLibraryInfo.COMPOSITE.getLegacyNamespace())) { - result = map.get(ns.replace(DefaultLibraryInfo.COMPOSITE.getLegacyNamespace(), DefaultLibraryInfo.COMPOSITE.getNamespace())); - } - } - return result; + return libraryInfo.getValidNamespaces().stream() + .map(map::get) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } /** @@ -92,31 +84,6 @@ private static T checkMapForNs(Map map, String ns) { * @return {@code true} if the collection contains new or legacy library namespace, {@code false} otherwise */ public static boolean containsNsOf(Collection collection, DefaultLibraryInfo library) { - if (collection.contains(library.getNamespace())) { - return true; - } - if (library.getLegacyNamespace() != null) { - return collection.contains(library.getLegacyNamespace()); - } - return false; + return library.getValidNamespaces().stream().anyMatch(collection::contains); } - - public static Set getAvailableNss(Map libraries, boolean jsf22plus) { - Set nss = new HashSet(); - for (Map.Entry entry : libraries.entrySet()) { - // library well known namespace - nss.add(entry.getKey()); - - // in case of JSF 2.2 add also its legacy namespaces - if (jsf22plus) { - Library library = entry.getValue(); - nss.add(library.getNamespace()); - if (NS_MAPPING.containsKey(library.getNamespace())) { - nss.add(NS_MAPPING.get(library.getNamespace())); - } - } - } - return nss; - } - } diff --git 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 new file mode 100644 index 000000000000..2f9a0e8d6f2f --- /dev/null +++ b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/spi/JsfReferenceImplementationProvider.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.web.jsfapi.spi; + +import java.nio.file.Path; +import org.netbeans.modules.web.jsfapi.api.JsfVersion; + +/** + * + * @author Benjamin Asbach + */ +public interface JsfReferenceImplementationProvider { + + Path of(JsfVersion jsfVersion); +} diff --git a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/spi/LibraryUtils.java b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/spi/LibraryUtils.java index 1eecffcf4f62..cf5bdb9cc7a3 100644 --- a/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/spi/LibraryUtils.java +++ b/enterprise/web.jsfapi/src/org/netbeans/modules/web/jsfapi/spi/LibraryUtils.java @@ -44,8 +44,8 @@ import org.netbeans.modules.parsing.spi.Parser; import org.netbeans.modules.web.common.api.WebUtils; import org.netbeans.modules.web.jsfapi.api.JsfSupport; +import org.netbeans.modules.web.jsfapi.api.JsfVersion; import org.netbeans.modules.web.jsfapi.api.Library; -import org.netbeans.modules.web.jsfapi.api.LibraryType; import org.netbeans.modules.web.jsfapi.api.NamespaceUtils; /** @@ -54,25 +54,23 @@ */ public class LibraryUtils { - public static final String COMPOSITE_LIBRARY_NS = "http://xmlns.jcp.org/jsf/composite"; //NOI18N - public static final String COMPOSITE_LIBRARY_LEGACY_NS = "http://java.sun.com/jsf/composite"; //NOI18N + public static final String COMPOSITE_LIBRARY_JAKARTA_NS = "jakarta.faces.composite"; //NOI18N + public static final String COMPOSITE_LIBRARY_JCP_NS = "http://xmlns.jcp.org/jsf/composite"; //NOI18N + public static final String COMPOSITE_LIBRARY_SUN_NS = "http://java.sun.com/jsf/composite"; //NOI18N public static final String XHTML_NS = "http://www.w3.org/1999/xhtml"; //NOI18N - public static String getCompositeLibraryURL(String libraryFolderPath, boolean jsf22Plus) { - if (jsf22Plus) { - return COMPOSITE_LIBRARY_NS + "/" + libraryFolderPath; //NOI18N + public static String getCompositeLibraryURL(String libraryFolderPath, JsfVersion jsfVersion) { + if (jsfVersion.isAtLeast(JsfVersion.JSF_4_0)) { + return COMPOSITE_LIBRARY_JAKARTA_NS + "/" + libraryFolderPath; + } else if (jsfVersion.isAtLeast(JsfVersion.JSF_2_2)) { + return COMPOSITE_LIBRARY_JCP_NS + "/" + libraryFolderPath; } else { - return COMPOSITE_LIBRARY_LEGACY_NS + "/" + libraryFolderPath; //NOI18N + return COMPOSITE_LIBRARY_SUN_NS + "/" + libraryFolderPath; } } - @Deprecated - public static boolean isCompositeComponentLibrary(Library library) { - return library.getType() == LibraryType.COMPOSITE; - } - - public static boolean importLibrary(Document document, Library library, String prefix, boolean isJsf22Plus) { - return !importLibrary(document, Collections.singletonMap(library, prefix), isJsf22Plus).isEmpty(); + public static boolean importLibrary(Document document, Library library, String prefix) { + return !importLibrary(document, Collections.singletonMap(library, prefix)).isEmpty(); } /** @@ -84,10 +82,10 @@ public static boolean importLibrary(Document document, Library library, String p * * @return a map of library2declared prefixes which contains just the imported pairs */ - public static Map importLibrary(Document document, Map libraries2prefixes, final boolean isJsf22Plus) { + public static Map importLibrary(Document document, Map libraries2prefixes) { assert document instanceof BaseDocument; - final Map imports = new LinkedHashMap(libraries2prefixes); + final Map imports = new LinkedHashMap<>(libraries2prefixes); //verify and update the imports map Iterator libsIterator = imports.keySet().iterator(); @@ -131,7 +129,7 @@ public void run(ResultIterator resultIterator) throws Exception { Element root = null; //no html root node, we need to find a root node of some other ast tree //belonging to some namespace - Collection roots = new ArrayList(); + Collection roots = new ArrayList<>(); roots.addAll(result.roots().values()); roots.add(result.rootOfUndeclaredTagsParseTree()); @@ -151,7 +149,7 @@ public boolean accepts(Element node) { } }); - List chsList = new ArrayList(chs); + List chsList = new ArrayList<>(chs); if (!chsList.isEmpty()) { Element top = chsList.get(0); @@ -226,8 +224,7 @@ public void run() { String prefixToDeclare = imports.get(library); int insertPosition = originalInsertPosition + offset_shift; - String namespace = isJsf22Plus || library.getLegacyNamespace() == null ? - library.getNamespace() : library.getLegacyNamespace(); + String namespace = library.getNamespace(); String text = (!noAttributes ? "\n" : "") + " xmlns:" + prefixToDeclare + //NOI18N "=\"" + namespace + "\""; //NOI18N @@ -262,7 +259,7 @@ public void run() { public static Map getDeclaredLibraries(HtmlParsingResult result) { //find all usages of composite components tags for this page Collection declaredNamespaces = result.getNamespaces().keySet(); - Map declaredLibraries = new HashMap(); + Map declaredLibraries = new HashMap<>(); JsfSupport jsfSupport = JsfSupportProvider.get(result.getSyntaxAnalyzerResult().getSource().getSourceFileObject()); if (jsfSupport != null) { Map libs = jsfSupport.getLibraries(); diff --git a/enterprise/web.primefaces/nbproject/project.xml b/enterprise/web.primefaces/nbproject/project.xml index ba083ef95f91..d0246bef92be 100644 --- a/enterprise/web.primefaces/nbproject/project.xml +++ b/enterprise/web.primefaces/nbproject/project.xml @@ -92,8 +92,8 @@ - 1 - 1.44 + 2 + 2.0 @@ -107,8 +107,8 @@ - 1 - 1.14 + 2 + 2.0 diff --git a/ide/html.editor/src/org/netbeans/modules/html/editor/api/completion/HtmlCompletionItem.java b/ide/html.editor/src/org/netbeans/modules/html/editor/api/completion/HtmlCompletionItem.java index c00358c60669..d763ee0fff94 100644 --- a/ide/html.editor/src/org/netbeans/modules/html/editor/api/completion/HtmlCompletionItem.java +++ b/ide/html.editor/src/org/netbeans/modules/html/editor/api/completion/HtmlCompletionItem.java @@ -93,6 +93,10 @@ public static HtmlCompletionItem createAttributeValue(String name, int substitut return new AttributeValue(name, substitutionOffset, addQuotation); } + public static HtmlCompletionItem createAttributeValue(String name, int substitutionOffset, boolean addQuotation, int sortPrioritiy) { + return new AttributeValue(name, substitutionOffset, addQuotation, sortPrioritiy); + } + public static HtmlCompletionItem createAttributeValue(String name, int substitutionOffset) { return createAttributeValue(name, substitutionOffset, false); } @@ -654,11 +658,23 @@ protected String getRightHtmlText() { */ public static class AttributeValue extends HtmlCompletionItem { - private boolean addQuotation; + private final boolean addQuotation; + + private final int sortPriority; - public AttributeValue(String value, int offset, boolean addQuotation) { + public AttributeValue(String value, int offset, boolean addQuotation, int sortPriority) { super(value, offset); this.addQuotation = addQuotation; + this.sortPriority = sortPriority; + } + + public AttributeValue(String value, int offset, boolean addQuotation) { + this(value, offset, addQuotation, DEFAULT_SORT_PRIORITY); + } + + @Override + public int getSortPriority() { + return sortPriority; } @Override