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