
com.day.cq.dam.drive.util.DriveUtil Maven / Gradle / Ivy
/***************************************************************************/
/* */
/* ADOBE CONFIDENTIAL */
/* _ _ _ _ _ _ _ _ _ _ */
/* */
/* Copyright 2014, Adobe Systems Incorporated */
/* All Rights Reserved. */
/* */
/* NOTICE: All information contained herein is, and remains the property */
/* of Adobe Systems Incorporated and its suppliers, if any. The */
/* intellectual and technical concepts contained herein are proprietary */
/* to Adobe Systems Incorporated and its suppliers and may be covered by */
/* U.S. and Foreign Patents, patents in process, and are protected by */
/* trade secret or copyright law. Dissemination of this information or */
/* reproduction of this material is strictly forbidden unless prior */
/* written permission is obtained from Adobe Systems Incorporated. */
/* */
/***************************************************************************/
package com.day.cq.dam.drive.util;
import static com.day.cq.commons.jcr.JcrConstants.JCR_CONTENT;
import static com.day.cq.dam.api.DamConstants.METADATA_FOLDER;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceWrapper;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.xmp.XMPException;
import com.adobe.xmp.XMPMeta;
import com.adobe.xmp.XMPMetaFactory;
import com.adobe.xmp.options.SerializeOptions;
import com.day.cq.commons.LabeledResource;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.AssetManager;
import com.day.cq.dam.api.DamConstants;
import com.day.cq.dam.api.Rendition;
import com.day.cq.dam.api.Revision;
import com.day.cq.dam.commons.metadata.SimpleXmpToJcrMetadataBuilder;
import com.day.cq.dam.drive.common.AssetType;
import com.day.cq.dam.drive.common.BasicDataConstants;
import com.day.cq.dam.drive.common.Flag;
import com.day.cq.dam.drive.common.IconConstants;
import com.day.cq.dam.drive.common.IdentificationConstants;
import com.day.cq.dam.drive.common.StringConstants;
public class DriveUtil {
private static final Logger log = LoggerFactory.getLogger(DriveUtil.class);
private static final char DELIMITER = '@';
static final String SMART_COLLECTION_SLING_RES_TYPE = "dam/smartcollection";
/**
* Returns the best fit rendition which is closest to given width and
* follows the naming convention cq5dam.[thumbnail|web].width.height.ext
*
* @param width The desired width of rendition
* @param renditions The list of renditions
* @return Closest rendition to given width which follows naming convention
* cq5dam.[thumbnail|web].width.height.ext
*/
public static Resource getBestFitRendition(int width,
List renditions) {
PrefixRenditionPicker prefixPicker = new PrefixRenditionPicker(
DamConstants.PREFIX_ASSET_THUMBNAIL + "." + width);
Resource bestFitRendition = prefixPicker.getRendition(renditions.iterator());
if (bestFitRendition != null) {
return bestFitRendition;
}
DriveUtil.WidthBasedRenditionComparator comp = new DriveUtil.WidthBasedRenditionComparator();
Collections.sort(renditions, comp);
int i = 0;
while (i < renditions.size()) {
if (width > getWidth(renditions.get(i))) {
i++;
} else {
break;
}
}
if (i == 0) {
return renditions.get(0); // required width is less than smallest
// rendition
} else if (i == renditions.size()) {
return renditions.get(i - 1); // required width is larger than
// largest rendition
} else {
int d1 = width - getWidth(renditions.get(i - 1));
int d2 = getWidth(renditions.get(i)) - width;
return d1 > d2 ? renditions.get(i) : renditions.get(i - 1); // return
// rendition
// which
// is
// closest
}
}
/**
* Returns the width of rendition if follows the naming convention
* cq5dam.[thumbnail|web].width.height.ext,else 0
*
* @param r Rendition whose width is required
* @return width if it follows the naming convention, else 0
*/
public static int getWidth(final Resource r) {
String name = r.getName();
// assuming convention cq5dam.[thumbnail|web].width.height.ext
int renditionWidth = 0;
try {
String[] split = name.split("\\.");
if (split.length > 3) {
try {
renditionWidth = Integer.parseInt(split[2]);
} catch (NumberFormatException e) {
// ignore
}
}
Asset asset = new ResourceWrapper(r).adaptTo(Rendition.class).adaptTo(
Asset.class);
if (asset != null && StringConstants.ORIGINAL.equals(name)) {
return Integer.parseInt(asset.getMetadataValue(StringConstants.TIFF_IMAGEWIDTH));
}
} catch (Exception e) {
log.warn("Failed to compute with for rendition " + name, e);
renditionWidth = 0;
}
return renditionWidth;
}
public static int getHeight(final Resource r) {
String name = r.getName();
// assuming convention cq5dam.[thumbnail|web].width.height.ext
int renditionHeight = 0;
try {
String[] split = name.split("\\.");
if (split.length > 3) {
try {
renditionHeight = Integer.parseInt(split[3]);
} catch (NumberFormatException e) {
// ignore
}
}
Asset asset = new ResourceWrapper(r).adaptTo(Rendition.class).adaptTo(
Asset.class);
if (asset != null && StringConstants.ORIGINAL.equals(name)) {
return Integer.parseInt(asset.getMetadataValue(StringConstants.TIFF_IMAGELENGTH));
}
} catch (Exception e) {
log.warn("Failed to compute with for rendition " + name, e);
renditionHeight = 0;
}
return renditionHeight;
}
public static String getIdentifier(Node n) {
String identifier = "";
try {
if (n.hasProperty("jcr:uuid")) {
identifier = n.getIdentifier();
} else {
identifier = DriveUtil.getPathBasedIdentifier(n);
}
} catch (RepositoryException e) {
log.warn("Error in getting identifier", e);
}
return identifier;
}
private static AssetType getAssetType(Resource resource) {
try {
Node resourceNode = resource.adaptTo(Node.class);
if (resourceNode.isNodeType(DamConstants.NT_DAM_ASSET)
|| resourceNode.isNodeType(JcrConstants.NT_FROZENNODE))
return AssetType.FILE;
String resourceType = resource.getResourceType();
if ("dam/collection".equals(resourceType)
|| "collections".equals(resource.getName()))
return AssetType.FILE_CONTAINER;
if ("sling:OrderedFolder".equals(resourceType)
|| "sling:Folder".equals(resourceType)
|| JcrConstants.NT_UNSTRUCTURED.equals(resourceType))
return AssetType.FILE_CONTAINER;
} catch (RepositoryException e) {
log.error("Error in getting asset type", e);
}
return null;
}
public static String[] getDataType(final SlingHttpServletRequest request) {
String dataTypes = request.getParameter(StringConstants.DATA_TYPE_PARAM);
String[] dTypes = null;
if (dataTypes != null) {
dTypes = dataTypes.split(",");
} else {
dTypes = StringConstants.ALL_PARAMETERS;
}
return dTypes;
}
/**
* Checks if given resource represent a smart collection
* @param resource an instance of {@link Resource}
* @return true
if resource
represents a smart collection
* false
if resource
does not represents a smart collection
*/
public static boolean isSmartCollection(final Resource resource) {
return resource.isResourceType(SMART_COLLECTION_SLING_RES_TYPE);
}
public static void fillRecipeData(final SlingHttpServletRequest request,
String[] dTypes, Resource resource, DriveRenditionPicker picker,
final AssetManager assetManager, JSONObject json)
throws JSONException, PathNotFoundException, RepositoryException,
XMPException {
for (int i = 0; i < dTypes.length; i++) {
String selector = dTypes[i];
if (StringConstants.IDENTIFICATION.equals(selector)) {
JSONObject identificationData = DriveUtil.buildIdentificationData(
resource, assetManager);
json.put(StringConstants.IDENTIFICATION, identificationData);
}
if (StringConstants.XMP.equals(selector)) {
String xmlStr = DriveUtil.buildXMPData(resource);
json.put(StringConstants.XMP, xmlStr);
} else if (StringConstants.VERSION_PROPERTY.equals(selector)) {
Asset asset = resource.adaptTo(Asset.class);
if (asset != null) {
Map metadata = asset.getMetadata();
json.put(StringConstants.VERSION_PROPERTY, metadata);
}
} else if (StringConstants.ICON.equals(selector)) {
json.put(StringConstants.ICON,
DriveUtil.getIconData(resource, picker));
} else if (StringConstants.BASIC.equals(selector)) {
JSONObject basicData = DriveUtil.buildBasicData(resource,
request.getRemoteUser(), assetManager);
json.put(StringConstants.BASIC, basicData);
}
}
}
private static String getPathBasedIdentifier(Node n) {
try {
if ("/".equals(n.getPath())) {
return DELIMITER + "{}";
} else {
return getPathBasedIdentifier(n.getParent()) + "\t{}"
+ n.getName();
}
} catch (Exception e) {
log.warn("Failed to get Path Based Identifier", e);
}
return null;
}
private static class WidthBasedRenditionComparator implements
Comparator {
public int compare(Resource r1, Resource r2) {
int w1 = getWidth(r1);
int w2 = getWidth(r2);
if (w1 < w2) {
return -1;
} else if (w1 == w2) {
return 0;
} else {
return 1;
}
}
}
public static JSONObject buildIdentificationData(Resource resource,
AssetManager assetManager) {
JSONObject identificationData = new JSONObject();
try {
Node resourceNode = resource.adaptTo(Node.class);
String identifier = DriveUtil.getIdentifier(resourceNode);
/*identificationData.put(IdentificationConstants.IDENTIFIER,
identifier);*/
identificationData.put(JcrConstants.JCR_UUID,
identifier);
String parentIdentifier = DriveUtil.getIdentifier(resourceNode.getParent());
/* identificationData.put(IdentificationConstants.PARENT_IDENTIFIER,
parentIdentifier);*/
identificationData.put(JcrConstants.JCR_PREDECESSORS,
parentIdentifier);
AssetType assetType = getAssetType(resource);
identificationData.put(IdentificationConstants.ASSET_TYPE,
assetType);
String resourceType = resource.getResourceType();
/* identificationData.put(IdentificationConstants.RESOURCE_TYPE,
resourceType);*/
identificationData.put(JcrConstants.JCR_DEFAULTPRIMARYTYPE,
resourceType);
String name = resource.getName();
/*identificationData.put(IdentificationConstants.ASSET_NAME, name);*/
identificationData.put(JcrConstants.JCR_NAME, name);
String path = resource.getPath();
/*identificationData.put(IdentificationConstants.ASSET_PATH, path);*/
identificationData.put(JcrConstants.JCR_PATH, path);
Asset asset = resource.adaptTo(Asset.class);
if (asset != null) {
long lastModificationDate = getLastModificationDate(asset);
Collection revisions = assetManager.getRevisions(
asset.getPath(), null);
int currentVersionNumber = revisions.size() > 0
? revisions.size() + 1
: 1;
JSONObject etag = new JSONObject();
etag.put(IdentificationConstants.ETAG_CONTENT,
lastModificationDate);
etag.put(IdentificationConstants.ETAG_VERSION,
currentVersionNumber);
identificationData.put(IdentificationConstants.ETAG, etag);
/* identificationData.put(IdentificationConstants.CURRENT_VERSION,
currentVersionNumber);
*/
identificationData.put(JcrConstants.JCR_ROOTVERSION,
currentVersionNumber);
String lastVersionComment = "";
if (currentVersionNumber > 1) {
try {
lastVersionComment = asset.adaptTo(Node.class).getNode(
"jcr:content").getProperty("cq:versionComment").getString();
} catch (Exception e) {
log.debug("Failed to get the last version comment", e);
lastVersionComment = "";
}
}
/*identificationData.put(
IdentificationConstants.LAST_VERSION_COMMENT,
lastVersionComment);*/
identificationData.put(
DamConstants.PN_VERSION_COMMENT,
lastVersionComment);
}
} catch (Exception e) {
log.error("Error in building identification data", e);
}
return identificationData;
}
private static long getLastModificationDate(Asset asset) {
long lastModificationDate = asset.getLastModified();
if (lastModificationDate == 0) { // case when asset is just created via
// copy/paste
lastModificationDate = System.currentTimeMillis();
}
return lastModificationDate;
}
public static String buildXMPData(Resource resource)
throws PathNotFoundException, RepositoryException, XMPException {
try {
Node resourceNode = resource.adaptTo(Node.class);
SimpleXmpToJcrMetadataBuilder jcrBuilder = new SimpleXmpToJcrMetadataBuilder();
Node metadataNode = resourceNode.getNode(JcrConstants.JCR_CONTENT
+ "/" + METADATA_FOLDER);
if (metadataNode == null) {
return "";
}
XMPMeta xmpMeta = jcrBuilder.getXmpFromJcr(metadataNode);
String xmlStr = XMPMetaFactory.serializeToString(xmpMeta,
new SerializeOptions());
return xmlStr;
} catch (Exception e) {
log.error("Error in building xmp string for resource", e);
}
return "";
}
public static JSONObject buildBasicData(Resource resource,
String remoteUser, AssetManager assetManager) {
JSONObject basicData = new JSONObject();
try {
Node resourceNode = resource.adaptTo(Node.class);
long creationDate;
try {
creationDate = resourceNode.getProperty("jcr:created").getLong();
} catch (Exception e1) {
log.warn("Failed to get creation date");
creationDate = System.currentTimeMillis();
}
/*basicData.put(BasicDataConstants.CREATION_DATE, creationDate);*/
basicData.put(JcrConstants.JCR_CREATED, creationDate);
Asset asset = resource.adaptTo(Asset.class);
if (asset != null) {
long lastModificationDate = getLastModificationDate(asset);
/* basicData.put(BasicDataConstants.LAST_MODIFIED,
lastModificationDate);
*/
basicData.put(JcrConstants.JCR_LASTMODIFIED,
lastModificationDate);
long size = 0;
try {
Property sizeProperty = resourceNode.getNode("jcr:content").getNode(
"metadata").getProperty(DamConstants.DAM_SIZE);
if (sizeProperty != null) size = sizeProperty.getLong();
} catch (Exception e) {
log.warn("Failed to asset size from property");
size = 0;
}
if (size == 0) size = asset.getOriginal().getSize();
/*basicData.put(BasicDataConstants.SIZE, size);*/
basicData.put(DamConstants.DAM_SIZE, size);
JSONArray flags = new JSONArray();
if (asset.getMetadata().size() > 0) flags.put(Flag.HAS_XMP);
if (asset.getRenditions().size() > 0) flags.put(Flag.HAS_ICON);
basicData.put(BasicDataConstants.FLAGS, flags);
/*basicData.put(BasicDataConstants.MIME_TYPE, asset.getMimeType());*/
basicData.put(JcrConstants.JCR_MIMETYPE, asset.getMimeType());
basicData.put(BasicDataConstants.LAST_MODIFIER,
asset.getModifier());
JSONObject lock = new JSONObject();
/*lock.put(BasicDataConstants.NODE_PATH, asset.getPath());*/
lock.put(JcrConstants.JCR_PATH, asset.getPath());
Node jcrContent = resourceNode.getNode(JcrConstants.JCR_CONTENT);
String driveLockOwner = "";
if (jcrContent.hasProperty(BasicDataConstants.DRIVE_LOCK_PROPERTY)) {
driveLockOwner = jcrContent.getProperty(
BasicDataConstants.DRIVE_LOCK_PROPERTY).getString();
/*lock.put(BasicDataConstants.LOCK_OWNER, driveLockOwner);*/
lock.put(JcrConstants.JCR_LOCKOWNER, driveLockOwner);
/*lock.put(BasicDataConstants.NODE_PATH, asset.getPath());*/
lock.put(JcrConstants.JCR_PATH, asset.getPath());
}
boolean isLockOwner = driveLockOwner.equals(remoteUser)
? true
: false;
lock.put(BasicDataConstants.IS_LOCK_OWNER, isLockOwner);
/*basicData.put(BasicDataConstants.LOCK, lock);*/
basicData.put(BasicDataConstants.LOCK, lock);
} else {
LabeledResource lr = resource.adaptTo(LabeledResource.class);
Node metaNode = null;
if (resourceNode.hasNode(JCR_CONTENT + "/" + METADATA_FOLDER)) {
metaNode = resourceNode.getNode(JCR_CONTENT + "/"
+ METADATA_FOLDER);
}
// modification status
ResourceMetadata data = resource.getResourceMetadata();
long lastModificationDate = data.getModificationTime();
/*basicData.put(BasicDataConstants.LAST_MODIFIED,
lastModificationDate);*/
basicData.put(JcrConstants.JCR_LASTMODIFIED,
lastModificationDate);
}
} catch (Exception e) {
log.error("Failed in building basic data", e);
}
return basicData;
}
public static JSONObject getIconData(Resource resource,
DriveRenditionPicker picker) {
Resource renditionsRes;
if (resource.adaptTo(Asset.class) != null) {
renditionsRes = resource.getChild(JcrConstants.JCR_CONTENT
+ "/renditions");
} else {
renditionsRes = resource.getChild(JcrConstants.JCR_FROZENNODE + "/"
+ JcrConstants.JCR_CONTENT + "/renditions");
}
JSONObject obj = new JSONObject();
if (renditionsRes == null) return obj;
Iterator itr = renditionsRes.getChildren().iterator();
List renditions = new ArrayList();
while (itr.hasNext()) {
Resource res = itr.next();
renditions.add(res);
}
Resource thumnailRendition = picker.getThumbnailRendition(renditions);
Resource previewRendition = picker.getPreviewRendition(renditions);
try {
obj.put(IconConstants.THUMBNAIL_RENDITION,
getJsonFromRendition(thumnailRendition));
obj.put(IconConstants.PREVIEW_RENDITION,
getJsonFromRendition(previewRendition));
} catch (JSONException e) {
log.error("Failed in getting icon data", e);
}
return obj;
}
public static boolean userOwnsAllLocks(Node node, String userID)
throws RepositoryException {
// Check the current node.
if (node.hasProperty(BasicDataConstants.DRIVE_LOCK_PROPERTY)) {
final String lockOwner = node.getProperty(
BasicDataConstants.DRIVE_LOCK_PROPERTY).getString();
if (!lockOwner.equals(userID)) {
return false;
}
}
if (!node.hasNodes()) {
// stop condition
return true;
} else {
// Check the children nodes.
for (NodeIterator iter = node.getNodes(); iter.hasNext();) {
if (!userOwnsAllLocks(iter.nextNode(), userID)) {
return false;
}
}
return true;
}
}
private static JSONObject getJsonFromRendition(Resource rend) {
JSONObject json = new JSONObject();
try {
if (rend != null) {
/*json.put(IconConstants.BINARY_PATH, rend.getPath());*/
json.put(JcrConstants.JCR_PATH, rend.getPath());
/* json.put(IconConstants.RENDITION_WIDTH,
DriveUtil.getWidth(rend));*/
json.put(DamConstants.EXIF_PIXELXDIMENSION,
DriveUtil.getWidth(rend));
/*json.put(IconConstants.RENDITION_HEIGHT,
DriveUtil.getHeight(rend));*/
json.put(DamConstants.EXIF_PIXELYDIMENSION,
DriveUtil.getHeight(rend));
String mimeType = rend.getChild(JcrConstants.JCR_CONTENT).adaptTo(
Node.class).getProperty("jcr:mimeType").getString();
/*json.put(IconConstants.MIME_TYPE, mimeType);*/
json.put(JcrConstants.JCR_MIMETYPE, mimeType);
}
} catch (Exception e) {
log.error("Failed in getting json from rendition", e);
}
return json;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy