From b76b17cc82b48e1c2e75c5460a74fdebdbdf879c Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Tue, 15 Mar 2022 18:21:29 +0100 Subject: [PATCH 01/11] [gitflow-maven-plugin] Update for next development version 1.9.3-SNAPSHOT --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7647d7b..47c565d 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ io.wcm io.wcm.handler.link - 1.9.2 + 1.9.3-SNAPSHOT jar Link Handler @@ -49,7 +49,7 @@ handler/link - 2022-03-15T17:20:00Z + 2022-03-15T17:21:26Z From 34b75a64d7ab3a81737598ac21c4b26aeadd779b Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Fri, 6 May 2022 14:14:12 +0200 Subject: [PATCH 02/11] Switch to AEM 6.5.7 as minimum version. --- changes.xml | 6 ++++++ pom.xml | 3 +-- src/site/markdown/index.md | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/changes.xml b/changes.xml index 2f56ab6..847c804 100644 --- a/changes.xml +++ b/changes.xml @@ -23,6 +23,12 @@ xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd"> + + + Switch to AEM 6.5.7 as minimum version. + + + Make dependency to package org.apache.sling.sitemap.spi.common optional, only available in latest AEM versions. diff --git a/pom.xml b/pom.xml index 47c565d..4b821c7 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ io.wcm io.wcm.parent_toplevel - 2.0.2 + 2.1.0-SNAPSHOT @@ -195,7 +195,6 @@ com.adobe.aem uber-jar - apis provided diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index 1f8d57c..e7f804b 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -32,7 +32,8 @@ Read the [general concepts][general-concepts] to get an overview of the function |Link Handler version |AEM version supported |---------------------|---------------------- -|1.9.x or higher |AEM 6.5+, AEMaaCS +|1.9.4 or higher |AEM 6.5.7+, AEMaaCS +|1.9.0 - 1.9.2 |AEM 6.5+, AEMaaCS |1.6.x - 1.8.x |AEM 6.4.5+, AEMaaCS |1.5.x |AEM 6.3.3+, AEM 6.4.5+ |1.1.x - 1.4.x |AEM 6.2+ From 45b563a1511a43f85041efac2612f252b1f37eb2 Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Wed, 11 May 2022 17:42:58 +0200 Subject: [PATCH 03/11] update dependencies --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4b821c7..94790da 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ io.wcm io.wcm.parent_toplevel - 2.1.0-SNAPSHOT + 2.1.0 @@ -152,7 +152,7 @@ io.wcm io.wcm.testing.aem-mock.junit5 - 4.1.8 + 5.0.0 test From 260bd4f226457efb6b0b85cf9d3d5b19ce9a3903 Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Thu, 23 Jun 2022 15:59:08 +0200 Subject: [PATCH 04/11] switch maven central badge to shields.io to avoid out-of-sync issues with maven index --- README.md | 2 +- src/site/markdown/index.md | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1baa0d9..107e7ea 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Link Handler ====== [![Build](https://github.com/wcm-io/io.wcm.handler.link/workflows/Build/badge.svg?branch=develop)](https://github.com/wcm-io/io.wcm.handler.link/actions?query=workflow%3ABuild+branch%3Adevelop) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.link/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.link) +[![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.handler.link)](https://repo1.maven.org/maven2/io/wcm/io.wcm.handler.link/) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=wcm-io_io.wcm.handler.link&metric=coverage)](https://sonarcloud.io/summary/new_code?id=wcm-io_io.wcm.handler.link) Link resolving, processing and markup generation. diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index e7f804b..b066d2c 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -2,7 +2,7 @@ Link resolving, processing and markup generation. -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.link/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.link) +[![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.handler.link)](https://repo1.maven.org/maven2/io/wcm/io.wcm.handler.link/) ### Documentation @@ -46,13 +46,13 @@ Read the [general concepts][general-concepts] to get an overview of the function To use this module you have to deploy also: |---|---|---| -| [wcm.io Sling Commons](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.sling.commons) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.sling.commons/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.sling.commons) | -| [wcm.io AEM Sling Models Extensions](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.sling.models) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.sling.models/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.sling.models) | -| [wcm.io WCM Commons](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.wcm.commons) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.wcm.commons/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.wcm.commons) | -| [wcm.io WCM Granite UI Extensions](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.wcm.ui.granite) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.wcm.ui.granite/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.wcm.ui.granite) | -| [wcm.io Handler Commons](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.commons) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.commons/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.commons) | -| [wcm.io URL Handler](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.url) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.url/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.url) | -| [wcm.io Media Handler](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.media) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.media/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.wcm/io.wcm.handler.media) | +| [wcm.io Sling Commons](https://repo1.maven.org/maven2/io/wcm/io.wcm.sling.commons/) | [![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.sling.commons)](https://repo1.maven.org/maven2/io/wcm/io.wcm.sling.commons/) | +| [wcm.io AEM Sling Models Extensions](https://repo1.maven.org/maven2/io/wcm/io.wcm.sling.models/) | [![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.sling.models)](https://repo1.maven.org/maven2/io/wcm/io.wcm.sling.models/) | +| [wcm.io WCM Commons](https://repo1.maven.org/maven2/io/wcm/io.wcm.wcm.commons/) | [![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.wcm.commons)](https://repo1.maven.org/maven2/io/wcm/io.wcm.wcm.commons/) | +| [wcm.io WCM Granite UI Extensions](https://repo1.maven.org/maven2/io/wcm/io.wcm.wcm.ui.granite/) | [![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.wcm.ui.granite)](https://repo1.maven.org/maven2/io/wcm/io.wcm.wcm.ui.granite/) | +| [wcm.io Handler Commons](https://repo1.maven.org/maven2/io/wcm/io.wcm.handler.commons/) | [![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.handler.commons)](https://repo1.maven.org/maven2/io/wcm/io.wcm.handler.commons/) | +| [wcm.io URL Handler](https://repo1.maven.org/maven2/io/wcm/io.wcm.handler.url/) | [![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.handler.url)](https://repo1.maven.org/maven2/io/wcm/io.wcm.handler.url/) | +| [wcm.io Media Handler](https://repo1.maven.org/maven2/io/wcm/io.wcm.handler.media/) | [![Maven Central](https://img.shields.io/maven-central/v/io.wcm/io.wcm.handler.media)](https://repo1.maven.org/maven2/io/wcm/io.wcm.handler.media/) | ### GitHub Repository From 3b67d920562ca986b7c6db5a0640b67a5ae66e12 Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Tue, 29 Nov 2022 18:11:49 +0100 Subject: [PATCH 05/11] Add LinkBuilder.disableSuffixSelector to allow to diable the automatic addition of a "suffix" selector in case a suffix is present. Although recommended as best practice, this can be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk for file name clashes in dispatcher cache. --- changes.xml | 6 +++- pom.xml | 4 +-- .../java/io/wcm/handler/link/LinkArgs.java | 28 +++++++++++++++++++ .../java/io/wcm/handler/link/LinkBuilder.java | 12 ++++++++ .../handler/link/impl/LinkBuilderImpl.java | 6 ++++ .../io/wcm/handler/link/package-info.java | 2 +- .../type/helpers/InternalLinkResolver.java | 1 + .../io/wcm/handler/link/LinkArgsTest.java | 4 +++ .../io/wcm/handler/link/LinkRequestTest.java | 2 +- .../java/io/wcm/handler/link/LinkTest.java | 2 +- .../link/type/InternalLinkTypeTest.java | 3 ++ 11 files changed, 64 insertions(+), 6 deletions(-) diff --git a/changes.xml b/changes.xml index 847c804..9e34065 100644 --- a/changes.xml +++ b/changes.xml @@ -23,7 +23,11 @@ xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd"> - + + + Add LinkBuilder.disableSuffixSelector to allow to diable the automatic addition of a "suffix" selector in case a suffix is present. + Although recommended as best practice, this can be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk for file name clashes in dispatcher cache. + Switch to AEM 6.5.7 as minimum version. diff --git a/pom.xml b/pom.xml index 94790da..bc29c33 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ io.wcm io.wcm.handler.link - 1.9.3-SNAPSHOT + 1.10.0-SNAPSHOT jar Link Handler @@ -69,7 +69,7 @@ io.wcm io.wcm.handler.url - 1.7.0 + 1.10.0-SNAPSHOT compile diff --git a/src/main/java/io/wcm/handler/link/LinkArgs.java b/src/main/java/io/wcm/handler/link/LinkArgs.java index 255d0c7..bd633bf 100644 --- a/src/main/java/io/wcm/handler/link/LinkArgs.java +++ b/src/main/java/io/wcm/handler/link/LinkArgs.java @@ -32,6 +32,7 @@ import org.jetbrains.annotations.Nullable; import org.osgi.annotation.versioning.ProviderType; +import io.wcm.handler.url.UrlHandler; import io.wcm.handler.url.UrlMode; import io.wcm.wcm.commons.util.ToStringStyle; @@ -50,10 +51,12 @@ public final class LinkArgs implements Cloneable { private String queryString; private String fragment; private String windowTarget; + private boolean disableSuffixSelector; private ValueMap properties; private String[] linkTargetUrlFallbackProperty; private String[] linkTargetWindowTargetFallbackProperty; + /** * @return URL mode for externalizing the URL */ @@ -198,6 +201,30 @@ public boolean isDummyLink() { return this; } + /** + * Disable the automatic addition of an additional selector {@link UrlHandler#SELECTOR_SUFFIX} + * in case a suffix is present for building the URL. Although recommended as best practice, this can + * be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk + * for file name clashes in dispatcher cache. + * @return If set to true, no additional suffix selector is added + */ + public boolean isDisableSuffixSelector() { + return this.disableSuffixSelector; + } + + /** + * Disable the automatic addition of an additional selector {@link UrlHandler#SELECTOR_SUFFIX} + * in case a suffix is present for building the URL. Although recommended as best practice, this can + * be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk + * for file name clashes in dispatcher cache. + * @param value If set to true, no additional suffix selector is added + * @return this + */ + public @NotNull LinkArgs disableSuffixSelector(boolean value) { + this.disableSuffixSelector = value; + return this; + } + /** * Custom properties that my be used by application-specific markup builders or processors. * @param map Property map. Is merged with properties already set. @@ -314,6 +341,7 @@ public LinkArgs clone() { //NOPMD clone.queryString = this.queryString; clone.fragment = this.fragment; clone.windowTarget = this.windowTarget; + clone.disableSuffixSelector = this.disableSuffixSelector; clone.linkTargetUrlFallbackProperty = ArrayUtils.clone(this.linkTargetUrlFallbackProperty); clone.linkTargetWindowTargetFallbackProperty = ArrayUtils.clone(this.linkTargetWindowTargetFallbackProperty); if (this.properties != null) { diff --git a/src/main/java/io/wcm/handler/link/LinkBuilder.java b/src/main/java/io/wcm/handler/link/LinkBuilder.java index df370c5..035fe58 100644 --- a/src/main/java/io/wcm/handler/link/LinkBuilder.java +++ b/src/main/java/io/wcm/handler/link/LinkBuilder.java @@ -24,6 +24,7 @@ import org.osgi.annotation.versioning.ProviderType; import io.wcm.handler.commons.dom.Anchor; +import io.wcm.handler.url.UrlHandler; import io.wcm.handler.url.UrlMode; /** @@ -88,6 +89,17 @@ public interface LinkBuilder { @NotNull LinkBuilder windowTarget(@Nullable String windowTarget); + /** + * Disable the automatic addition of an additional selector {@link UrlHandler#SELECTOR_SUFFIX} + * in case a suffix is present for building the URL. Although recommended as best practice, this can + * be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk + * for file name clashes in dispatcher cache. + * @param disableSuffixSelector If set to true, no additional suffix selector is added + * @return URL builder + */ + @NotNull + LinkBuilder disableSuffixSelector(boolean disableSuffixSelector); + /** * Set URL mode for externalizing the URL * @param urlMode URL mode. If null, default URL mode is used. diff --git a/src/main/java/io/wcm/handler/link/impl/LinkBuilderImpl.java b/src/main/java/io/wcm/handler/link/impl/LinkBuilderImpl.java index 1eefb55..bf0580c 100644 --- a/src/main/java/io/wcm/handler/link/impl/LinkBuilderImpl.java +++ b/src/main/java/io/wcm/handler/link/impl/LinkBuilderImpl.java @@ -205,6 +205,12 @@ private static String getWindowTargetFromResource(@NotNull Resource resource, @N return this; } + @Override + public @NotNull LinkBuilder disableSuffixSelector(boolean disableSuffixSelector) { + this.linkArgs.disableSuffixSelector(disableSuffixSelector); + return this; + } + @Override @SuppressFBWarnings("NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION") public @NotNull LinkBuilder linkTargetUrlFallbackProperty(@NotNull String @Nullable... propertyNames) { diff --git a/src/main/java/io/wcm/handler/link/package-info.java b/src/main/java/io/wcm/handler/link/package-info.java index 62bc1db..7e82163 100644 --- a/src/main/java/io/wcm/handler/link/package-info.java +++ b/src/main/java/io/wcm/handler/link/package-info.java @@ -20,5 +20,5 @@ /** * Link Handler API. */ -@org.osgi.annotation.versioning.Version("1.6.0") +@org.osgi.annotation.versioning.Version("1.7.0") package io.wcm.handler.link; diff --git a/src/main/java/io/wcm/handler/link/type/helpers/InternalLinkResolver.java b/src/main/java/io/wcm/handler/link/type/helpers/InternalLinkResolver.java index baa04f5..eeafb44 100644 --- a/src/main/java/io/wcm/handler/link/type/helpers/InternalLinkResolver.java +++ b/src/main/java/io/wcm/handler/link/type/helpers/InternalLinkResolver.java @@ -197,6 +197,7 @@ public boolean acceptPage(@Nullable Page page, @NotNull InternalLinkResolverOpti .queryString(queryString) .fragment(fragment) .urlMode(linkArgs.getUrlMode()) + .disableSuffixSelector(linkArgs.isDisableSuffixSelector()) .buildExternalLinkUrl(targetPage); } diff --git a/src/test/java/io/wcm/handler/link/LinkArgsTest.java b/src/test/java/io/wcm/handler/link/LinkArgsTest.java index c621fe8..0970cb0 100644 --- a/src/test/java/io/wcm/handler/link/LinkArgsTest.java +++ b/src/test/java/io/wcm/handler/link/LinkArgsTest.java @@ -47,6 +47,7 @@ void testProperties() { .queryString("query1") .fragment("fragment1") .windowTarget("_parent") + .disableSuffixSelector(true) .linkTargetUrlFallbackProperty("property1"); assertEquals(UrlModes.FULL_URL, linkArgs.getUrlMode()); @@ -58,6 +59,7 @@ void testProperties() { assertEquals("query1", linkArgs.getQueryString()); assertEquals("fragment1", linkArgs.getFragment()); assertEquals("_parent", linkArgs.getWindowTarget()); + assertTrue(linkArgs.isDisableSuffixSelector()); assertArrayEquals(new String[] { "property1" }, linkArgs.getLinkTargetUrlFallbackProperty()); } @@ -92,6 +94,7 @@ void testClone() { .windowTarget("_blank") .linkTargetUrlFallbackProperty("property1") .linkTargetWindowTargetFallbackProperty("property2") + .disableSuffixSelector(true) .properties(props); LinkArgs clone = linkArgs.clone(); @@ -105,6 +108,7 @@ void testClone() { assertEquals(linkArgs.getQueryString(), clone.getQueryString()); assertEquals(linkArgs.getFragment(), clone.getFragment()); assertEquals(linkArgs.getWindowTarget(), clone.getWindowTarget()); + assertEquals(linkArgs.isDisableSuffixSelector(), clone.isDisableSuffixSelector()); assertArrayEquals(linkArgs.getLinkTargetUrlFallbackProperty(), clone.getLinkTargetUrlFallbackProperty()); assertArrayEquals(linkArgs.getLinkTargetWindowTargetFallbackProperty(), clone.getLinkTargetWindowTargetFallbackProperty()); assertEquals(ImmutableValueMap.copyOf(linkArgs.getProperties()), ImmutableValueMap.copyOf(clone.getProperties())); diff --git a/src/test/java/io/wcm/handler/link/LinkRequestTest.java b/src/test/java/io/wcm/handler/link/LinkRequestTest.java index 2ccdd6c..2bc5de6 100644 --- a/src/test/java/io/wcm/handler/link/LinkRequestTest.java +++ b/src/test/java/io/wcm/handler/link/LinkRequestTest.java @@ -30,7 +30,7 @@ class LinkRequestTest { @Test void testToString() { LinkRequest request = new LinkRequest(null, null, new LinkArgs().urlMode(UrlModes.DEFAULT)); - assertEquals("LinkRequest[linkArgs=LinkArgs[urlMode=DEFAULT,dummyLink=false]]", request.toString()); + assertEquals("LinkRequest[linkArgs=LinkArgs[urlMode=DEFAULT,dummyLink=false,disableSuffixSelector=false]]", request.toString()); } } diff --git a/src/test/java/io/wcm/handler/link/LinkTest.java b/src/test/java/io/wcm/handler/link/LinkTest.java index 1101ade..3392307 100644 --- a/src/test/java/io/wcm/handler/link/LinkTest.java +++ b/src/test/java/io/wcm/handler/link/LinkTest.java @@ -109,7 +109,7 @@ void testTargetRendition() { @Test void testToString() { - assertEquals("Link[linkType=linkType,linkRequest=LinkRequest[linkArgs=LinkArgs[dummyLink=false]],linkReferenceInvalid=false]", + assertEquals("Link[linkType=linkType,linkRequest=LinkRequest[linkArgs=LinkArgs[dummyLink=false,disableSuffixSelector=false]],linkReferenceInvalid=false]", underTest.toString()); } diff --git a/src/test/java/io/wcm/handler/link/type/InternalLinkTypeTest.java b/src/test/java/io/wcm/handler/link/type/InternalLinkTypeTest.java index 0077018..d22cba0 100644 --- a/src/test/java/io/wcm/handler/link/type/InternalLinkTypeTest.java +++ b/src/test/java/io/wcm/handler/link/type/InternalLinkTypeTest.java @@ -420,6 +420,9 @@ void testTargetPageLinkUrlVariants() { assertEquals("/content/unittest/de_test/brand/de/section/content.sel1.suffix.htx/suf1/suf2.htx", linkHandler.get(targetPage).selectors("sel1").extension(FileExtension.HTML_UNCACHED).suffix("suf1/suf2").urlMode(UrlModes.NO_HOSTNAME).buildUrl()); + + assertEquals("http://www.dummysite.org/content/unittest/de_test/brand/de/section/content.sel1.html/suf1/suf2.html", + linkHandler.get(targetPage).selectors("sel1").suffix("suf1/suf2").disableSuffixSelector(true).buildUrl()); } @Test From c7584f8ffd72009ca0c20c0836ccc77f94f2b76e Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Wed, 30 Nov 2022 17:04:14 +0100 Subject: [PATCH 06/11] Add LinkBuilder.property method to be able to directly specify custom properties. --- changes.xml | 3 +++ src/main/java/io/wcm/handler/link/LinkBuilder.java | 9 +++++++++ .../java/io/wcm/handler/link/impl/LinkBuilderImpl.java | 6 ++++++ .../io/wcm/handler/link/impl/LinkHandlerImplTest.java | 8 ++++++++ 4 files changed, 26 insertions(+) diff --git a/changes.xml b/changes.xml index 9e34065..deed73d 100644 --- a/changes.xml +++ b/changes.xml @@ -28,6 +28,9 @@ Add LinkBuilder.disableSuffixSelector to allow to diable the automatic addition of a "suffix" selector in case a suffix is present. Although recommended as best practice, this can be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk for file name clashes in dispatcher cache. + + Add LinkBuilder.property method to be able to directly specify custom properties. + Switch to AEM 6.5.7 as minimum version. diff --git a/src/main/java/io/wcm/handler/link/LinkBuilder.java b/src/main/java/io/wcm/handler/link/LinkBuilder.java index 035fe58..3b677ee 100644 --- a/src/main/java/io/wcm/handler/link/LinkBuilder.java +++ b/src/main/java/io/wcm/handler/link/LinkBuilder.java @@ -133,6 +133,15 @@ public interface LinkBuilder { @NotNull LinkBuilder linkTargetUrlFallbackProperty(@NotNull String @Nullable... propertyNames); + /** + * Adds a custom property that my be used by application-specific processors. + * @param key Property key + * @param value Property value + * @return this + */ + @NotNull + LinkBuilder property(@NotNull String key, @Nullable Object value); + /** * Resolve link and return metadata object that contains the results. * @return Link metadata object. Never null, if the resolving failed the isValid() method returns false. diff --git a/src/main/java/io/wcm/handler/link/impl/LinkBuilderImpl.java b/src/main/java/io/wcm/handler/link/impl/LinkBuilderImpl.java index bf0580c..80a2d81 100644 --- a/src/main/java/io/wcm/handler/link/impl/LinkBuilderImpl.java +++ b/src/main/java/io/wcm/handler/link/impl/LinkBuilderImpl.java @@ -218,6 +218,12 @@ private static String getWindowTargetFromResource(@NotNull Resource resource, @N return this; } + @Override + public @NotNull LinkBuilder property(@NotNull String key, @Nullable Object value) { + this.linkArgs.property(key, value); + return this; + } + @Override public @NotNull Link build() { LinkRequest request = new LinkRequest(this.resource, this.page, this.reference, this.linkArgs); diff --git a/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java b/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java index 47dd967..45fcfce 100644 --- a/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java +++ b/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java @@ -183,6 +183,14 @@ void testLinkTargetUrlFallbackProperty_IgnoreWhenValidLinkSet() { assertEquals("http://xyz/path1/pre1", link.getAnchor().getHRef()); } + @Test + void testLinkHandlerCustomProperty() { + LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class); + + Link link = linkHandler.get("http://dummy").property("prop1", "value1").build(); + assertEquals("value1", link.getLinkRequest().getLinkArgs().getProperties().get("prop1")); + } + public static class TestLinkHandlerConfig extends LinkHandlerConfig { From 48318b4a15b929f47298ff80e05ae093ed0e6d7a Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Tue, 6 Dec 2022 17:27:50 +0100 Subject: [PATCH 07/11] LinkType: Mark getEditComponentResourceType and hasRichTextPlugin to be ignored in JSON representation. --- changes.xml | 3 +++ src/main/java/io/wcm/handler/link/spi/LinkType.java | 2 ++ src/main/java/io/wcm/handler/link/spi/package-info.java | 2 +- src/main/java/io/wcm/handler/link/type/package-info.java | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/changes.xml b/changes.xml index deed73d..c4f293a 100644 --- a/changes.xml +++ b/changes.xml @@ -31,6 +31,9 @@ Add LinkBuilder.property method to be able to directly specify custom properties. + + LinkType: Mark getEditComponentResourceType and hasRichTextPlugin to be ignored in JSON representation. + Switch to AEM 6.5.7 as minimum version. diff --git a/src/main/java/io/wcm/handler/link/spi/LinkType.java b/src/main/java/io/wcm/handler/link/spi/LinkType.java index 163711f..f336045 100644 --- a/src/main/java/io/wcm/handler/link/spi/LinkType.java +++ b/src/main/java/io/wcm/handler/link/spi/LinkType.java @@ -111,6 +111,7 @@ public boolean accepts(@NotNull LinkRequest linkRequest) { * Granite UI component resource type to be used for editing this link type's properties in edit dialog. * @return Granite UI component resource type or null, if none is available */ + @JsonIgnore public @Nullable String getEditComponentResourceType() { return null; } @@ -120,6 +121,7 @@ public boolean accepts(@NotNull LinkRequest linkRequest) { * this link type in the rich text editor. * @return true if a RTE plugin is available. */ + @JsonIgnore public boolean hasRichTextPlugin() { return false; } diff --git a/src/main/java/io/wcm/handler/link/spi/package-info.java b/src/main/java/io/wcm/handler/link/spi/package-info.java index 8522973..cd1404a 100644 --- a/src/main/java/io/wcm/handler/link/spi/package-info.java +++ b/src/main/java/io/wcm/handler/link/spi/package-info.java @@ -20,5 +20,5 @@ /** * SPI for configuring and tailoring link handler processing. */ -@org.osgi.annotation.versioning.Version("1.2") +@org.osgi.annotation.versioning.Version("1.2.1") package io.wcm.handler.link.spi; diff --git a/src/main/java/io/wcm/handler/link/type/package-info.java b/src/main/java/io/wcm/handler/link/type/package-info.java index f7b8965..85cb0d2 100644 --- a/src/main/java/io/wcm/handler/link/type/package-info.java +++ b/src/main/java/io/wcm/handler/link/type/package-info.java @@ -20,5 +20,5 @@ /** * Default link type implementations. */ -@org.osgi.annotation.versioning.Version("1.4") +@org.osgi.annotation.versioning.Version("1.4.1") package io.wcm.handler.link.type; From f96a0f1a47adc2222ecbbf804e61177ee9c9b950 Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Fri, 9 Dec 2022 09:47:15 +0100 Subject: [PATCH 08/11] LinkHandler: Build anchor markup on-demand based on the current status of link when the anchor is requested. This allows to react on results of link post processors, and avoids building the anchor if not required. --- changes.xml | 3 +++ src/main/java/io/wcm/handler/link/Link.java | 23 +++++++++++++++---- .../handler/link/impl/LinkHandlerImpl.java | 14 ++++++----- .../java/io/wcm/handler/link/LinkTest.java | 13 +++++++++++ .../link/impl/LinkHandlerImplTest.java | 8 +++---- 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/changes.xml b/changes.xml index c4f293a..6997055 100644 --- a/changes.xml +++ b/changes.xml @@ -34,6 +34,9 @@ LinkType: Mark getEditComponentResourceType and hasRichTextPlugin to be ignored in JSON representation. + + LinkHandler: Build anchor markup on-demand based on the current status of link when the anchor is requested. This allows to react on results of link post processors, and avoids building the anchor if not required. + Switch to AEM 6.5.7 as minimum version. diff --git a/src/main/java/io/wcm/handler/link/Link.java b/src/main/java/io/wcm/handler/link/Link.java index 8efb0ae..9a67b56 100644 --- a/src/main/java/io/wcm/handler/link/Link.java +++ b/src/main/java/io/wcm/handler/link/Link.java @@ -23,6 +23,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.function.Function; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ToStringBuilder; @@ -54,6 +55,7 @@ public final class Link { private @NotNull LinkRequest linkRequest; private boolean linkReferenceInvalid; private Anchor anchor; + private Function anchorBuilder; private String url; private Page targetPage; private Asset targetAsset; @@ -113,6 +115,10 @@ public void setLinkReferenceInvalid(boolean linkReferenceInvalid) { */ @JsonIgnore public Anchor getAnchor() { + if (this.anchor == null && this.anchorBuilder != null) { + this.anchor = this.anchorBuilder.apply(this); + this.anchorBuilder = null; + } return this.anchor; } @@ -122,11 +128,12 @@ public Anchor getAnchor() { @JsonIgnore @SuppressWarnings("java:S1168") public Map getAnchorAttributes() { - if (getAnchor() == null) { + Anchor a = getAnchor(); + if (a == null) { return null; } Map attributes = new HashMap<>(); - for (Attribute attribute : getAnchor().getAttributes()) { + for (Attribute attribute : a.getAttributes()) { attributes.put(attribute.getName(), attribute.getValue()); } return attributes; @@ -139,13 +146,21 @@ public void setAnchor(Anchor anchor) { this.anchor = anchor; } + /** + * @param anchorBuilder Function that builds an anchor representation on demand + */ + public void setAnchorBuilder(Function anchorBuilder) { + this.anchorBuilder = anchorBuilder; + } + /** * @return Link markup (only the opening anchor tag) or null if resolving was not successful. */ @JsonIgnore public String getMarkup() { - if (this.anchor != null) { - return StringUtils.removeEnd(this.anchor.toString(), ""); + Anchor a = getAnchor(); + if (a != null) { + return StringUtils.removeEnd(a.toString(), ""); } else { return null; diff --git a/src/main/java/io/wcm/handler/link/impl/LinkHandlerImpl.java b/src/main/java/io/wcm/handler/link/impl/LinkHandlerImpl.java index 11c9e4e..5974c0a 100644 --- a/src/main/java/io/wcm/handler/link/impl/LinkHandlerImpl.java +++ b/src/main/java/io/wcm/handler/link/impl/LinkHandlerImpl.java @@ -144,13 +144,15 @@ Link processRequest(@NotNull LinkRequest linkRequest) { // generate markup (if markup builder is available) - first accepting wins List> linkMarkupBuilders = linkHandlerConfig.getMarkupBuilders(); if (linkMarkupBuilders != null) { - for (Class linkMarkupBuilderClass : linkMarkupBuilders) { - LinkMarkupBuilder linkMarkupBuilder = AdaptTo.notNull(adaptable, linkMarkupBuilderClass); - if (linkMarkupBuilder.accepts(link)) { - link.setAnchor(linkMarkupBuilder.build(link)); - break; + link.setAnchorBuilder(l -> { + for (Class linkMarkupBuilderClass : linkMarkupBuilders) { + LinkMarkupBuilder linkMarkupBuilder = AdaptTo.notNull(adaptable, linkMarkupBuilderClass); + if (linkMarkupBuilder.accepts(l)) { + return linkMarkupBuilder.build(l); + } } - } + return null; + }); } // postprocess link after resolving diff --git a/src/test/java/io/wcm/handler/link/LinkTest.java b/src/test/java/io/wcm/handler/link/LinkTest.java index 3392307..7797e83 100644 --- a/src/test/java/io/wcm/handler/link/LinkTest.java +++ b/src/test/java/io/wcm/handler/link/LinkTest.java @@ -78,6 +78,19 @@ void testAnchor() { assertEquals("", underTest.getMarkup()); } + @Test + void testAnchorBuilder() { + assertNull(underTest.getAnchorAttributes()); + assertNull(underTest.getMarkup()); + + underTest.setAnchorBuilder(l -> new Anchor(l.getUrl()).setTitle("title1")); + underTest.setUrl("http://dummy1"); + + assertEquals("title1", underTest.getAnchor().getTitle()); + assertEquals("http://dummy1", underTest.getAnchorAttributes().get("href")); + assertEquals("", underTest.getMarkup()); + } + @Test void testUrlAndValid() { assertFalse(underTest.isValid()); diff --git a/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java b/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java index 45fcfce..88c199d 100644 --- a/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java +++ b/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java @@ -108,7 +108,7 @@ void testPipelining() { assertEquals(true, link.isValid()); assertEquals("http://xyz/path1/pre1/post1", link.getUrl()); assertNotNull(link.getAnchor()); - assertEquals("http://xyz/path1/pre1", link.getAnchor().getHRef()); + assertEquals("http://xyz/path1/pre1/post1", link.getAnchor().getHRef()); } @Test @@ -138,7 +138,7 @@ void testLinkTargetUrlFallbackProperty() { assertEquals(true, link.isValid()); assertEquals("http://xyz/fallbackpath1/post1", link.getUrl()); assertNotNull(link.getAnchor()); - assertEquals(ImmutableMap.of("href", "http://xyz/fallbackpath1", "target", "_blank"), link.getAnchorAttributes()); + assertEquals(ImmutableMap.of("href", "http://xyz/fallbackpath1/post1", "target", "_blank"), link.getAnchorAttributes()); } @Test @@ -158,7 +158,7 @@ void testLinkTargetUrlFallbackProperty_MultipleProperties() { assertEquals(true, link.isValid()); assertEquals("http://xyz/fallbackpath1/post1", link.getUrl()); assertNotNull(link.getAnchor()); - assertEquals(ImmutableMap.of("href", "http://xyz/fallbackpath1"), link.getAnchorAttributes()); + assertEquals(ImmutableMap.of("href", "http://xyz/fallbackpath1/post1"), link.getAnchorAttributes()); } @Test @@ -180,7 +180,7 @@ void testLinkTargetUrlFallbackProperty_IgnoreWhenValidLinkSet() { assertEquals(true, link.isValid()); assertEquals("http://xyz/path1/pre1/post1", link.getUrl()); assertNotNull(link.getAnchor()); - assertEquals("http://xyz/path1/pre1", link.getAnchor().getHRef()); + assertEquals("http://xyz/path1/pre1/post1", link.getAnchor().getHRef()); } @Test From 0a9499422771cde534f54c2bdd9509a048e64e3b Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Fri, 9 Dec 2022 11:10:14 +0100 Subject: [PATCH 09/11] with building anchor lazily, it's not longer required to set anchor url explicitly in AbstractInternalLinkInheritUrlParamLinkPostProcessor mark Link#setAnchor as deprecated --- src/main/java/io/wcm/handler/link/Link.java | 2 ++ ...ternalLinkInheritUrlParamLinkPostProcessor.java | 3 --- src/test/java/io/wcm/handler/link/LinkTest.java | 1 + ...alLinkInheritUrlParamLinkPostProcessorTest.java | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/wcm/handler/link/Link.java b/src/main/java/io/wcm/handler/link/Link.java index 9a67b56..0bee05e 100644 --- a/src/main/java/io/wcm/handler/link/Link.java +++ b/src/main/java/io/wcm/handler/link/Link.java @@ -141,7 +141,9 @@ public Map getAnchorAttributes() { /** * @param anchor Anchor element + * @deprecated Use {@link #setAnchorBuilder(Function)} to build anchor on-demand */ + @Deprecated public void setAnchor(Anchor anchor) { this.anchor = anchor; } diff --git a/src/main/java/io/wcm/handler/link/processor/AbstractInternalLinkInheritUrlParamLinkPostProcessor.java b/src/main/java/io/wcm/handler/link/processor/AbstractInternalLinkInheritUrlParamLinkPostProcessor.java index b92930c..28d2cff 100644 --- a/src/main/java/io/wcm/handler/link/processor/AbstractInternalLinkInheritUrlParamLinkPostProcessor.java +++ b/src/main/java/io/wcm/handler/link/processor/AbstractInternalLinkInheritUrlParamLinkPostProcessor.java @@ -75,9 +75,6 @@ protected AbstractInternalLinkInheritUrlParamLinkPostProcessor(Set inher .fragment(uri.getFragment()) .build(); link.setUrl(url); - if (link.getAnchor() != null) { - link.getAnchor().setAttribute("href", url); - } } catch (URISyntaxException ex) { log.warn("Skipping post-processing or URL: {}", url, ex); diff --git a/src/test/java/io/wcm/handler/link/LinkTest.java b/src/test/java/io/wcm/handler/link/LinkTest.java index 7797e83..21d2938 100644 --- a/src/test/java/io/wcm/handler/link/LinkTest.java +++ b/src/test/java/io/wcm/handler/link/LinkTest.java @@ -67,6 +67,7 @@ void testLinkReferenceInvalid() { } @Test + @SuppressWarnings("deprecation") void testAnchor() { assertNull(underTest.getAnchorAttributes()); assertNull(underTest.getMarkup()); diff --git a/src/test/java/io/wcm/handler/link/processor/InternalLinkInheritUrlParamLinkPostProcessorTest.java b/src/test/java/io/wcm/handler/link/processor/InternalLinkInheritUrlParamLinkPostProcessorTest.java index c8fd111..d52d356 100644 --- a/src/test/java/io/wcm/handler/link/processor/InternalLinkInheritUrlParamLinkPostProcessorTest.java +++ b/src/test/java/io/wcm/handler/link/processor/InternalLinkInheritUrlParamLinkPostProcessorTest.java @@ -60,7 +60,7 @@ void testInternalLinkWithDefaultParameterList() { Link link = new Link(new InternalLinkType(), null); link.setUrl("/sample.html"); - link.setAnchor(new Anchor().setHRef("/sample.html")); + link.setAnchorBuilder(l -> new Anchor().setHRef(l.getUrl())); // test without url parameters postProcessor.process(link); @@ -84,7 +84,7 @@ void testInternalLinkFragment() { Link link = new Link(new InternalLinkType(), null); link.setUrl("/sample.html#fragment1"); - link.setAnchor(new Anchor().setHRef("/sample.html#fragment1")); + link.setAnchorBuilder(l -> new Anchor().setHRef(l.getUrl())); // test without url parameters postProcessor.process(link); @@ -108,7 +108,7 @@ void testInternalLinkFullUrl() { Link link = new Link(new InternalLinkType(), null); link.setUrl("https://host1/sample.html#fragment1"); - link.setAnchor(new Anchor().setHRef("/sample.html#fragment1")); + link.setAnchorBuilder(l -> new Anchor().setHRef(l.getUrl())); // test without url parameters postProcessor.process(link); @@ -132,7 +132,7 @@ void testInternalLinkFullUrlWithPort() { Link link = new Link(new InternalLinkType(), null); link.setUrl("https://host1:8080/sample.html#fragment1"); - link.setAnchor(new Anchor().setHRef("/sample.html#fragment1")); + link.setAnchorBuilder(l -> new Anchor().setHRef(l.getUrl())); // test without url parameters postProcessor.process(link); @@ -156,7 +156,7 @@ void testInternalLinkWithCustomParameterList() { Link link = new Link(new InternalLinkType(), null); link.setUrl("/sample.html"); - link.setAnchor(new Anchor().setHRef("/sample.html")); + link.setAnchorBuilder(l -> new Anchor().setHRef(l.getUrl())); // test without url parameters postProcessor.process(link); @@ -180,7 +180,7 @@ void testExternalLinkWithDefaultParameterList() { Link link = new Link(new ExternalLinkType(), null); link.setUrl("/sample.html"); - link.setAnchor(new Anchor().setHRef("/sample.html")); + link.setAnchorBuilder(l -> new Anchor().setHRef(l.getUrl())); // test without url parameters postProcessor.process(link); @@ -199,7 +199,7 @@ void testInternalCrossContextLinkWithDefaultParameterList() { Link link = new Link(new InternalCrossContextLinkType(), null); link.setUrl("/sample.html"); - link.setAnchor(new Anchor().setHRef("/sample.html")); + link.setAnchorBuilder(l -> new Anchor().setHRef(l.getUrl())); // test without url parameters postProcessor.process(link); From 45d1350cb9ff6cd09dcea8da0d2aa8be3f46eafa Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Thu, 15 Dec 2022 12:35:17 +0100 Subject: [PATCH 10/11] prepare release --- changes.xml | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/changes.xml b/changes.xml index 6997055..5d06902 100644 --- a/changes.xml +++ b/changes.xml @@ -23,7 +23,7 @@ xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd"> - + Add LinkBuilder.disableSuffixSelector to allow to diable the automatic addition of a "suffix" selector in case a suffix is present. Although recommended as best practice, this can be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk for file name clashes in dispatcher cache. diff --git a/pom.xml b/pom.xml index bc29c33..c6ae627 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ io.wcm io.wcm.handler.url - 1.10.0-SNAPSHOT + 1.10.0 compile @@ -152,7 +152,7 @@ io.wcm io.wcm.testing.aem-mock.junit5 - 5.0.0 + 5.1.2 test From abf465961b5b195d5366b9e2578b3b7f92b026b8 Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Thu, 15 Dec 2022 12:36:38 +0100 Subject: [PATCH 11/11] [gitflow-maven-plugin] Update versions for release 1.10.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c6ae627..58cb6ea 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ io.wcm io.wcm.handler.link - 1.10.0-SNAPSHOT + 1.10.0 jar Link Handler @@ -49,7 +49,7 @@ handler/link - 2022-03-15T17:21:26Z + 2022-12-15T11:36:37Z