1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.sling.models.injectors.impl;
21
22 import java.lang.reflect.AnnotatedElement;
23 import java.lang.reflect.Type;
24 import java.util.Locale;
25
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.sling.api.SlingHttpServletRequest;
28 import org.apache.sling.api.resource.Resource;
29 import org.apache.sling.api.resource.ResourceResolver;
30 import org.apache.sling.api.scripting.SlingBindings;
31 import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
32 import org.apache.sling.models.spi.AcceptsNullName;
33 import org.apache.sling.models.spi.DisposalCallbackRegistry;
34 import org.apache.sling.models.spi.Injector;
35 import org.apache.sling.models.spi.injectorspecific.AbstractInjectAnnotationProcessor2;
36 import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor2;
37 import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
38 import org.apache.sling.xss.XSSAPI;
39 import org.jetbrains.annotations.NotNull;
40 import org.jetbrains.annotations.Nullable;
41 import org.osgi.framework.Constants;
42 import org.osgi.service.component.annotations.Component;
43 import org.osgi.service.component.annotations.Reference;
44
45 import com.adobe.cq.sightly.WCMBindings;
46 import com.adobe.granite.workflow.WorkflowSession;
47 import com.day.cq.i18n.I18n;
48 import com.day.cq.tagging.TagManager;
49 import com.day.cq.wcm.api.AuthoringUIMode;
50 import com.day.cq.wcm.api.Page;
51 import com.day.cq.wcm.api.PageManager;
52 import com.day.cq.wcm.api.WCMMode;
53 import com.day.cq.wcm.api.components.ComponentContext;
54 import com.day.cq.wcm.api.designer.Design;
55 import com.day.cq.wcm.api.designer.Designer;
56 import com.day.cq.wcm.api.designer.Style;
57 import com.day.cq.wcm.commons.WCMUtils;
58
59 import io.wcm.sling.commons.request.RequestContext;
60 import io.wcm.sling.models.annotations.AemObject;
61
62
63
64
65
66 @Component(service = { Injector.class, StaticInjectAnnotationProcessorFactory.class }, property = {
67
68
69
70
71
72
73 Constants.SERVICE_RANKING + ":Integer=" + 4400
74 })
75 public final class AemObjectInjector implements Injector, StaticInjectAnnotationProcessorFactory, AcceptsNullName {
76
77
78
79
80 public static final @NotNull String NAME = "wcm-io-aem-object";
81
82 static final String RESOURCE_PAGE = "resourcePage";
83 static final String USER_I18N = "userI18n";
84
85 @Reference
86 private RequestContext requestContext;
87 @Reference
88 private ModelsImplConfiguration modelsImplConfiguration;
89
90 @Override
91 public @NotNull String getName() {
92 return NAME;
93 }
94
95 @Override
96 @SuppressWarnings("java:S3776")
97 public Object getValue(@NotNull final Object adaptable, final String name, @NotNull final Type type,
98 @NotNull final AnnotatedElement element, @NotNull final DisposalCallbackRegistry callbackRegistry) {
99
100
101 if (!(type instanceof Class<?>)) {
102 return null;
103 }
104 Class<?> requestedClass = (Class<?>)type;
105
106 SlingHttpServletRequest request = getRequest(adaptable);
107 if (request != null) {
108 if (requestedClass.equals(WCMMode.class)) {
109 return getWcmMode(request);
110 }
111 if (requestedClass.equals(AuthoringUIMode.class)) {
112 return getAuthoringUiMode(request);
113 }
114 if (requestedClass.equals(ComponentContext.class)) {
115 return getComponentContext(request);
116 }
117 if (requestedClass.equals(Style.class)) {
118 return getStyle(request);
119 }
120 if (requestedClass.equals(XSSAPI.class)) {
121 return getXssApi(request);
122 }
123 if (requestedClass.equals(I18n.class)) {
124 if (StringUtils.equals(name, USER_I18N)) {
125 return getUserI18n(request);
126 }
127 else {
128 return getResourceI18n(request);
129 }
130 }
131 }
132
133 if (requestedClass.equals(PageManager.class)) {
134 return getPageManager(adaptable);
135 }
136 else if (requestedClass.equals(Page.class)) {
137 if (StringUtils.equals(name, RESOURCE_PAGE)) {
138 return getResourcePage(adaptable);
139 }
140 else {
141 return getCurrentPage(adaptable);
142 }
143 }
144 else if (requestedClass.equals(Designer.class)) {
145 return getDesigner(adaptable);
146 }
147 else if (requestedClass.equals(Design.class)) {
148 return getCurrentDesign(adaptable);
149 }
150 else if (requestedClass.equals(TagManager.class)) {
151 return getTagManager(adaptable);
152 }
153 else if (requestedClass.equals(WorkflowSession.class)) {
154 return getWorkflowSession(adaptable);
155 }
156
157 return null;
158 }
159
160 private @Nullable SlingHttpServletRequest getRequest(@NotNull final Object adaptable) {
161 if (adaptable instanceof SlingHttpServletRequest) {
162 return (SlingHttpServletRequest)adaptable;
163 }
164 else if (modelsImplConfiguration.isRequestThreadLocal()) {
165 return requestContext.getThreadRequest();
166 }
167 else {
168 return null;
169 }
170 }
171
172 private @Nullable ResourceResolver getResourceResolver(@NotNull final Object adaptable) {
173 if (adaptable instanceof ResourceResolver) {
174 return (ResourceResolver)adaptable;
175 }
176 if (adaptable instanceof Resource) {
177 return ((Resource)adaptable).getResourceResolver();
178 }
179 if (adaptable instanceof Page) {
180 Resource resource = ((Page)adaptable).adaptTo(Resource.class);
181 if (resource != null) {
182 return resource.getResourceResolver();
183 }
184 }
185 SlingHttpServletRequest request = getRequest(adaptable);
186 if (request != null) {
187 return request.getResourceResolver();
188 }
189 return null;
190 }
191
192 private @Nullable Resource getResource(@NotNull final Object adaptable) {
193 if (adaptable instanceof Resource) {
194 return (Resource)adaptable;
195 }
196 if (adaptable instanceof Page) {
197 return ((Page)adaptable).adaptTo(Resource.class);
198 }
199 SlingHttpServletRequest request = getRequest(adaptable);
200 if (request != null) {
201 return request.getResource();
202 }
203 return null;
204 }
205
206 private @Nullable PageManager getPageManager(@NotNull final Object adaptable) {
207 ResourceResolver resolver = getResourceResolver(adaptable);
208 if (resolver != null) {
209 return resolver.adaptTo(PageManager.class);
210 }
211 return null;
212 }
213
214 private @Nullable Designer getDesigner(@NotNull final Object adaptable) {
215 ResourceResolver resolver = getResourceResolver(adaptable);
216 if (resolver != null) {
217 return resolver.adaptTo(Designer.class);
218 }
219 return null;
220 }
221
222 private @Nullable Page getCurrentPage(@NotNull final Object adaptable) {
223 SlingHttpServletRequest request = getRequest(adaptable);
224 if (request != null) {
225 ComponentContext context = getComponentContext(request);
226 if (context != null) {
227 return context.getPage();
228 }
229 }
230 return getResourcePage(adaptable);
231 }
232
233 private @Nullable Page getResourcePage(@NotNull final Object adaptable) {
234 PageManager pageManager = getPageManager(adaptable);
235 Resource resource = getResource(adaptable);
236 if (pageManager != null && resource != null) {
237 return pageManager.getContainingPage(resource);
238 }
239 return null;
240 }
241
242 private @NotNull WCMMode getWcmMode(@NotNull final SlingHttpServletRequest request) {
243 return WCMMode.fromRequest(request);
244 }
245
246 private @NotNull AuthoringUIMode getAuthoringUiMode(@NotNull final SlingHttpServletRequest request) {
247 AuthoringUIMode mode = AuthoringUIMode.fromRequest(request);
248 if (mode == null) {
249
250 mode = AuthoringUIMode.TOUCH;
251 }
252 return mode;
253 }
254
255 private @Nullable ComponentContext getComponentContext(@NotNull final SlingHttpServletRequest request) {
256 return WCMUtils.getComponentContext(request);
257 }
258
259 private @Nullable Design getCurrentDesign(final Object adaptable) {
260 Page currentPage = getCurrentPage(adaptable);
261 Designer designer = getDesigner(adaptable);
262 if (currentPage != null && designer != null) {
263 return designer.getDesign(currentPage);
264 }
265 return null;
266 }
267
268 @SuppressWarnings("deprecation")
269 private @Nullable Style getStyle(@NotNull final SlingHttpServletRequest request) {
270 Style style = null;
271
272 SlingBindings slingBindings = getSlingBindings(request);
273 if (slingBindings != null) {
274 style = (Style)slingBindings.get(WCMBindings.CURRENT_STYLE);
275 }
276 if (style == null) {
277
278 Design currentDesign = getCurrentDesign(request);
279 ComponentContext componentContext = getComponentContext(request);
280 if (currentDesign != null && componentContext != null) {
281 style = currentDesign.getStyle(componentContext.getCell());
282 }
283 }
284 return style;
285 }
286
287 private @Nullable XSSAPI getXssApi(@NotNull final SlingHttpServletRequest request) {
288 return request.adaptTo(XSSAPI.class);
289 }
290
291 private @Nullable I18n getResourceI18n(@NotNull final SlingHttpServletRequest request) {
292 Page currentPage = getCurrentPage(request);
293 if (currentPage != null) {
294 Locale currentLocale = currentPage.getLanguage(false);
295 return new I18n(getI18nEnabledRequest(request).getResourceBundle(currentLocale));
296 }
297 return null;
298 }
299
300 private @NotNull I18n getUserI18n(@NotNull final SlingHttpServletRequest request) {
301 return new I18n(getI18nEnabledRequest(request));
302 }
303
304 private @Nullable TagManager getTagManager(@NotNull final Object adaptable) {
305 ResourceResolver resolver = getResourceResolver(adaptable);
306 if (resolver != null) {
307 return resolver.adaptTo(TagManager.class);
308 }
309 return null;
310 }
311
312 private @Nullable WorkflowSession getWorkflowSession(@NotNull final Object adaptable) {
313 ResourceResolver resolver = getResourceResolver(adaptable);
314 if (resolver != null) {
315 return resolver.adaptTo(WorkflowSession.class);
316 }
317 return null;
318 }
319
320
321
322
323
324
325
326
327
328
329
330 private @NotNull SlingHttpServletRequest getI18nEnabledRequest(@NotNull SlingHttpServletRequest request) {
331 SlingBindings bindings = getSlingBindings(request);
332 if (bindings != null) {
333 SlingHttpServletRequest bindingsRequest = bindings.getRequest();
334 if (bindingsRequest != null) {
335 return bindingsRequest;
336 }
337 }
338 if (modelsImplConfiguration.isRequestThreadLocal()) {
339 SlingHttpServletRequest threadLocalRequest = requestContext.getThreadRequest();
340 if (threadLocalRequest != null) {
341 return threadLocalRequest;
342 }
343 }
344 return request;
345 }
346
347 private @Nullable SlingBindings getSlingBindings(@NotNull SlingHttpServletRequest request) {
348 return (SlingBindings)request.getAttribute(SlingBindings.class.getName());
349 }
350
351 @SuppressWarnings({ "null", "unused" })
352 @Override
353 public InjectAnnotationProcessor2 createAnnotationProcessor(final AnnotatedElement element) {
354
355 AemObject annotation = element.getAnnotation(AemObject.class);
356 if (annotation != null) {
357 return new AemObjectAnnotationProcessor(annotation);
358 }
359 return null;
360 }
361
362 private static class AemObjectAnnotationProcessor extends AbstractInjectAnnotationProcessor2 {
363
364 private final AemObject annotation;
365
366 AemObjectAnnotationProcessor(final AemObject annotation) {
367 this.annotation = annotation;
368 }
369
370 @Override
371 public InjectionStrategy getInjectionStrategy() {
372 return annotation.injectionStrategy();
373 }
374
375 @Override
376 @SuppressWarnings("deprecation")
377 public Boolean isOptional() {
378 return annotation.optional();
379 }
380 }
381
382 }