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

com.day.cq.dam.core.process.MetadataExtractor 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 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.core.process;

import static com.day.cq.commons.jcr.JcrConstants.JCR_CONTENT;
import static com.day.cq.dam.api.DamConstants.DAM_SIZE;
import static com.day.cq.dam.api.DamConstants.DC_FORMAT;
import static com.day.cq.dam.api.DamConstants.METADATA_FOLDER;
import static com.day.cq.dam.api.DamConstants.PN_EXTRACTED;
import static com.day.cq.dam.api.DamConstants.PN_SHA1;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;

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

import com.day.cq.dam.commons.util.AssetCache;
import com.day.cq.dam.commons.util.DamUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.contentdetection.ContentAwareMimeTypeService;
import org.apache.sling.commons.mime.MimeTypeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.Rendition;
import com.day.cq.dam.api.handler.AssetHandler;
import com.day.cq.dam.api.metadata.ExtractedMetadata;
import com.day.cq.dam.commons.metadata.SimpleXmpToJcrMetadataBuilder;
import com.day.cq.dam.commons.util.DamMimeUtil;
import com.day.cq.tagging.JcrTagManagerFactory;
import com.day.cq.tagging.Tag;
import com.day.cq.tagging.TagManager;

/**
 * The MetadataExtractor is used in multiple workflow steps. At the time of
 * writing this comment it is used in Metadata Processor step and Metadata Extractor step.
 *
 */
public class MetadataExtractor {
    /**
     * Logger instance for this class.
     */
    private static final Logger log = LoggerFactory.getLogger(MetadataExtractor.class);

    private static final String JCR_CONTENT_METADATA = JCR_CONTENT + "/" + METADATA_FOLDER;
    private static final String JCR_CONTENT_JCR_DATA = "jcr:content/jcr:data";

    private SimpleXmpToJcrMetadataBuilder metadataBuilder;

    /**
     * @deprecated since release 6.3, this has been replaced by
     * {@link com.day.cq.dam.commons.metadata.SimpleXmpToJcrMetadataBuilder},
     * implying that responsibility (and ownership) of providing XMP Metadata Builder class lies with the component instantiating
     * {@link com.day.cq.dam.core.process.MetadataExtractor}
     *
     * To prevent catastrophic failures for components calling the deprecated API, a new instance of
     * {@link com.day.cq.dam.commons.metadata.SimpleXmpToJcrMetadataBuilder} is created by this constructor.
     * However, please be aware that since SimpleXmpToJcrMetadataBuilder is now an OSGi Declarative Service, lifecycle events
     * and any configurations of the service WILL NOT be honoured when deprecated API is invoked.
     */
    @Deprecated
    public MetadataExtractor() {
        log.warn("Deprecated constructor invoked. Please instantiate MetadataExtractor object providing "
            + "com.day.cq.dam.commons.metadata.SimpleXmpToJcrMetadataBuilder as argument");
        this.metadataBuilder = new SimpleXmpToJcrMetadataBuilder();
    }

    public MetadataExtractor(SimpleXmpToJcrMetadataBuilder metadataBuilder) {
        this.metadataBuilder = metadataBuilder;
    }

    public void extractMetadata(Session session, Asset asset, AssetHandler assetHandler,
        boolean sha1Enabled, MimeTypeService mimeTypeService) throws RepositoryException, IOException {

        final AssetCache cache = DamUtil.getAssetCache();
        try {
            //set the enable writeback flag to false
            final Resource assetResource = asset.adaptTo(Resource.class);
            final ResourceResolver resolver = assetResource.getResourceResolver();
            final Resource metadataResource = resolver.getResource(assetResource, JCR_CONTENT_METADATA);

            final ExtractedMetadata metadata = assetHandler.extractMetadata(asset);
            // set these properties always
            metadata.setMetaDataProperty(PN_EXTRACTED, Calendar.getInstance().getTime());

            Rendition originalRendition = asset.getOriginal();
            if (sha1Enabled) {
                final String sha1 = DigestUtils.shaHex(cache.getStream(originalRendition, false));
                metadata.setMetaDataProperty(PN_SHA1, sha1);
            }

            //add size of the asset as property
            Node originalBinary = originalRendition.adaptTo(Node.class);
            if (originalBinary.hasProperty(JCR_CONTENT_JCR_DATA)) {
                metadata.setMetaDataProperty(DAM_SIZE, originalBinary.getProperty(JCR_CONTENT_JCR_DATA).getBinary().getSize());
            }

            // recheck mime type respectively dc:format. it might happen
            // that the extracted xmp data contains
            // a wrong dc:format value. the correct dc:format value is
            // required for the processing.
            resetMimetype(asset, metadata, mimeTypeService);
            saveMetadata(asset, metadata, metadataResource);

        }
        finally {
            cache.release();
        }
    }

    protected void saveMetadata(final Asset asset,
        final ExtractedMetadata metadata, Resource metadataResource) {

        if (null != metadataResource) {
            try {
                metadataBuilder.storeAsXmp(metadata, asset, false);

            } catch (Exception e) {
                log.error(
                    "saveMetadata: error while saving metdata for asset [{}]: ",
                    asset.getPath(), e);
            }
        } else {
            log.error(
                "execute: cannot save metdata for asset [{}], doesn't have metdata node.",
                asset.getPath());
        }
    }



    /**
     * Resets the mimetype
     * 
     * @param asset Asset to read the mimetype
     * @param metadata Metadata to set the mimetype
     * @param mimeTypeService 
     */
    private void resetMimetype(Asset asset, ExtractedMetadata metadata, MimeTypeService mimeTypeService) {

        final AssetCache cache = DamUtil.getAssetCache();
        String mimeType = null;
        try {
            if (DamMimeUtil.getDetectMimeFromContent()) {
                InputStream is = cache.getOriginalStream(asset, false);
                if (!is.markSupported()) {
                    is = new BufferedInputStream(is);
                }
                mimeType = ((ContentAwareMimeTypeService)mimeTypeService).getMimeType(asset.getName(), is);
            } else {
                mimeType = mimeTypeService.getMimeType(asset.getName());
            }
        } catch (IOException ign) {
            ;
        }
        finally {
            cache.release();
        }
        if (StringUtils.isNotEmpty(mimeType)) {
            metadata.setMetaDataProperty(DC_FORMAT, mimeType);
        }
    }



}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy