View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2021 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.handler.mediasource.inline;
21  
22  import static io.wcm.handler.media.MediaNameConstants.URI_TEMPLATE_PLACEHOLDER_HEIGHT;
23  import static io.wcm.handler.media.MediaNameConstants.URI_TEMPLATE_PLACEHOLDER_WIDTH;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.sling.api.adapter.Adaptable;
27  import org.apache.sling.api.resource.Resource;
28  import org.jetbrains.annotations.NotNull;
29  import org.jetbrains.annotations.Nullable;
30  
31  import io.wcm.handler.media.CropDimension;
32  import io.wcm.handler.media.Dimension;
33  import io.wcm.handler.media.MediaArgs;
34  import io.wcm.handler.media.UriTemplate;
35  import io.wcm.handler.media.UriTemplateType;
36  import io.wcm.handler.media.impl.ImageFileServlet;
37  import io.wcm.handler.media.impl.ImageFileServletSelector;
38  import io.wcm.handler.media.impl.JcrBinary;
39  import io.wcm.handler.media.impl.MediaFileServletConstants;
40  import io.wcm.handler.url.UrlHandler;
41  import io.wcm.sling.commons.adapter.AdaptTo;
42  
43  final class InlineUriTemplate implements UriTemplate {
44  
45    private final String uriTemplate;
46    private final UriTemplateType type;
47    private final Dimension dimension;
48  
49    @SuppressWarnings("java:S107") // allow more than 7 params
50    InlineUriTemplate(@NotNull UriTemplateType type, @NotNull Dimension dimension,
51        @NotNull Resource resource, @NotNull String fileName,
52        @Nullable CropDimension cropDimension, @Nullable Integer rotation,
53        @NotNull MediaArgs mediaArgs, @NotNull Adaptable adaptable) {
54      this.uriTemplate = buildUriTemplate(type, resource, fileName, cropDimension, rotation, mediaArgs, adaptable);
55      this.type = type;
56      this.dimension = dimension;
57    }
58  
59    @SuppressWarnings("java:S1075") // not a file path
60    private static String buildUriTemplate(@NotNull UriTemplateType type, @NotNull Resource resource,
61        @NotNull String fileName, @Nullable CropDimension cropDimension, @Nullable Integer rotation,
62        @NotNull MediaArgs mediaArgs, @NotNull Adaptable adaptable) {
63      String resourcePath = resource.getPath();
64  
65      // if parent resource is a nt:file resource, use this one as path for scaled image
66      Resource parentResource = resource.getParent();
67      if (parentResource != null && JcrBinary.isNtFile(parentResource)) {
68        resourcePath = parentResource.getPath();
69      }
70  
71      // URL to render scaled image via {@link InlineRenditionServlet}
72      final long DUMMY_WIDTH = 999991;
73      final long DUMMY_HEIGHT = 999992;
74      String path = resourcePath
75          + "." + ImageFileServletSelector.build(DUMMY_WIDTH, DUMMY_HEIGHT, cropDimension, rotation,
76              mediaArgs.getImageQualityPercentage(), false)
77          + "." + MediaFileServletConstants.EXTENSION
78          // replace extension based on the format supported by ImageFileServlet for rendering for this rendition
79          + "/" + ImageFileServlet.getImageFileName(fileName, mediaArgs.getEnforceOutputFileExtension());
80  
81      // build externalized URL
82      UrlHandler urlHandler = AdaptTo.notNull(adaptable, UrlHandler.class);
83      String url = urlHandler.get(path).urlMode(mediaArgs.getUrlMode()).buildExternalResourceUrl(resource);
84  
85      switch (type) {
86        case CROP_CENTER:
87          url = StringUtils.replace(url, Long.toString(DUMMY_WIDTH), URI_TEMPLATE_PLACEHOLDER_WIDTH);
88          url = StringUtils.replace(url, Long.toString(DUMMY_HEIGHT), URI_TEMPLATE_PLACEHOLDER_HEIGHT);
89          break;
90        case SCALE_WIDTH:
91          url = StringUtils.replace(url, Long.toString(DUMMY_WIDTH), URI_TEMPLATE_PLACEHOLDER_WIDTH);
92          url = StringUtils.replace(url, Long.toString(DUMMY_HEIGHT), "0");
93          break;
94        case SCALE_HEIGHT:
95          url = StringUtils.replace(url, Long.toString(DUMMY_WIDTH), "0");
96          url = StringUtils.replace(url, Long.toString(DUMMY_HEIGHT), URI_TEMPLATE_PLACEHOLDER_HEIGHT);
97          break;
98        default:
99          throw new IllegalArgumentException("Unsupported type: " + type);
100     }
101     return url;
102   }
103 
104   @Override
105   public @NotNull UriTemplateType getType() {
106     return type;
107   }
108 
109   @Override
110   public @NotNull String getUriTemplate() {
111     return uriTemplate;
112   }
113 
114   @Override
115   public long getMaxWidth() {
116     return dimension.getWidth();
117   }
118 
119   @Override
120   public long getMaxHeight() {
121     return dimension.getHeight();
122   }
123 
124   @Override
125   public String toString() {
126     return uriTemplate;
127   }
128 
129 }