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({ "unchecked", "null" })
66 @Override
67 public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
68 if (type == UrlHandlerConfig.class) {
69 return (AdapterType)serviceResolver.resolve(UrlHandlerConfig.class, (Adaptable)adaptable);
70 }
71 if (type == SiteConfig.class) {
72 return (AdapterType)getSiteConfigForSiteRoot(getContextResource(adaptable));
73 }
74 return null;
75 }
76
77 private Resource getContextResource(Object adaptable) {
78 if (adaptable instanceof Resource) {
79 return (Resource)adaptable;
80 }
81 else if (adaptable instanceof SlingHttpServletRequest) {
82 return ((SlingHttpServletRequest)adaptable).getResource();
83 }
84 return null;
85 }
86
87 private SiteConfig getSiteConfigForSiteRoot(Resource contextResource) {
88 if (contextResource == null) {
89 return null;
90 }
91 String contextRootPath = configurationResourceResolver.getContextPath(contextResource);
92
93
94 if (StringUtils.isBlank(contextRootPath)) {
95 return getSiteConfigForResource(contextResource);
96 }
97
98
99 return siteConfigCache.get(contextRootPath, path -> {
100 Resource siteRootResource = contextResource.getResourceResolver().getResource(contextRootPath);
101 return getSiteConfigForResourceCacheable(siteRootResource);
102 });
103 }
104
105
106
107
108
109
110
111 private SiteConfig getSiteConfigForResourceCacheable(Resource contextResource) {
112 final SiteConfig siteConfig = getSiteConfigForResource(contextResource);
113 return new SiteConfig() {
114 @Override
115 public Class<? extends Annotation> annotationType() {
116 return SiteConfig.class;
117 }
118 @Override
119 public String siteUrl() {
120 return siteConfig.siteUrl();
121 }
122 @Override
123 public String siteUrlSecure() {
124 return siteConfig.siteUrlSecure();
125 }
126 @Override
127 public String siteUrlAuthor() {
128 return siteConfig.siteUrlAuthor();
129 }
130
131 };
132 }
133
134 @SuppressWarnings("java:S112")
135 private SiteConfig getSiteConfigForResource(Resource contextResource) {
136 ConfigurationBuilder configurationBuilder = contextResource.adaptTo(ConfigurationBuilder.class);
137 if (configurationBuilder == null) {
138 throw new RuntimeException("No configuration builder.");
139 }
140 return configurationBuilder.as(SiteConfig.class);
141 }
142
143 }