1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.handler.mediasource.dam.impl;
21
22 import java.util.Date;
23 import java.util.List;
24
25 import org.apache.commons.io.FilenameUtils;
26 import org.apache.sling.api.adapter.SlingAdaptable;
27 import org.apache.sling.api.resource.Resource;
28 import org.apache.sling.api.resource.ValueMap;
29 import org.jetbrains.annotations.NotNull;
30 import org.jetbrains.annotations.Nullable;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
35 import io.wcm.handler.media.CropDimension;
36 import io.wcm.handler.media.MediaArgs;
37 import io.wcm.handler.media.MediaFileType;
38 import io.wcm.handler.media.Rendition;
39 import io.wcm.handler.media.UriTemplate;
40 import io.wcm.handler.media.UriTemplateType;
41 import io.wcm.handler.media.format.MediaFormat;
42 import io.wcm.handler.url.UrlHandler;
43 import io.wcm.sling.commons.adapter.AdaptTo;
44 import io.wcm.wcm.commons.caching.ModificationDate;
45
46
47
48
49 class DamRendition extends SlingAdaptable implements Rendition {
50
51 private final DamContext damContext;
52 private final MediaArgs mediaArgs;
53 private final RenditionMetadata rendition;
54 private boolean fallback;
55
56 private static final Logger log = LoggerFactory.getLogger(DamRendition.class);
57
58
59
60
61
62
63 @SuppressWarnings("java:S3776")
64 DamRendition(CropDimension cropDimension, Integer rotation, MediaArgs mediaArgs, DamContext damContext) {
65 this.damContext = damContext;
66 this.mediaArgs = mediaArgs;
67 RenditionMetadata resolvedRendition = null;
68
69
70 if (cropDimension == null && rotation == null) {
71 RenditionHandler renditionHandler = new DefaultRenditionHandler(damContext);
72 resolvedRendition = renditionHandler.getRendition(mediaArgs);
73 }
74
75 else {
76
77 RenditionHandler renditionHandler = new TransformedRenditionHandler(cropDimension, rotation, damContext);
78 resolvedRendition = renditionHandler.getRendition(mediaArgs);
79
80
81 if (resolvedRendition == null && cropDimension != null) {
82 if (rotation != null) {
83 renditionHandler = new TransformedRenditionHandler(null, rotation, damContext);
84 resolvedRendition = renditionHandler.getRendition(mediaArgs);
85 }
86 else {
87 renditionHandler = new DefaultRenditionHandler(damContext);
88 resolvedRendition = renditionHandler.getRendition(mediaArgs);
89 }
90 if (resolvedRendition != null) {
91 fallback = true;
92 }
93 }
94 }
95
96
97
98 if (resolvedRendition == null && mediaArgs.isAutoCrop()) {
99 DamAutoCropping autoCropping = new DamAutoCropping(damContext, mediaArgs);
100 List<CropDimension> autoCropDimensions = autoCropping.calculateAutoCropDimensions();
101 for (CropDimension autoCropDimension : autoCropDimensions) {
102 RenditionHandler renditionHandler = new TransformedRenditionHandler(autoCropDimension, rotation, damContext);
103 resolvedRendition = renditionHandler.getRendition(mediaArgs);
104 if (resolvedRendition != null) {
105 break;
106 }
107 }
108 }
109
110 if (log.isTraceEnabled()) {
111 log.trace("DamRendition: resolvedRendition={}, mediaArgs={}, cropDimension={}, rotation={}",
112 resolvedRendition, mediaArgs, cropDimension, rotation);
113 }
114
115 this.rendition = resolvedRendition;
116 }
117
118 @Override
119 public String getUrl() {
120 if (rendition == null) {
121 return null;
122 }
123 String url = null;
124
125
126 if (damContext.isDynamicMediaEnabled()) {
127 if (damContext.isDynamicMediaAsset()) {
128 url = buildDynamicMediaUrl();
129 if (url == null) {
130
131
132 return null;
133 }
134 }
135 else {
136
137 if (damContext.isDynamicMediaAemFallbackDisabled()) {
138 log.warn("Asset is not a valid DM asset, fallback disabled, rendition invalid: {}", rendition.getRendition().getPath());
139 return null;
140 }
141 else {
142 log.trace("Asset is not a valid DM asset, fallback to AEM-rendered rendition: {}", rendition.getRendition().getPath());
143 }
144 }
145 }
146
147
148 if (url == null) {
149 url = buildWebOptimizedImageDeliveryUrl();
150 }
151
152
153 if (url == null) {
154 UrlHandler urlHandler = AdaptTo.notNull(damContext, UrlHandler.class);
155 String mediaPath = rendition.getMediaPath(mediaArgs.isContentDispositionAttachment());
156 url = urlHandler.get(mediaPath).urlMode(mediaArgs.getUrlMode())
157 .buildExternalResourceUrl(rendition.adaptTo(Resource.class));
158 }
159
160 return url;
161 }
162
163
164
165
166
167 private @Nullable String buildDynamicMediaUrl() {
168 String dynamicMediaPath = rendition.getDynamicMediaPath(mediaArgs.isContentDispositionAttachment(), damContext);
169 String productionAssetUrl = damContext.getDynamicMediaServerUrl();
170 if (dynamicMediaPath != null && productionAssetUrl != null) {
171 return productionAssetUrl + dynamicMediaPath;
172 }
173 else {
174 return null;
175 }
176 }
177
178
179
180
181
182 private @Nullable String buildWebOptimizedImageDeliveryUrl() {
183 if (MediaFileType.isImage(getFileExtension())
184 && !MediaFileType.isVectorImage(getFileExtension())
185 && !mediaArgs.isContentDispositionAttachment()
186 && !mediaArgs.isWebOptimizedImageDeliveryDisabled()) {
187 return rendition.getWebOptimizedImageDeliveryPath(damContext);
188 }
189 else {
190 return null;
191 }
192 }
193
194
195 @Override
196 public String getPath() {
197 if (this.rendition != null) {
198 return this.rendition.getRendition().getPath();
199 }
200 else {
201 return null;
202 }
203 }
204
205 @Override
206 public String getFileName() {
207 if (this.rendition != null) {
208 return this.rendition.getFileName(this.mediaArgs.isContentDispositionAttachment());
209 }
210 else {
211 return null;
212 }
213 }
214
215 @Override
216 public String getFileExtension() {
217 return FilenameUtils.getExtension(getFileName());
218 }
219
220 @Override
221 public long getFileSize() {
222 if (this.rendition != null) {
223 return this.rendition.getFileSize();
224 }
225 else {
226 return 0L;
227 }
228 }
229
230 @Override
231 public String getMimeType() {
232 if (this.rendition != null) {
233 return this.rendition.getMimeType();
234 }
235 else {
236 return null;
237 }
238 }
239
240 @Override
241 public Date getModificationDate() {
242 if (this.rendition != null) {
243 return ModificationDate.get(this.rendition.getRendition().adaptTo(Resource.class));
244 }
245 else {
246 return null;
247 }
248 }
249
250 @Override
251 public MediaFormat getMediaFormat() {
252 if (this.rendition != null) {
253 return this.rendition.getMediaFormat();
254 }
255 else {
256 return null;
257 }
258 }
259
260 @Override
261 @SuppressWarnings("null")
262 @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE")
263 public @NotNull ValueMap getProperties() {
264 if (this.rendition != null) {
265 return this.rendition.getRendition().adaptTo(Resource.class).getValueMap();
266 }
267 else {
268 return ValueMap.EMPTY;
269 }
270 }
271
272 @Override
273 public boolean isImage() {
274 return MediaFileType.isImage(getFileExtension());
275 }
276
277 @Override
278 public boolean isBrowserImage() {
279 return MediaFileType.isBrowserImage(getFileExtension());
280 }
281
282 @Override
283 public boolean isVectorImage() {
284 return MediaFileType.isVectorImage(getFileExtension());
285 }
286
287 @Override
288 public boolean isDownload() {
289 return !isImage();
290 }
291
292 @Override
293 public long getWidth() {
294 if (this.rendition != null) {
295 return this.rendition.getWidth();
296 }
297 else {
298 return 0;
299 }
300 }
301
302 @Override
303 public long getHeight() {
304 if (this.rendition != null) {
305 return this.rendition.getHeight();
306 }
307 else {
308 return 0;
309 }
310 }
311
312 @Override
313 public boolean isFallback() {
314 return fallback;
315 }
316
317 @Override
318 public @NotNull UriTemplate getUriTemplate(@NotNull UriTemplateType type) {
319 if (this.rendition == null) {
320 throw new IllegalStateException("Rendition is not valid.");
321 }
322 if (type == UriTemplateType.CROP_CENTER) {
323 throw new IllegalArgumentException("CROP_CENTER not supported for rendition URI templates.");
324 }
325 return this.rendition.getUriTemplate(type, damContext);
326 }
327
328 @Override
329 @SuppressWarnings("null")
330 public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
331 if (this.rendition != null) {
332 AdapterType result = this.rendition.adaptTo(type);
333 if (result != null) {
334 return result;
335 }
336 }
337 return super.adaptTo(type);
338 }
339
340 @Override
341 public String toString() {
342 if (rendition != null) {
343 return rendition.toString();
344 }
345 return super.toString();
346 }
347
348 }