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

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