MediaHandlerConfig.java

  1. /*
  2.  * #%L
  3.  * wcm.io
  4.  * %%
  5.  * Copyright (C) 2014 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.media.spi;

  21. import java.util.Collections;
  22. import java.util.EnumSet;
  23. import java.util.List;
  24. import java.util.Set;

  25. import org.jetbrains.annotations.NotNull;
  26. import org.jetbrains.annotations.Nullable;
  27. import org.osgi.annotation.versioning.ConsumerType;

  28. import com.day.cq.wcm.api.Page;

  29. import io.wcm.handler.media.MediaFileType;
  30. import io.wcm.handler.media.MediaNameConstants;
  31. import io.wcm.handler.media.markup.DummyImageMediaMarkupBuilder;
  32. import io.wcm.handler.media.markup.MediaMarkupBuilderUtil;
  33. import io.wcm.handler.media.markup.SimpleImageMediaMarkupBuilder;
  34. import io.wcm.handler.mediasource.dam.AemRenditionType;
  35. import io.wcm.handler.mediasource.dam.DamMediaSource;
  36. import io.wcm.sling.commons.caservice.ContextAwareService;

  37. /**
  38.  * {@link MediaHandlerConfig} OSGi services provide application-specific configuration for media handling.
  39.  * Applications can set service properties or bundle headers as defined in {@link ContextAwareService} to apply this
  40.  * configuration only for resources that match the relevant resource paths.
  41.  */
  42. @ConsumerType
  43. public abstract class MediaHandlerConfig implements ContextAwareService {

  44.   /**
  45.    * Default image quality for images with lossy compressions (e.g. JPEG).
  46.    */
  47.   public static final double DEFAULT_IMAGE_QUALITY = 0.85d;

  48.   /**
  49.    * Default value for JPEG quality.
  50.    * @deprecated Use {@link #DEFAULT_IMAGE_QUALITY} instead.
  51.    */
  52.   @Deprecated(since = "2.0.0")
  53.   public static final double DEFAULT_JPEG_QUALITY = DEFAULT_IMAGE_QUALITY;

  54.   private static final List<Class<? extends MediaSource>> DEFAULT_MEDIA_SOURCES = List.of(
  55.       DamMediaSource.class);

  56.   private static final List<Class<? extends MediaMarkupBuilder>> DEFAULT_MEDIA_MARKUP_BUILDERS = List.of(
  57.       SimpleImageMediaMarkupBuilder.class,
  58.       DummyImageMediaMarkupBuilder.class);

  59.   /**
  60.    * @return Supported media sources
  61.    */
  62.   public @NotNull List<Class<? extends MediaSource>> getSources() {
  63.     return DEFAULT_MEDIA_SOURCES;
  64.   }

  65.   /**
  66.    * @return Available media markup builders
  67.    */
  68.   public @NotNull List<Class<? extends MediaMarkupBuilder>> getMarkupBuilders() {
  69.     return DEFAULT_MEDIA_MARKUP_BUILDERS;
  70.   }

  71.   /**
  72.    * @return List of media metadata pre processors (optional). The processors are applied in list order.
  73.    */
  74.   public @NotNull List<Class<? extends MediaProcessor>> getPreProcessors() {
  75.     // no processors
  76.     return Collections.emptyList();
  77.   }

  78.   /**
  79.    * @return List of media metadata post processors (optional). The processors are applied in list order.
  80.    */
  81.   public @NotNull List<Class<? extends MediaProcessor>> getPostProcessors() {
  82.     // no processors
  83.     return Collections.emptyList();
  84.   }

  85.   /**
  86.    * Get the default quality for images.
  87.    * The meaning of the quality parameter for the different image formats is described in
  88.    * {@link com.day.image.Layer#write(String, double, java.io.OutputStream)}.
  89.    * @param contentType MIME-type of the output format
  90.    * @return Quality factor
  91.    */
  92.   public double getDefaultImageQuality(@Nullable String contentType) {
  93.     MediaFileType mediaFileType = MediaFileType.getByContentType(contentType);
  94.     if (mediaFileType != null && mediaFileType.isImageQualityPercentage()) {
  95.       return getDefaultImageQualityPercentage();
  96.     }
  97.     else if (mediaFileType == MediaFileType.GIF) {
  98.       return 256d; // 256 colors
  99.     }
  100.     // return quality "1" for all other mime types
  101.     return 1d;
  102.   }

  103.   /**
  104.    * Get the default quality for images.
  105.    * This parameter only applies to images with lossy compression (e.g. JPEG).
  106.    * @return Quality percentage (0..1)
  107.    */
  108.   public double getDefaultImageQualityPercentage() {
  109.     return DEFAULT_IMAGE_QUALITY;
  110.   }

  111.   /**
  112.    * With this switch it's possible to switch all used property and node names from (legacy) wcm.io
  113.    * Handler standard to Adobe Standard (as used e.g. in Adobe Core WCM Components) - e.g.
  114.    * using "fileReference" instead of property name "mediaRef" for the asset reference.
  115.    *
  116.    * <p>
  117.    * The benefit of the wcm.io Handler standard was that it supported storage multiple asset references
  118.    * in one single node - but this it not well supported by the Touch UI anyway, so it's not of much
  119.    * use nowadays.
  120.    * </p>
  121.    *
  122.    * <p>
  123.    * For new projects it is recommended to always use the Adobe standard names. But for backward compatibility
  124.    * the default values is false.
  125.    * </p>
  126.    * @return If true, Adobe standard property and node names are used.
  127.    */
  128.   public boolean useAdobeStandardNames() {
  129.     return false;
  130.   }

  131.   /**
  132.    * @return Default property name for reference to media library item
  133.    */
  134.   public @NotNull String getMediaRefProperty() {
  135.     if (useAdobeStandardNames()) {
  136.       return MediaNameConstants.PN_MEDIA_REF_STANDARD;
  137.     }
  138.     else {
  139.       return MediaNameConstants.PN_MEDIA_REF;
  140.     }
  141.   }

  142.   /**
  143.    * @return Default property name for cropping parameters
  144.    */
  145.   public @NotNull String getMediaCropProperty() {
  146.     if (useAdobeStandardNames()) {
  147.       return MediaNameConstants.PN_MEDIA_CROP_STANDARD;
  148.     }
  149.     else {
  150.       return MediaNameConstants.PN_MEDIA_CROP;
  151.     }
  152.   }

  153.   /**
  154.    * @return Default property name for rotate parameter
  155.    */
  156.   public @NotNull String getMediaRotationProperty() {
  157.     if (useAdobeStandardNames()) {
  158.       return MediaNameConstants.PN_MEDIA_ROTATION_STANDARD;
  159.     }
  160.     else {
  161.       return MediaNameConstants.PN_MEDIA_ROTATION;
  162.     }
  163.   }

  164.   /**
  165.    * @return Default property name for map parameter
  166.    */
  167.   public @NotNull String getMediaMapProperty() {
  168.     if (useAdobeStandardNames()) {
  169.       return MediaNameConstants.PN_MEDIA_MAP_STANDARD;
  170.     }
  171.     else {
  172.       return MediaNameConstants.PN_MEDIA_MAP;
  173.     }
  174.   }

  175.   /**
  176.    * @return Default property name for media alt. text
  177.    */
  178.   public @NotNull String getMediaAltTextProperty() {
  179.     if (useAdobeStandardNames()) {
  180.       return MediaNameConstants.PN_MEDIA_ALTTEXT_STANDARD;
  181.     }
  182.     else {
  183.       return MediaNameConstants.PN_MEDIA_ALTTEXT;
  184.     }
  185.   }

  186.   /**
  187.    * @return Default property name for forcing reading alt. text from DAM asset description
  188.    */
  189.   public @NotNull String getMediaForceAltTextFromAssetProperty() {
  190.     if (useAdobeStandardNames()) {
  191.       return MediaNameConstants.PN_MEDIA_FORCE_ALTTEXT_FROM_ASSET_STANDARD;
  192.     }
  193.     else {
  194.       return MediaNameConstants.PN_MEDIA_FORCE_ALTTEXT_FROM_ASSET;
  195.     }
  196.   }

  197.   /**
  198.    * @return Default property name for marking image as "decorative" - requiring no alt. text
  199.    */
  200.   public @NotNull String getMediaIsDecorativeProperty() {
  201.     if (useAdobeStandardNames()) {
  202.       return MediaNameConstants.PN_MEDIA_IS_DECORATIVE_STANDARD;
  203.     }
  204.     else {
  205.       return MediaNameConstants.PN_MEDIA_IS_DECORATIVE;
  206.     }
  207.   }

  208.   /**
  209.    * @return Default node name for inline media item stored in node within the content page
  210.    */
  211.   public @NotNull String getMediaInlineNodeName() {
  212.     if (useAdobeStandardNames()) {
  213.       return MediaNameConstants.NN_MEDIA_INLINE_STANDARD;
  214.     }
  215.     else {
  216.       return MediaNameConstants.NN_MEDIA_INLINE;
  217.     }
  218.   }

  219.   /**
  220.    * @return If set to true, web renditions generated by AEM (with <code>cq5dam.web.</code> prefix) are
  221.    *         taken into account by default when trying to resolve the media request.
  222.    * @deprecated Use {@link #getIncludeAssetAemRenditionsByDefault()} instead.
  223.    */
  224.   @Deprecated(since = "2.0.0")
  225.   public boolean includeAssetWebRenditionsByDefault() {
  226.     return false;
  227.   }

  228.   /**
  229.    * Set of renditions auto-generated by AEM (with <code>cq5dam.</code> prefix) which are taken into account
  230.    * by default when trying to resolve the media request.
  231.    * @return Set or rendition types
  232.    */
  233.   @SuppressWarnings("java:S1874") // ignore use of deprecated method
  234.   public @NotNull Set<AemRenditionType> getIncludeAssetAemRenditionsByDefault() {
  235.     if (includeAssetWebRenditionsByDefault()) {
  236.       return EnumSet.of(AemRenditionType.WEB_RENDITION, AemRenditionType.VIDEO_RENDITION);
  237.     }
  238.     else {
  239.       return EnumSet.of(AemRenditionType.VIDEO_RENDITION);
  240.     }
  241.   }

  242.   /**
  243.    * Enforce to generate only virtual renditions.
  244.    *
  245.    * <p>
  246.    * By default, virtual renditions (rendered on-the-fly via <code>ImageFileServet</code>) are only
  247.    * generated if there is a need to re-scale or crop or transform an image. Otherwise direct references
  248.    * to renditions or original stored in DAM are returned when there is an direct match with the requested ratio and
  249.    * resolution.
  250.    * </p>
  251.    *
  252.    * <p>
  253.    * When this flag is set to <code>true</code>, even if there is a direct match a virtual rendition is returned.
  254.    * This ensures that the default quality setting e.g. for JPEG images is always respected, regardless
  255.    * in which quality the original images was uploaded.
  256.    * </p>
  257.    * @return Enforce always returning virtual renditions for images.
  258.    */
  259.   public boolean enforceVirtualRenditions() {
  260.     return false;
  261.   }

  262.   /**
  263.    * @return Allowed editor types for image IPE (in-place editor).
  264.    *         By default, only the OOTB "image" editor type is supported.
  265.    */
  266.   public @NotNull Set<String> allowedIpeEditorTypes() {
  267.     return MediaMarkupBuilderUtil.DEFAULT_ALLOWED_IPE_EDITOR_TYPES;
  268.   }

  269.   /**
  270.    * Get root path for picking assets using path field widgets.
  271.    * @param page Context page
  272.    * @return DAM root path
  273.    */
  274.   public @NotNull String getDamRootPath(@NotNull Page page) {
  275.     return "/content/dam";
  276.   }

  277. }