1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.handler.url.impl;
21
22 import java.lang.annotation.Annotation;
23 import java.util.concurrent.TimeUnit;
24
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.sling.api.SlingHttpServletRequest;
27 import org.apache.sling.api.adapter.Adaptable;
28 import org.apache.sling.api.adapter.AdapterFactory;
29 import org.apache.sling.api.resource.Resource;
30 import org.apache.sling.caconfig.ConfigurationBuilder;
31 import org.apache.sling.caconfig.resource.ConfigurationResourceResolver;
32 import org.osgi.service.component.annotations.Component;
33 import org.osgi.service.component.annotations.Reference;
34
35 import com.github.benmanes.caffeine.cache.Cache;
36 import com.github.benmanes.caffeine.cache.Caffeine;
37
38 import io.wcm.handler.url.SiteConfig;
39 import io.wcm.handler.url.spi.UrlHandlerConfig;
40 import io.wcm.sling.commons.caservice.ContextAwareServiceResolver;
41
42
43
44
45 @Component(service = AdapterFactory.class,
46 property = {
47 AdapterFactory.ADAPTABLE_CLASSES + "=org.apache.sling.api.resource.Resource",
48 AdapterFactory.ADAPTABLE_CLASSES + "=org.apache.sling.api.SlingHttpServletRequest",
49 AdapterFactory.ADAPTER_CLASSES + "=io.wcm.handler.url.spi.UrlHandlerConfig",
50 AdapterFactory.ADAPTER_CLASSES + "=io.wcm.handler.url.SiteConfig"
51 })
52 public class UrlHandlerAdapterFactory implements AdapterFactory {
53
54 @Reference
55 private ContextAwareServiceResolver serviceResolver;
56 @Reference
57 private ConfigurationResourceResolver configurationResourceResolver;
58
59
60 private final Cache<String, SiteConfig> siteConfigCache = Caffeine.newBuilder()
61 .expireAfterWrite(5, TimeUnit.SECONDS)
62 .maximumSize(10000)
63 .build();
64
65 @SuppressWarnings({
66 "unchecked", "null"
67 })
68 @Override
69 public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
70 if (type == UrlHandlerConfig.class) {
71 return (AdapterType)serviceResolver.resolve(UrlHandlerConfig.class, (Adaptable)adaptable);
72 }
73 if (type == SiteConfig.class) {
74 return (AdapterType)getSiteConfigForSiteRoot(getContextResource(adaptable));
75 }
76 return null;
77 }
78
79 private Resource getContextResource(Object adaptable) {
80 if (adaptable instanceof Resource) {
81 return (Resource)adaptable;
82 }
83 else if (adaptable instanceof SlingHttpServletRequest) {
84 return ((SlingHttpServletRequest)adaptable).getResource();
85 }
86 return null;
87 }
88
89 private SiteConfig getSiteConfigForSiteRoot(Resource contextResource) {
90 if (contextResource == null) {
91 return null;
92 }
93 String contextRootPath = configurationResourceResolver.getContextPath(contextResource);
94
95
96 if (StringUtils.isBlank(contextRootPath)) {
97 return getSiteConfigForResource(contextResource);
98 }
99
100
101 return siteConfigCache.get(contextRootPath, path -> {
102 Resource siteRootResource = contextResource.getResourceResolver().getResource(contextRootPath);
103 return getSiteConfigForResourceCacheable(siteRootResource);
104 });
105 }
106
107
108
109
110
111
112
113 private SiteConfig getSiteConfigForResourceCacheable(Resource contextResource) {
114 final SiteConfig siteConfig = getSiteConfigForResource(contextResource);
115 return new SiteConfig() {
116
117 @Override
118 public Class<? extends Annotation> annotationType() {
119 return SiteConfig.class;
120 }
121
122 @Override
123 public String siteUrl() {
124 return siteConfig.siteUrl();
125 }
126
127 @Override
128 public String siteUrlSecure() {
129 return siteConfig.siteUrlSecure();
130 }
131
132 @Override
133 public String siteUrlAuthor() {
134 return siteConfig.siteUrlAuthor();
135 }
136
137 };
138 }
139
140 @SuppressWarnings("java:S112")
141 private SiteConfig getSiteConfigForResource(Resource contextResource) {
142 ConfigurationBuilder configurationBuilder = contextResource.adaptTo(ConfigurationBuilder.class);
143 if (configurationBuilder == null) {
144 throw new RuntimeException("No configuration builder.");
145 }
146 return configurationBuilder.as(SiteConfig.class);
147 }
148
149 }