All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.day.cq.dam.core.process.CreateWebEnabledImageProcess Maven / Gradle / Ivy

There is a newer version: 6.5.21
Show newest version
/*
 * Copyright 1997-2008 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */
package com.day.cq.dam.core.process;

import static com.day.cq.commons.jcr.JcrConstants.JCR_CONTENT;
import static com.day.cq.commons.jcr.JcrConstants.JCR_LASTMODIFIED;
import static com.day.cq.commons.jcr.JcrConstants.JCR_LAST_MODIFIED_BY;
import static com.day.cq.dam.api.DamConstants.PREFIX_ASSET_THUMBNAIL;
import static com.day.cq.dam.api.DamConstants.PREFIX_ASSET_WEB;
import static com.day.cq.dam.core.process.CreateThumbnailProcess.isThumbnailStale;

import java.util.Calendar;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

import com.day.cq.dam.commons.util.DamUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.DamConstants;
import com.day.cq.dam.api.Rendition;
import com.day.cq.dam.api.renditions.RenditionMaker;
import com.day.cq.dam.api.renditions.RenditionTemplate;
import com.day.cq.dam.commons.process.AbstractAssetWorkflowProcess;
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.metadata.MetaDataMap;

/**
 * The CreateWebEnabledImageProcess is called in a Workflow {@link com.day.cq.workflow.exec.WorkflowProcess Process} step. This
 * Process creates, if possible, a web enabled representation from the {@link com.day.cq.dam.api.Asset Asset}.
* The Format of the webenabled image, can be set by arguments to the * {@link com.day.cq.workflow.exec.WorkflowProcess#execute(WorkItem, WorkflowSession, MetaDataMap) Process}
* Process is memory aware. If the required memory is not available, image creatation is deferred or cancelled if the memory requirement * can't be sattisfied within a fixed amount of trails. *

* Example with the following workflow step arguments: * *

 *    dimension:500:100,
 *    quality:60
 * 
*

* The Process create a PNG Image of the size of 500x100 Pixels. The Quality will be set to 60%. *

* Arguments: *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
PrefixDescriptionDefaultMultipleExample
dimension:Amount in pixels given in the following format widht:hight.
* Image will be risized to have at most this dimension, keeping aspect ratio
1000:1000dimension:400:300
quality:Quality as percentage from optimal. This depends on the mimetype of the resulting image. For Gifs this reduces the amount of colors, * for Jpgs this sets the compression rate, etc.60quality:90
skip:Set the mimetypes of Assets that should not be processedmulitpleskip:application/pdf, skip:image/tiff
mimetype:Set the mimetype of the Image to createimage/pngmimetype:image/jpg
keepFormatList:Commas epareted list of mimetypes that can be taken webinabled imageimage/pjpeg, image/jpeg, image/jpg, image/gif, image/png, image/x-pngkeepFormatList:image/gif,image/png,image/x-png
* * @see AbstractAssetWorkflowProcess */ @Component(metatype = false) @Service @Property(name = "process.label", value = "Create Web Enabled Image") public class CreateWebEnabledImageProcess extends AbstractAssetWorkflowProcess { private static final Logger log = LoggerFactory.getLogger(CreateWebEnabledImageProcess.class); @Reference protected RenditionMaker renditionMaker; /** * Enum mixing old and new metadata argument names. */ public enum Arguments { PROCESS_ARGS("PROCESS_ARGS"), // legacy metadata property holding string with all arguments DIMENSION("dimension"), // legacy only WIDTH("width"), HEIGHT("height"), QUALITY("quality"), MIME_TYPE("mimetype"), KEEP_FORMAT_LIST("keepFormatList"), SKIP("skip"); public final String legacyName; Arguments(String legacyName) { this.legacyName = legacyName; } } /** The parsed configuration for this wf process */ public static class Config { public int width; public int height; public int quality; public String mimeType; public String[] mimeTypesToKeep; public String[] skipMimeTypes; } public void createWebEnabledImage(WorkItem workItem, Config config, Asset asset, RenditionMaker renditionMaker) throws RepositoryException { if (handleAsset(asset, config)) { asset.setBatchMode(true); // skip rendition if it exists if(isWebThumbnailStale(asset, config.width, config.height)) { RenditionTemplate template = renditionMaker.createWebRenditionTemplate(asset, config.width, config.height, config.quality, config.mimeType, config.mimeTypesToKeep); renditionMaker.generateRenditions(asset, template); } } // lastModifiedBy is admin user by renditionMaker.generateRenditions // set lastModifiedBy appropriately final Node assetNode = asset.adaptTo(Node.class); final Node content = assetNode.getNode(JCR_CONTENT); // get user id String resolvedUser = workItem.getWorkflowData().getMetaDataMap().get("userId", String.class); Rendition rendition = asset.getRendition(DamConstants.ORIGINAL_FILE); if (rendition != null) { String lastModified = (String) rendition.getProperties().get(JCR_LAST_MODIFIED_BY); // It can be blank in cases where there was no last modified for // the original if (StringUtils.isNotBlank(lastModified)) { resolvedUser = lastModified; } } content.setProperty(JCR_LAST_MODIFIED_BY, resolvedUser); content.setProperty(JCR_LASTMODIFIED, Calendar.getInstance()); } private boolean isWebThumbnailStale(Asset asset, int width, int height) { // check both png & jpeg mime types String pngName = PREFIX_ASSET_WEB + "." + String.valueOf(width) + "." + String.valueOf(height) + ".png"; String jpegName = PREFIX_ASSET_WEB + "." + String.valueOf(width) + "." + String.valueOf(height) + ".jpeg"; // check both for existing fresh thumbnails return (isThumbnailStale(asset, pngName) && isThumbnailStale(asset, jpegName)) ; } public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaData) throws WorkflowException { final Asset asset = getAssetFromPayload(workItem, workflowSession.getSession()); if (asset == null) { String wfPayload = workItem.getWorkflowData().getPayload().toString(); String message = "execute: cannot create web enabled image, asset [{" + wfPayload + "}] in payload doesn't exist for workflow [{" + workItem.getId() + "}]."; throw new WorkflowException(message); } final Config config = parseConfig(metaData); try { createWebEnabledImage(workItem, config, asset, renditionMaker); } catch (RepositoryException re) { throw new WorkflowException(re); } } public Config parseConfig(MetaDataMap metaData) { // check for legacy config first String processArgs = metaData.get(Arguments.PROCESS_ARGS.name(), String.class); if (StringUtils.isNotEmpty(processArgs)) { return parseLegacyConfig(processArgs); } Config cfg = new Config(); // only long values can be automatically converted from strings (jcr LONG), not integer cfg.width = metaData.get(Arguments.WIDTH.name(), 1000L).intValue(); cfg.height = metaData.get(Arguments.HEIGHT.name(), 1000L).intValue(); cfg.mimeType = metaData.get(Arguments.MIME_TYPE.name(), "image/png"); cfg.quality = metaData.get(Arguments.QUALITY.name(), cfg.mimeType.equals("image/gif") ? 256L : 60L).intValue(); cfg.mimeTypesToKeep = metaData.get(Arguments.KEEP_FORMAT_LIST.name(), new String[] { "image/pjpeg", "image/jpeg", "image/jpg", "image/gif", "image/png", "image/x-png" }); cfg.skipMimeTypes = metaData.get(Arguments.SKIP.name(), new String[] {}); return cfg; } private Config parseLegacyConfig(String processArgs) { Config cfg = new Config(); String[] args = processArgs.split(","); // dimension final String dimension = getFirstValueFromArgs(args, Arguments.DIMENSION.legacyName, null); if (dimension == null) { cfg.width = 1000; cfg.height = 1000; } else { String dim[] = dimension.split(":"); cfg.width = Integer.valueOf(dim[0]); cfg.height = Integer.valueOf(dim[1]); } // default mime type cfg.mimeType = getFirstValueFromArgs(args, Arguments.MIME_TYPE.legacyName, "image/png"); // keep the original format? String keepFormat = getFirstValueFromArgs(args, Arguments.KEEP_FORMAT_LIST.legacyName, "image/pjpeg,image/jpeg,image/jpg,image/gif,image/png,image/x-png"); cfg.mimeTypesToKeep = keepFormat.split(","); // image quality: from 0 to 100 % in case of jpeg or number of colors 0 to 256 in case of gif String qualityStr = getFirstValueFromArgs(args, Arguments.QUALITY.legacyName, cfg.mimeType.equals("image/gif") ? "256" : "60"); cfg.quality = Integer.valueOf(qualityStr); // mime types to ignore for this process List values = getValuesFromArgs(Arguments.SKIP.legacyName, args); cfg.skipMimeTypes = values.toArray(new String[values.size()]); return cfg; } private String getFirstValueFromArgs(String[] arguments, String key, String defaultValue) { List values = getValuesFromArgs(key, arguments); if (values.size() > 0) { return values.get(0); } else { return defaultValue; } } protected boolean handleAsset(Asset asset, Config config) { if (asset == null || config.skipMimeTypes == null) { return true; } final String mimeType = asset.getMimeType(); if (mimeType == null) { // absence of mimetype is handled at later stage in process return true; } for (String val : config.skipMimeTypes) { if (mimeType.matches(val)) { log.debug(this.getClass().getName() + " skipped for MIME type: " + mimeType); return false; } } return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy