View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2024 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.ngdm.impl;
21  
22  import org.apache.commons.lang3.StringUtils;
23  import org.jetbrains.annotations.NotNull;
24  import org.jetbrains.annotations.Nullable;
25  import org.osgi.service.component.annotations.Activate;
26  import org.osgi.service.component.annotations.Component;
27  import org.osgi.service.component.annotations.ConfigurationPolicy;
28  import org.osgi.service.component.annotations.Reference;
29  import org.osgi.service.component.annotations.ReferenceCardinality;
30  import org.osgi.service.component.annotations.ReferencePolicy;
31  import org.osgi.service.component.annotations.ReferencePolicyOption;
32  import org.osgi.service.metatype.annotations.AttributeDefinition;
33  import org.osgi.service.metatype.annotations.Designate;
34  import org.osgi.service.metatype.annotations.ObjectClassDefinition;
35  import org.osgi.service.metatype.annotations.Option;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  import com.adobe.cq.ui.wcm.commons.config.NextGenDynamicMediaConfig;
40  
41  
42  /**
43   * Wraps access to NextGenDynamicMediaConfig - which is deployed but not accessible on AEM 6.5.
44   */
45  @Component(service = NextGenDynamicMediaConfigService.class, immediate = true, configurationPolicy = ConfigurationPolicy.REQUIRE)
46  @Designate(ocd = NextGenDynamicMediaConfigServiceImpl.Config.class)
47  public class NextGenDynamicMediaConfigServiceImpl implements NextGenDynamicMediaConfigService {
48  
49    @ObjectClassDefinition(
50        name = "wcm.io Media Handler Dynamic Media with OpenAPI Support",
51        description = "Support for Dynamic Media with OpenAPI.")
52    @interface Config {
53  
54      @AttributeDefinition(
55          name = "Remote Assets",
56          description = "Enable Dynamic Media with OpenAPI for remote assets.")
57      boolean enabledRemoteAssets() default false;
58  
59      @AttributeDefinition(
60          name = "Local Assets",
61          description = "Enable Next Dynamic Media with OpenAPI for local assets in this AEMaaCS instance.")
62      boolean enabledLocalAssets() default false;
63  
64      @AttributeDefinition(
65          name = "Repository ID for Local Assets",
66          description = "Dynamic Media with OpenAPI Delivery host name for local assets. Mandatory if local assets is enabled.")
67      String localAssetsRepositoryId();
68  
69      @AttributeDefinition(
70          name = "Image Delivery Base Path",
71          description = "Base path with placeholders to deliver image renditions. "
72              + "Placeholders: " + PLACEHOLDER_ASSET_ID + ", " + PLACEHOLDER_SEO_NAME + ", " + PLACEHOLDER_FORMAT + ". "
73              + "If not set, the default value from the NextGenDynamicMediaConfig service will be used.")
74      String imageDeliveryBasePath() default ADOBE_ASSETS_PREFIX + PLACEHOLDER_ASSET_ID + "/as/"
75          + PLACEHOLDER_SEO_NAME + "." + PLACEHOLDER_FORMAT;
76  
77      @AttributeDefinition(
78          name = "Video Delivery Path",
79          description = "Base path with placeholders to deliver adaptive video manifests. "
80              + "Placeholders: " + PLACEHOLDER_ASSET_ID + ", " + PLACEHOLDER_FORMAT + ". "
81              + "If not set, the default value from the NextGenDynamicMediaConfig service will be used.")
82      String videoDeliveryPath() default ADOBE_ASSETS_PREFIX + PLACEHOLDER_ASSET_ID + "/manifest." + PLACEHOLDER_FORMAT;
83  
84      @AttributeDefinition(
85          name = "Video Player Path",
86          description = "Base path of the hosted video player experience. "
87              + "Placeholder: " + PLACEHOLDER_ASSET_ID + ". "
88              + "If not set, the default " + DEFAULT_VIDEO_PLAYER_PATH + " will be used.")
89      String videoPlayerPath() default DEFAULT_VIDEO_PLAYER_PATH;
90  
91      @AttributeDefinition(
92          name = "Asset Original Binary Delivery Path",
93          description = "Base path with placeholders to deliver asset original binaries. "
94              + "Placeholders: " + PLACEHOLDER_ASSET_ID + ", " + PLACEHOLDER_SEO_NAME + ". "
95              + "If not set, the default value from the NextGenDynamicMediaConfig service will be used.")
96      String assetOriginalBinaryDeliveryPath() default ADOBE_ASSETS_PREFIX + PLACEHOLDER_ASSET_ID + "/original/as/"
97          + PLACEHOLDER_SEO_NAME;
98  
99      @AttributeDefinition(
100         name = "Asset Metadata Path",
101         description = "Base path to get asset metadata. "
102             + "Placeholder: " + PLACEHOLDER_ASSET_ID + ". "
103             + "If not set, the default value from the NextGenDynamicMediaConfig service will be used.")
104     String assetMetadataPath() default ADOBE_ASSETS_PREFIX + PLACEHOLDER_ASSET_ID + "/metadata";
105 
106     @AttributeDefinition(
107         name = "Default image width/height",
108         description = "Default width/height (longest edge) when requesting image renditions without explicit dimension.")
109     long imageWidthHeightDefault() default 2048;
110 
111     @AttributeDefinition(
112         name = "Default video manifest format",
113         description = "Default adaptive streaming manifest format used when no per-request override is given.",
114         options = {
115             @Option(label = "HLS (m3u8)", value = "m3u8"),
116             @Option(label = "DASH (mpd)", value = "mpd")
117         })
118     String defaultVideoManifestFormat() default DEFAULT_VIDEO_MANIFEST_FORMAT;
119   }
120 
121   private static final String ADOBE_ASSETS_PREFIX = "/adobe/assets/";
122   private static final String DEFAULT_VIDEO_PLAYER_PATH = ADOBE_ASSETS_PREFIX + PLACEHOLDER_ASSET_ID + "/play";
123   private static final String DEFAULT_VIDEO_MANIFEST_FORMAT = "m3u8";
124   private static final Logger log = LoggerFactory.getLogger(NextGenDynamicMediaConfigServiceImpl.class);
125 
126   private boolean enabledRemoteAssets;
127   private boolean enabledLocalAssets;
128   private String localAssetsRepositoryId;
129   private String imageDeliveryBasePath;
130   private String videoDeliveryPath;
131   private String videoPlayerPath;
132   private String assetOriginalBinaryDeliveryPath;
133   private String assetMetadataPath;
134   private long imageWidthHeightDefault;
135   private String defaultVideoManifestFormat = DEFAULT_VIDEO_MANIFEST_FORMAT;
136 
137   @Reference(policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL)
138   private NextGenDynamicMediaConfig nextGenDynamicMediaConfig;
139 
140   @Activate
141   private void activate(Config config) {
142     enabledRemoteAssets = config.enabledRemoteAssets();
143     if (enabledRemoteAssets) {
144       if (nextGenDynamicMediaConfig == null) {
145         log.debug("NextGenDynamicMediaConfig service is not available, disable remote assets.");
146         enabledRemoteAssets = false;
147       }
148       else {
149         log.debug("NextGenDynamicMediaConfig: enabled={}, repositoryId={}, apiKey={}, env={}, imsClient={}",
150             nextGenDynamicMediaConfig.enabled(), nextGenDynamicMediaConfig.getRepositoryId(),
151             nextGenDynamicMediaConfig.getApiKey(), nextGenDynamicMediaConfig.getEnv(), nextGenDynamicMediaConfig.getImsClient());
152       }
153     }
154 
155     imageDeliveryBasePath = StringUtils.defaultIfBlank(config.imageDeliveryBasePath(),
156         nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getImageDeliveryBasePath() : null);
157     videoDeliveryPath = StringUtils.defaultIfBlank(config.videoDeliveryPath(),
158         nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getVideoDeliveryPath() : null);
159     videoPlayerPath = StringUtils.defaultIfBlank(config.videoPlayerPath(), DEFAULT_VIDEO_PLAYER_PATH);
160     assetOriginalBinaryDeliveryPath = StringUtils.defaultIfBlank(config.assetOriginalBinaryDeliveryPath(),
161         nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getAssetOriginalBinaryDeliveryPath() : null);
162     assetMetadataPath = StringUtils.defaultIfBlank(config.assetMetadataPath(),
163         nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getAssetMetadataPath() : null);
164 
165     enabledLocalAssets = config.enabledLocalAssets();
166     localAssetsRepositoryId = config.localAssetsRepositoryId();
167     if (enabledLocalAssets && StringUtils.isBlank(localAssetsRepositoryId)) {
168       log.debug("localAssetsRepositoryId is not configured, disable local assets.");
169       enabledLocalAssets = false;
170     }
171 
172     imageWidthHeightDefault = config.imageWidthHeightDefault();
173 
174     defaultVideoManifestFormat = StringUtils.defaultIfBlank(config.defaultVideoManifestFormat(), DEFAULT_VIDEO_MANIFEST_FORMAT);
175   }
176 
177   @Override
178   public boolean isEnabledRemoteAssets() {
179     return enabledRemoteAssets && nextGenDynamicMediaConfig != null && nextGenDynamicMediaConfig.enabled();
180   }
181 
182   @Override
183   public boolean isEnabledLocalAssets() {
184     return enabledLocalAssets;
185   }
186 
187   @Override
188   public @Nullable String getAssetSelectorsJsUrl() {
189     return nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getAssetSelectorsJsUrl() : null;
190   }
191 
192   @Override
193   public @Nullable String getImageDeliveryBasePath() {
194     return imageDeliveryBasePath;
195   }
196 
197   @Override
198   public @Nullable String getVideoDeliveryPath() {
199     return videoDeliveryPath;
200   }
201 
202   @Override
203   public @Nullable String getVideoPlayerPath() {
204     return videoPlayerPath;
205   }
206 
207   @Override
208   public @NotNull String getDefaultVideoManifestFormat() {
209     return defaultVideoManifestFormat;
210   }
211 
212   @Override
213   public @Nullable String getAssetOriginalBinaryDeliveryPath() {
214     return assetOriginalBinaryDeliveryPath;
215   }
216 
217   @Override
218   public @Nullable String getAssetMetadataPath() {
219     return assetMetadataPath;
220   }
221 
222   @Override
223   public @Nullable String getRemoteAssetsRepositoryId() {
224     return nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getRepositoryId() : null;
225   }
226 
227   @Override
228   public @Nullable String getLocalAssetsRepositoryId() {
229     return localAssetsRepositoryId;
230   }
231 
232   @Override
233   public @Nullable String getApiKey() {
234     return nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getApiKey() : null;
235   }
236 
237   @Override
238   public @Nullable String getEnv() {
239     return nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getEnv() : null;
240   }
241 
242   @Override
243   public @Nullable String getImsClient() {
244     return nextGenDynamicMediaConfig != null ? nextGenDynamicMediaConfig.getImsClient() : null;
245   }
246 
247   @Override
248   public long getImageWidthHeightDefault() {
249     return imageWidthHeightDefault;
250   }
251 
252 }