diff --git a/changes.xml b/changes.xml
index e8eaf95..f60e406 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">
+
+
+ Provide DEBUG/TRACE log messages for link processing.
+
+
+
Support detecting redirect pages using AEM cq:redirectTarget property (instead of link handler properties).
diff --git a/pom.xml b/pom.xml
index 36384fe..778ff40 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,13 +25,13 @@
io.wcm
io.wcm.parent_toplevel
- 2.3.0
+ 2.3.2
io.wcm
io.wcm.handler.link
- 2.2.0
+ 2.2.2
jar
Link Handler
@@ -49,7 +49,7 @@
handler/link
- 2024-05-14T09:33:17Z
+ 2024-07-08T08:54:43Z
@@ -88,7 +88,7 @@
io.wcm
io.wcm.wcm.commons
- 1.10.0
+ 1.11.0
compile
diff --git a/src/main/java/io/wcm/handler/link/Link.java b/src/main/java/io/wcm/handler/link/Link.java
index ef29dee..bd01cce 100644
--- a/src/main/java/io/wcm/handler/link/Link.java
+++ b/src/main/java/io/wcm/handler/link/Link.java
@@ -28,6 +28,7 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
import org.jdom2.Attribute;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,7 +44,6 @@
import io.wcm.handler.link.spi.LinkType;
import io.wcm.handler.media.Asset;
import io.wcm.handler.media.Rendition;
-import io.wcm.wcm.commons.util.ToStringStyle;
/**
* Holds information about a link processed and resolved by {@link LinkHandler}.
@@ -259,7 +259,32 @@ && getUrl() != null
@Override
public String toString() {
- return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE);
+ ToStringBuilder sb = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
+ sb.append("valid", isValid());
+ if (isValid()) {
+ sb.append("url", getUrl());
+ }
+ else {
+ sb.append("linkReferenceInvalid", this.linkReferenceInvalid);
+ }
+ sb.append("linkType", getLinkType());
+ if (this.anchor != null) {
+ sb.append("anchor", this.anchor.toString());
+ }
+ if (targetPage != null) {
+ sb.append("targetPage", targetPage.getPath());
+ }
+ if (targetAsset != null) {
+ sb.append("targetAsset", targetAsset.getPath());
+ }
+ if (targetRendition != null) {
+ sb.append("targetRendition", targetRendition);
+ }
+ if (redirectPages != null && !redirectPages.isEmpty()) {
+ sb.append("redirectPages", redirectPages.stream().map(Page::getPath).toArray());
+ }
+ sb.append("linkRequest", linkRequest);
+ return sb.build();
}
}
diff --git a/src/main/java/io/wcm/handler/link/LinkRequest.java b/src/main/java/io/wcm/handler/link/LinkRequest.java
index 1bdc627..780c914 100644
--- a/src/main/java/io/wcm/handler/link/LinkRequest.java
+++ b/src/main/java/io/wcm/handler/link/LinkRequest.java
@@ -31,7 +31,7 @@
import com.day.cq.wcm.api.Page;
-import io.wcm.wcm.commons.util.ToStringStyle;
+import io.wcm.wcm.commons.util.AemObjectReflectionToStringBuilder;
/**
* Holds all properties that are part of a link handling request.
@@ -121,7 +121,22 @@ public LinkRequest(@Nullable Resource resource, @Nullable Page page, @Nullable S
@Override
public String toString() {
- return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE);
+ ToStringBuilder sb = new ToStringBuilder(this,
+ io.wcm.wcm.commons.util.ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE);
+ if (resource != null) {
+ sb.append("resource", resource.getPath());
+ sb.append("resourceProperties", AemObjectReflectionToStringBuilder.filteredValueMap(resource.getValueMap()));
+ }
+ if (page != null) {
+ sb.append("page", page.getPath());
+ }
+ if (reference != null) {
+ sb.append("reference", reference);
+ }
+ if (linkArgs != null) {
+ sb.append("linkArgs", linkArgs);
+ }
+ return sb.build();
}
}
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 705b0fc..f471e58 100644
--- a/src/main/java/io/wcm/handler/link/impl/LinkHandlerImpl.java
+++ b/src/main/java/io/wcm/handler/link/impl/LinkHandlerImpl.java
@@ -31,6 +31,8 @@
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.day.cq.wcm.api.Page;
@@ -66,6 +68,8 @@ public final class LinkHandlerImpl implements LinkHandler {
@OSGiService
private ComponentPropertyResolverFactory componentPropertyResolverFactory;
+ private static final Logger log = LoggerFactory.getLogger(LinkHandlerImpl.class);
+
@Override
public @NotNull LinkBuilder get(@Nullable Resource resource) {
return new LinkBuilderImpl(resource, this, componentPropertyResolverFactory);
@@ -119,10 +123,15 @@ Link processRequest(@NotNull LinkRequest linkRequest) {
}
Link link = new Link(linkType, linkRequest);
+ if (log.isTraceEnabled()) {
+ log.trace("Start processing link request (linkType={}): {}", linkType.getId(), linkRequest);
+ }
+
// preprocess link before resolving
List> linkPreProcessors = linkHandlerConfig.getPreProcessors();
if (linkPreProcessors != null) {
for (Class extends LinkProcessor> processorClass : linkPreProcessors) {
+ log.trace("Apply pre processor ({}): {}", processorClass, linkRequest);
LinkProcessor processor = AdaptTo.notNull(adaptable, processorClass);
link = processor.process(link);
if (link == null) {
@@ -141,6 +150,7 @@ Link processRequest(@NotNull LinkRequest linkRequest) {
if (!link.isValid()) {
LinkRequest fallbackLinkRequest = getFallbackLinkRequest(linkRequest);
if (fallbackLinkRequest != null) {
+ log.trace("Link is invalid ({}) - process fallback link request: {}", link, fallbackLinkRequest);
Link fallbackLink = processRequest(fallbackLinkRequest);
if (fallbackLink.isValid()) {
return fallbackLink;
@@ -155,6 +165,7 @@ Link processRequest(@NotNull LinkRequest linkRequest) {
for (Class extends LinkMarkupBuilder> linkMarkupBuilderClass : linkMarkupBuilders) {
LinkMarkupBuilder linkMarkupBuilder = AdaptTo.notNull(adaptable, linkMarkupBuilderClass);
if (linkMarkupBuilder.accepts(l)) {
+ log.trace("Apply link markup builder ({}): {}", linkMarkupBuilderClass, linkRequest);
return linkMarkupBuilder.build(l);
}
}
@@ -166,6 +177,7 @@ Link processRequest(@NotNull LinkRequest linkRequest) {
List> linkPostProcessors = linkHandlerConfig.getPostProcessors();
if (linkPostProcessors != null) {
for (Class extends LinkProcessor> processorClass : linkPostProcessors) {
+ log.trace("Apply post processor ({}): {}", processorClass, linkRequest);
LinkProcessor processor = AdaptTo.notNull(adaptable, processorClass);
link = processor.process(link);
if (link == null) {
@@ -174,6 +186,8 @@ Link processRequest(@NotNull LinkRequest linkRequest) {
}
}
+ log.debug("Finished link processing: {}", link);
+
return link;
}
diff --git a/src/main/java/io/wcm/handler/link/type/MediaLinkType.java b/src/main/java/io/wcm/handler/link/type/MediaLinkType.java
index 58f5bf2..7e8a5ed 100644
--- a/src/main/java/io/wcm/handler/link/type/MediaLinkType.java
+++ b/src/main/java/io/wcm/handler/link/type/MediaLinkType.java
@@ -97,7 +97,7 @@ public boolean hasRichTextPlugin() {
@Override
public boolean accepts(@NotNull String linkRef) {
// accept as media link if the ref is inside default media subtrees
- return MediaLinkType.isDefaultMediaContentPath(linkRef);
+ return isDefaultMediaContentPath(linkRef);
}
@SuppressWarnings("null")
diff --git a/src/main/java/io/wcm/handler/link/type/helpers/SyntheticNavigatableResource.java b/src/main/java/io/wcm/handler/link/type/helpers/SyntheticNavigatableResource.java
index b0463a1..1d4cb20 100644
--- a/src/main/java/io/wcm/handler/link/type/helpers/SyntheticNavigatableResource.java
+++ b/src/main/java/io/wcm/handler/link/type/helpers/SyntheticNavigatableResource.java
@@ -80,7 +80,7 @@ public Resource getParent() {
if (parentPath == null) {
return null;
}
- return SyntheticNavigatableResource.get(parentPath, resolver);
+ return get(parentPath, resolver);
}
/**
diff --git a/src/site/markdown/graniteui-components.md b/src/site/markdown/graniteui-components.md
index 7c20e2e..cb9047e 100644
--- a/src/site/markdown/graniteui-components.md
+++ b/src/site/markdown/graniteui-components.md
@@ -7,7 +7,7 @@
A component that defines the full set of fields for defining a link with it's properties to be included in a dialog tab. The link types are displayed dynamically as configured in the link handler configuration. It is possible to add your own fields.
-```json
+```json-jcr
{
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "granite/ui/components/coral/foundation/fixedcolumns",
@@ -36,7 +36,7 @@ The link source input will be dynamically shown/hidden according to the link typ
This is a customized Path Field that always sets the root path to the link root path as defined by the Link Handler configuration for internal links. By default, this is the site root path as defined by the URL Handler configuration.
-```json
+```json-jcr
"field": {
"sling:resourceType": "wcm-io/handler/link/components/granite/form/internalLinkPathField",
"fieldLabel": "Internal page (same site)"
@@ -53,7 +53,7 @@ This component extends the [wcm.io Granite UI components Path Field][wcmio-wcm-u
This is a customized Path Field that always sets the root path to the link root path as defined by the Link Handler configuration for internal cross-context links. By default, this is `/content`.
-```json
+```json-jcr
"field": {
"sling:resourceType": "wcm-io/handler/link/components/granite/form/internalCrossContextLinkPathField",
"fieldLabel": "Internal Page (other site)"
@@ -70,7 +70,7 @@ This component extends the [wcm.io Granite UI components Path Field][wcmio-wcm-u
This is a customized Path Field that always sets the root path to the link root path as defined by the Link Handler configuration for media links. By default, this is `/content/dam`.
-```json
+```json-jcr
"field": {
"sling:resourceType": "wcm-io/handler/link/components/granite/form/mediaLinkPathField",
"fieldLabel": "Asset reference"
diff --git a/src/test/java/io/wcm/handler/link/LinkTest.java b/src/test/java/io/wcm/handler/link/LinkTest.java
index afa7d14..fd76e6f 100644
--- a/src/test/java/io/wcm/handler/link/LinkTest.java
+++ b/src/test/java/io/wcm/handler/link/LinkTest.java
@@ -110,7 +110,8 @@ void testTargetRendition() {
@Test
void testToString() {
- assertEquals("Link[linkReferenceInvalid=false,linkRequest=LinkRequest[linkArgs=LinkArgs[disableSuffixSelector=false,dummyLink=false]],linkType=linkType]",
+ assertEquals("Link[valid=false,linkReferenceInvalid=false,linkType=linkType,"
+ + "linkRequest=LinkRequest[linkArgs=LinkArgs[disableSuffixSelector=false,dummyLink=false]]]",
underTest.toString());
}
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 f24be12..2ea6d00 100644
--- a/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java
+++ b/src/test/java/io/wcm/handler/link/impl/LinkHandlerImplTest.java
@@ -207,7 +207,7 @@ public List> getPostProcessors() {
return List.of(TestLinkPostProcessor.class);
}
- };
+ }
@Model(adaptables = {
SlingHttpServletRequest.class, Resource.class
diff --git a/src/test/java/io/wcm/handler/link/impl/SeoSitemapLinkExternalizerImplTest.java b/src/test/java/io/wcm/handler/link/impl/SeoSitemapLinkExternalizerImplTest.java
index 2ca907c..455c049 100644
--- a/src/test/java/io/wcm/handler/link/impl/SeoSitemapLinkExternalizerImplTest.java
+++ b/src/test/java/io/wcm/handler/link/impl/SeoSitemapLinkExternalizerImplTest.java
@@ -56,7 +56,7 @@ class SeoSitemapLinkExternalizerImplTest {
private Page page1;
@BeforeEach
- void setUp() throws Exception {
+ void setUp() {
// simulate AEM built-in SitemapLinkExternalizer with lower service ranking
context.registerService(SitemapLinkExternalizer.class, aemSitemapLinkExternalizer,
diff --git a/src/test/java/io/wcm/handler/link/testcontext/DummyAppTemplate.java b/src/test/java/io/wcm/handler/link/testcontext/DummyAppTemplate.java
index 9b4c1ad..38d0926 100644
--- a/src/test/java/io/wcm/handler/link/testcontext/DummyAppTemplate.java
+++ b/src/test/java/io/wcm/handler/link/testcontext/DummyAppTemplate.java
@@ -62,8 +62,8 @@ public enum DummyAppTemplate {
// build resource type from template path
String resourceTypeFromTemplatePath = null;
- final Pattern TEMPLATE_PATH_PATTERN = Pattern.compile("^/apps/([^/]+)/templates(/.*)?/([^/]+)$");
- Matcher templateParts = TEMPLATE_PATH_PATTERN.matcher(templatePath);
+ final Pattern templatePathPattern = Pattern.compile("^/apps/([^/]+)/templates(/.*)?/([^/]+)$");
+ Matcher templateParts = templatePathPattern.matcher(templatePath);
if (templateParts.matches()) {
resourceTypeFromTemplatePath = templateParts.group(1) + "/components" + StringUtils.defaultString(templateParts.group(2))
+ "/page/" + templateParts.group(3);
@@ -72,11 +72,6 @@ public enum DummyAppTemplate {
this.resourceType = resourceTypeFromTemplatePath;
}
- DummyAppTemplate(String templatePath, String resourceType) {
- this.templatePath = templatePath;
- this.resourceType = resourceType;
- }
-
/**
* Template path
* @return Path
diff --git a/src/test/java/io/wcm/handler/link/type/ExternalLinkTypeTest.java b/src/test/java/io/wcm/handler/link/type/ExternalLinkTypeTest.java
index 8ec3a13..8485e7a 100644
--- a/src/test/java/io/wcm/handler/link/type/ExternalLinkTypeTest.java
+++ b/src/test/java/io/wcm/handler/link/type/ExternalLinkTypeTest.java
@@ -101,7 +101,7 @@ void testGetSyntheticLinkResource() {
}
@Test
- void testAccepts() throws Exception {
+ void testAccepts() {
LinkType underTest = AdaptTo.notNull(adaptable(), ExternalLinkType.class);
assertTrue(underTest.accepts("http://hostname"));
diff --git a/src/test/java/io/wcm/handler/link/type/InternalCrossContextLinkTypeTest.java b/src/test/java/io/wcm/handler/link/type/InternalCrossContextLinkTypeTest.java
index 8e20e92..d6f0e60 100644
--- a/src/test/java/io/wcm/handler/link/type/InternalCrossContextLinkTypeTest.java
+++ b/src/test/java/io/wcm/handler/link/type/InternalCrossContextLinkTypeTest.java
@@ -62,7 +62,7 @@ protected Adaptable adaptable() {
}
@BeforeEach
- void setUp() throws Exception {
+ void setUp() {
// create current page in site context
context.currentPage(context.create().page("/content/unittest/de_test/brand/de/section/page",
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 de42b75..257f72c 100644
--- a/src/test/java/io/wcm/handler/link/type/InternalLinkTypeTest.java
+++ b/src/test/java/io/wcm/handler/link/type/InternalLinkTypeTest.java
@@ -72,7 +72,7 @@ protected Adaptable adaptable() {
}
@BeforeEach
- void setUp() throws Exception {
+ void setUp() {
// create current page in site context
context.currentPage(context.create().page("/content/unittest/de_test/brand/de/section/page",
@@ -219,7 +219,7 @@ void testSecureTargetPage() {
}
@Test
- void testRedirectInternal() throws Exception {
+ void testRedirectInternal() {
LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class);
Page redirectInternalPage = context.create().page("/content/unittest/de_test/brand/de/section/redirectInternal",
@@ -240,7 +240,7 @@ void testRedirectInternal() throws Exception {
}
@Test
- void testRedirectInternal_cqRedirectTarget() throws Exception {
+ void testRedirectInternal_cqRedirectTarget() {
LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class);
// redirect page using cq:redirectTarget property
@@ -259,7 +259,7 @@ void testRedirectInternal_cqRedirectTarget() throws Exception {
}
@Test
- void testRedirectInternal_EditMode() throws Exception {
+ void testRedirectInternal_EditMode() {
if (!(adaptable() instanceof SlingHttpServletRequest)) {
return;
}
@@ -282,7 +282,7 @@ void testRedirectInternal_EditMode() throws Exception {
@Test
@SuppressWarnings("null")
- void testRedirectRedirectInternal() throws Exception {
+ void testRedirectRedirectInternal() {
LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class);
Page redirectInternalPage = context.create().page("/content/unittest/de_test/brand/de/section/redirectInternal",
@@ -313,7 +313,7 @@ void testRedirectRedirectInternal() throws Exception {
@Test
@SuppressWarnings("null")
- void testRedirectExternal() throws Exception {
+ void testRedirectExternal() {
LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class);
Page redirectExternalPage = context.create().page("/content/unittest/de_test/brand/de/section/redirectExternal",
@@ -332,7 +332,7 @@ void testRedirectExternal() throws Exception {
}
@Test
- void testRedirectCyclic() throws Exception {
+ void testRedirectCyclic() {
LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class);
String redirectInternalCyclic1Path = "/content/unittest/de_test/brand/de/section/redirectInternalCyclic1";
@@ -363,7 +363,7 @@ void testRedirectCyclic() throws Exception {
}
@Test
- void testIntegrator() throws Exception {
+ void testIntegrator() {
LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class);
Page integratorPage = context.create().page("/content/unittest/de_test/brand/de/section/integrator",
@@ -382,7 +382,7 @@ void testIntegrator() throws Exception {
}
@Test
- void testIntegrator_EditMode() throws Exception {
+ void testIntegrator_EditMode() {
if (!(adaptable() instanceof SlingHttpServletRequest)) {
return;
}
diff --git a/src/test/java/io/wcm/handler/link/type/MediaLinkTypeTest.java b/src/test/java/io/wcm/handler/link/type/MediaLinkTypeTest.java
index 1dddfd2..db34e0f 100644
--- a/src/test/java/io/wcm/handler/link/type/MediaLinkTypeTest.java
+++ b/src/test/java/io/wcm/handler/link/type/MediaLinkTypeTest.java
@@ -120,25 +120,6 @@ void testInvalidLink_EditMode() {
assertEquals("/my/dummy/url", link.getAnchor().getHRef(), "anchor.href");
}
- // --> does not work because dummy implementation does not support download media format detection
- //@Test
- //void testInvalidImageLink() {
- // LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class);
- //
- // SyntheticLinkResource linkResource = new SyntheticLinkResource(context.resourceResolver(),
- // "/content/dummy-path",
- // ImmutableValueMap.builder()
- // .put(LinkNameConstants.PN_LINK_TYPE, MediaLinkType.ID)
- // .put(LinkNameConstants.PN_LINK_MEDIA_REF, "/content/dam/dummymedia/image1")
- // .build());
- //
- // Link link = linkHandler.get(linkResource).build();
- //
- // assertFalse("link invalid", link.isValid());
- // assertNull("link url", link.getUrl());
- // assertNull("anchor", link.getAnchor());
- //}
-
@Test
void testValidPdfLink() {
LinkHandler linkHandler = AdaptTo.notNull(adaptable(), LinkHandler.class);
diff --git a/src/test/java/io/wcm/handler/link/type/helpers/InternalLinkResolverTest.java b/src/test/java/io/wcm/handler/link/type/helpers/InternalLinkResolverTest.java
index 75d8a66..efe16f8 100644
--- a/src/test/java/io/wcm/handler/link/type/helpers/InternalLinkResolverTest.java
+++ b/src/test/java/io/wcm/handler/link/type/helpers/InternalLinkResolverTest.java
@@ -54,7 +54,7 @@ class InternalLinkResolverTest {
private final AemContext context = AppAemContext.newAemContext();
@BeforeEach
- void setUp() throws Exception {
+ void setUp() {
// create current page in site context
context.currentPage(context.create().page("/content/unittest/de_test/brand/de/section/page",