1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.dam.templating.functions;
35
36 import info.magnolia.cms.core.AggregationState;
37 import info.magnolia.context.MgnlContext;
38 import info.magnolia.dam.api.Asset;
39 import info.magnolia.dam.api.AssetProvider;
40 import info.magnolia.dam.api.AssetProviderRegistry;
41 import info.magnolia.dam.api.AssetProviderRegistry.NoSuchAssetRendererException;
42 import info.magnolia.dam.api.AssetQuery;
43 import info.magnolia.dam.api.AssetRenderer;
44 import info.magnolia.dam.api.AssetRendition;
45 import info.magnolia.dam.api.Folder;
46 import info.magnolia.dam.api.Item;
47 import info.magnolia.dam.api.ItemKey;
48 import info.magnolia.dam.api.PathAwareAssetProvider;
49 import info.magnolia.dam.api.metadata.AssetMetadata;
50 import info.magnolia.dam.api.metadata.AssetMetadataDefinition;
51 import info.magnolia.dam.api.metadata.AssetMetadataRegistry;
52 import info.magnolia.dam.jcr.JcrAsset;
53 import info.magnolia.dam.jcr.JcrAssetProvider;
54 import info.magnolia.dam.jcr.JcrFolder;
55 import info.magnolia.jcr.wrapper.HTMLEscapingNodeWrapper;
56 import info.magnolia.objectfactory.Components;
57
58 import java.beans.BeanInfo;
59 import java.beans.Introspector;
60 import java.beans.PropertyDescriptor;
61 import java.lang.reflect.Method;
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.Collections;
65 import java.util.HashMap;
66 import java.util.Iterator;
67 import java.util.List;
68 import java.util.Map;
69 import java.util.Map.Entry;
70
71 import javax.inject.Inject;
72 import javax.inject.Singleton;
73
74 import org.apache.commons.lang3.StringUtils;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77
78 import com.google.common.base.Predicate;
79 import com.google.common.collect.Iterators;
80 import com.google.common.collect.Lists;
81 import com.google.common.collect.UnmodifiableIterator;
82 import com.google.common.net.MediaType;
83
84
85
86
87 @Singleton
88 public class DamTemplatingFunctions {
89
90 private static final Logger log = LoggerFactory.getLogger(DamTemplatingFunctions.class);
91
92 public static final String METADATA_KEY_ACCESS = "metadata";
93 public static final String DAM_VERSION_1_PROVIDER_ID = "jcr";
94
95 private final AssetProviderRegistry providerRegistry;
96 private final AssetMetadataRegistry metadataRegistry;
97
98
99
100
101 @Deprecated
102 public DamTemplatingFunctions(AssetProviderRegistry providerRegistry) {
103 this(providerRegistry, Components.getComponent(AssetMetadataRegistry.class));
104 }
105
106 @Inject
107 public DamTemplatingFunctions(AssetProviderRegistry providerRegistry, AssetMetadataRegistry metadataRegistry) {
108 this.providerRegistry = providerRegistry;
109 this.metadataRegistry = metadataRegistry;
110 }
111
112
113
114
115
116 public Asset getAsset(String itemKey) {
117 Item item = getItem(itemKey, true);
118 if (item != null) {
119 return (Asset) item;
120 }
121 return null;
122 }
123
124 public Asset getAsset(String providerId, String assetPath) {
125 Item item = getItem(providerId, assetPath, true);
126 if (item != null) {
127 return (Asset) item;
128 }
129 return null;
130 }
131
132 public Asset getAssetForAbsolutePath(String providerId, String absoluteAssetPath) {
133 AssetProvider provider = getProviderForId(providerId);
134 if (provider != null) {
135 String providerRootPath = provider.getRootFolder().getPath();
136 if (!StringUtils.endsWith(providerRootPath, "/")) {
137 providerRootPath += "/";
138 }
139 String relativeAssetPath = StringUtils.removeStart(absoluteAssetPath, providerRootPath);
140 log.debug("Convert absolute '{}' to relative '{}' path", absoluteAssetPath, relativeAssetPath);
141 return getAsset(providerId, relativeAssetPath);
142 }
143 return null;
144 }
145
146
147
148
149
150 public Folder getFolder(String itemKey) {
151 Item item = getItem(itemKey, false);
152 if (item != null) {
153 return (Folder) item;
154 }
155 return null;
156 }
157
158
159
160
161
162
163 public Folder getFolder(String providerId, String folderPath) {
164 Item item = getItem(providerId, folderPath, false);
165 if (item != null) {
166 return (Folder) item;
167 }
168 return null;
169 }
170
171
172
173
174 public Iterator<Item> getItems(String providerId, AssetQuery assetQuery) {
175 AssetProvider provider = getProviderForId(providerId);
176 if (provider != null) {
177 try {
178 return provider.list(assetQuery);
179 } catch (Exception e) {
180 log.warn("Exception occurred for the following query '{}' and asset provider '{}' : {}", assetQuery.toString(), providerId, e.getMessage());
181 }
182 }
183 return null;
184 }
185
186
187
188
189
190 public AssetRendition getRendition(Asset asset, MediaType mediaType, String renditionName) {
191 try {
192 final AssetRenderer renderer = providerRegistry.getRendererFor(asset, mediaType);
193 if (renderer.canRender(asset, mediaType)) {
194 return renderer.render(asset, mediaType, renditionName);
195 }
196 } catch (NoSuchAssetRendererException nsare) {
197 log.warn("No rendition found for the following assetId '{}', mediaType '{}' and renditionName '{}'. Exception: {} ", asset.getItemKey().asString(), mediaType.toString(), renditionName, nsare);
198 }
199 return null;
200 }
201
202
203
204
205 public AssetRendition getRendition(Asset asset, String renditionName) {
206 return getRendition(asset, MediaType.parse(asset.getMimeType()), renditionName);
207 }
208
209 public AssetRendition getRendition(String itemKey, String renditionName) {
210 Asset asset = getAsset(itemKey);
211 if (asset == null) {
212 log.warn("Trying to get asset with item key {} returned null.", itemKey);
213 return null;
214 }
215 return getRendition(asset, MediaType.parse(asset.getMimeType()), renditionName);
216 }
217
218 public AssetRendition getRendition(String itemKey, MediaType mediaType, String renditionName) {
219 return getRendition(getAsset(itemKey), mediaType, renditionName);
220 }
221
222
223
224
225 public boolean provides(String providerId, MediaType mediaType) {
226 try {
227 return providerRegistry.getProviderById(providerId).provides(mediaType);
228 } catch (Exception e) {
229 log.warn("Exception occurred for the following reason {}. False will be retruned. ", e.getMessage());
230 return false;
231 }
232 }
233
234
235
236
237
238
239 public Map<String, Object> getAssetMap(Asset asset) {
240 Map<String, Class<? extends AssetMetadata>> supportedMetadata = new HashMap<>();
241 for (AssetMetadataDefinition metadataDefinition : metadataRegistry.getAll()) {
242 if (asset.supports(metadataDefinition.getMetadataClass())) {
243 supportedMetadata.put(metadataDefinition.getNamespace(), metadataDefinition.getMetadataClass());
244 }
245 }
246
247 List<String> rejectedGetter = Arrays.asList("getAssetProvider", "getMetadata", "getContentStream", "getParent", "getClass", "supports");
248
249
250 Map<String, Object> rootMap = convertBeanToMap(asset, rejectedGetter);
251
252 Map<String, Object> metaDatasMap = new HashMap<>();
253
254 for (Entry<String, Class<? extends AssetMetadata>> entry : supportedMetadata.entrySet()) {
255 AssetMetadata metaData = asset.getMetadata(entry.getValue());
256 Map<String, Object> metaDataMap = convertBeanToMap(metaData, rejectedGetter);
257 metaDatasMap.put(entry.getKey(), Collections.unmodifiableMap(metaDataMap));
258 }
259 rootMap.put(METADATA_KEY_ACCESS, Collections.unmodifiableMap(metaDatasMap));
260
261 return Collections.unmodifiableMap(rootMap);
262 }
263
264 public Map<String, Object> getAssetMap(String itemKey) {
265 return getAssetMap(getAsset(itemKey));
266 }
267
268
269
270
271 public String getAssetLink(String assetKey) {
272 Asset asset = getAsset(assetKey);
273 if (asset != null) {
274 return asset.getLink();
275 }
276 return null;
277 }
278
279
280
281
282 public String getAssetLink(String itemKey, String renditionName) {
283 AssetRendition rendition = getRendition(itemKey, renditionName);
284 if (rendition != null) {
285 return rendition.getLink();
286 }
287 return null;
288 }
289
290
291
292
293 public String getAssetLink(Asset asset, String renditionName) {
294 return getAssetLink(asset, MediaType.parse(asset.getMimeType()), renditionName);
295 }
296
297
298
299
300 public String getAssetLink(Asset asset, MediaType mediaType, String renditionName) {
301 AssetRendition rendition = getRendition(asset, mediaType, renditionName);
302 if (rendition != null) {
303 return rendition.getLink();
304 }
305 return null;
306 }
307
308
309
310
311 public Map<String, Object> getAssetMapForAssetId(String assetKey) {
312 Asset asset = getAsset(assetKey);
313 if (asset != null) {
314 return getAssetMap(asset);
315 }
316 return null;
317 }
318
319
320
321
322
323
324
325
326
327
328 @Deprecated
329 public List<Asset> getAssetsFromFolderId(String folderKey) {
330 Folder folder = getFolder(folderKey);
331 if (folder != null) {
332 return Lists.newArrayList(onlyAssets(folder.getChildren()));
333 }
334 return new ArrayList<>();
335 }
336
337
338
339
340
341 @Deprecated
342 public Asset getAssetForPath(String assetPath) {
343 return getAssetForAbsolutePath(DAM_VERSION_1_PROVIDER_ID, assetPath);
344 }
345
346
347
348
349 @Deprecated
350 public Asset getAssetForId(String assetIdentifier) {
351 return getAsset(assetIdentifier);
352 }
353
354
355
356
357
358
359
360 @Deprecated
361 public Asset getAssetRendition(Asset asset, String renditionName) {
362 AssetRendition assetRendition = getRendition(asset, renditionName);
363 if (assetRendition != null) {
364 return getAssetRendition(assetRendition);
365 }
366 return asset;
367 }
368
369
370
371
372
373
374
375 @Deprecated
376 public Asset getAssetRenditionForAssetId(String itemKey, String renditionName) {
377 AssetRendition assetRendition = getRendition(itemKey, renditionName);
378 if (assetRendition != null) {
379 return getAssetRendition(assetRendition);
380 }
381 return getAsset(itemKey);
382 }
383
384
385
386
387 private Asset getAssetRendition(AssetRendition assetRendition) {
388 if (assetRendition != null) {
389 if (assetRendition instanceof Asset) {
390 return (Asset) assetRendition;
391 }
392 return assetRendition.getAsset();
393 }
394 return null;
395 }
396
397
398
399
400
401 @Deprecated
402 public String getAssetLinkForId(String assetKey) {
403 return getAssetLink(assetKey);
404 }
405
406
407
408
409
410 @Deprecated
411 public String getAssetLinkForId(String itemKey, String renditionName) {
412 return getAssetLink(itemKey, renditionName);
413 }
414
415
416
417
418
419
420 @Deprecated
421 public List<Asset> getAssetsForFilter(AssetQuery assetQuery) {
422 Iterator<Item> items = getItems(DAM_VERSION_1_PROVIDER_ID, assetQuery);
423 if (items != null) {
424 return Lists.newArrayList(onlyAssets(items));
425 }
426 return new ArrayList<>();
427 }
428
429 @SuppressWarnings("unchecked")
430
431 private static UnmodifiableIterator<Asset> onlyAssets(Iterator<? extends Item> unfiltered) {
432 return (UnmodifiableIterator<Asset>) Iterators.filter(unfiltered, (Predicate<Item>) Item::isAsset);
433 }
434
435
436
437
438
439
440 private Map<String, Object> convertBeanToMap(Object source, List<String> rejectedGetter) {
441 Map<String, Object> map = new HashMap<>();
442 try {
443 BeanInfo info = Introspector.getBeanInfo(source.getClass());
444 for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
445 Method reader = pd.getReadMethod();
446 if (reader != null && !rejectedGetter.contains(reader.getName()))
447 map.put(pd.getName(), reader.invoke(source));
448 }
449 } catch (Exception e) {
450 log.warn("Could not populate the map with the bean property", e);
451 }
452 return map;
453 }
454
455
456
457
458 private Item getItem(String itemKey, boolean assetItem) {
459 try {
460 validateItemKey(itemKey);
461 ItemKey key = ItemKey.from(itemKey);
462 Item item = this.providerRegistry.getProviderFor(key).getItem(key);
463
464 return determineItemToReturn(item, assetItem);
465 } catch (Exception e) {
466 if (MgnlContext.isWebContext()) {
467 AggregationState aggregationState = MgnlContext.getWebContext().getAggregationState();
468 log.warn("The following ItemKey '{}' generated exceptions when trying to retrieve the associated Item:[{}] at "
469 + "Node:[{}] Workspace:[{}]", itemKey, e.getMessage(), aggregationState.getCurrentContentNode(), aggregationState.getRepository());
470 } else {
471 log.warn("The following ItemKey '{}' generated exceptions when trying to retrieve the associated Item : {} ", itemKey, e.getMessage());
472 }
473 }
474 return null;
475 }
476
477
478
479
480
481 private Item determineItemToReturn(Item item, boolean assetItem) {
482 boolean isAsset = assetItem && item.isAsset();
483 boolean isFolder = !assetItem && item.isFolder();
484 boolean isJcrAsset = isAsset && (item instanceof JcrAsset && item.getAssetProvider() instanceof JcrAssetProvider);
485 boolean isJcrFolder = isFolder && (item instanceof JcrFolder && item.getAssetProvider() instanceof JcrAssetProvider);
486
487 if (isJcrAsset) {
488 return new JcrAsset((JcrAssetProvider) item.getAssetProvider(), new HTMLEscapingNodeWrapper(((JcrAsset) item).getNode(), true));
489 } else if (isJcrFolder) {
490 return new JcrFolder((JcrAssetProvider) item.getAssetProvider(), new HTMLEscapingNodeWrapper(((JcrFolder) item).getNode(), true));
491 } else if (isAsset || isFolder) {
492 return item;
493 }
494
495 log.warn("An '{}' was requested, but a '{}' was found", (assetItem ? "Asset" : "Folder"), (!assetItem ? "Asset" : "Folder"));
496 return null;
497 }
498
499
500
501
502
503
504 private void validateItemKey(String itemKey) {
505 if (StringUtils.isBlank(itemKey)) {
506 throw new IllegalArgumentException("ItemKey is null or blank.");
507 }
508 if (!ItemKey.isValid(itemKey)) {
509 throw new IllegalArgumentException("ItemKey is not valid.");
510 }
511 }
512
513
514
515
516
517 private Item getItem(String providerId, String itemPath, boolean assetItem) {
518 AssetProvider provider = getProviderForId(providerId);
519 if (provider != null) {
520
521 if (!(provider instanceof PathAwareAssetProvider)) {
522 throw new IllegalArgumentException("The provider '" + providerId + "' does not provide implementation for '" + PathAwareAssetProvider.class.getName() + "'. Retrieving an Item by path is not a supported operation ");
523 }
524 try {
525 Item item = ((PathAwareAssetProvider) provider).getItem(itemPath);
526 return determineItemToReturn(item, assetItem);
527 } catch (Exception e) {
528 log.warn("The following itemPath '{}' for the provider '{}' generated exceptions when trying to retrieve the associated Asset : {}", itemPath, providerId, e.getMessage());
529 }
530 }
531 return null;
532 }
533
534
535
536
537 private AssetProvider getProviderForId(String providerId) {
538 try {
539 return this.providerRegistry.getProviderById(providerId);
540 } catch (Exception e) {
541 log.warn("Exception occurred during the retrieval of the desired Asset Provider", e);
542 return null;
543 }
544 }
545
546 }