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

com.day.cq.dam.core.process.MetadataProcessorProcess 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 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.AssetUpdate;
import com.day.cq.dam.commons.util.AssetUpdateMonitor;
import com.day.cq.dam.commons.util.DamUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.PropertyUnbounded;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.ReferencePolicyOption;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.contentdetection.ContentAwareMimeTypeService;
import org.apache.sling.commons.osgi.OsgiUtil;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.granite.xss.XSSAPI;
import com.day.cq.commons.jcr.JcrConstants;
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.handler.AssetHandler;
import com.day.cq.dam.commons.metadata.SimpleXmpToJcrMetadataBuilder;
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 MetadataProcessorProcess is called in a workflow process step.
 * This process will import metadata, create references and apply processing profile if the
 * paylod of the step is an
 * {@link com.day.cq.dam.api.Asset Asset} or a part of an
 * {@link com.day.cq.dam.api.Asset Asset}.
 * 
 * @see AbstractAssetWorkflowProcess
 */
@Component(metatype = true)
@Service
@Property(name = "process.label", value = "Metadata Processor")
public class MetadataProcessorProcess extends AbstractAssetWorkflowProcess {

    private static final String METADATA_EXTRACED = "com.day.cq.dam.core.process.meta.extraced";

	private boolean sha1Enabled = false;
	private ProcessingProfileApplier processingProfileApplier = new ProcessingProfileApplier();

	@Reference(
		policy = ReferencePolicy.DYNAMIC,
		cardinality = ReferenceCardinality.OPTIONAL_UNARY,
		policyOption = ReferencePolicyOption.GREEDY  // ensures service-resolution to the one ranked highest
		)
	protected ContentAwareMimeTypeService contentAwareMimeTypeService;

	@Property(boolValue = true)
	public static final String ENABLE_SHA1_GEN = "cq.dam.enable.sha1";

    @Property(value = { "adobe_dam:restrictions" }, unbounded = PropertyUnbounded.ARRAY, label = "XSS protected properties", description = "These properties will be passed through xss api before saving")
    public static final String XSS_PROTECTED_PROPERTIES = "cq.dam.metadata.xssprotected.properties";

    private String[] xssProtectedProperties;

    private static final String[] DEFAULT_XSS_PROTECTED_PROPERTIES = new String[] { "adobe_dam:restrictions" };

	private static final String ATTRIBUTE_EXTRACT_METADATA = "dam:extractMetadata";

    @Reference
    private XSSAPI xssApi;

    @Reference
    private SimpleXmpToJcrMetadataBuilder metadataBuilder;

    @Reference
    private AssetUpdateMonitor monitor;

	/**
	 * Logger instance for this class.
	 */
	private static final Logger log = LoggerFactory.getLogger(MetadataProcessorProcess.class);

	public void execute(final WorkItem workItem, WorkflowSession workflowSession,
			MetaDataMap args) throws WorkflowException {
	    if (workItem.getWorkflow().getMetaDataMap().get(METADATA_EXTRACED, Boolean.FALSE)) {
            /* already run in this workflow */
            log.debug("already executed in workflow {}", workItem.getWorkflow().getId());
            return;
        }

	    final AssetCache cache = DamUtil.getAssetCache();
        final AssetUpdate update = monitor.startUpdate(workItem, getResourceResolver(workflowSession.getSession()), this);
		try {
			final Session session = workflowSession.getSession();
			final Asset asset = update.getAsset(new AssetUpdate.Check() {
                @Override
                public boolean isNullAcceptable() throws WorkflowException {
                    String wfPayload = workItem.getWorkflowData().getPayload().toString();
                    String message = "execute: cannot extract metadata, create references and apply processing profile, asset [{"
                            + wfPayload	+ "}] in payload doesn't exist for workflow [{"
                            + workItem.getId() + "}].";
                    throw new WorkflowException(message);
                }
            });
			if (null != asset) {
				asset.setBatchMode(true);
				try {
				    asset.adaptTo(AssetManager.class).assignAssetID(asset);
				} catch (RepositoryException e) {
                    update.error(e);
				    log.error("Couldn't assign Asset ID to asset at {}."
		                    + "Please see if sufficient privileges are available", asset.getPath(), e);
				}

				final AssetHandler assetHandler = getAssetHandler(asset.getMimeType());
				if (null != assetHandler) {
					Node assetNode = asset.adaptTo(Node.class);
					if(extractMetadataRequired(assetNode)) {
						MetadataExtractor metadataExtractor = new MetadataExtractor(metadataBuilder);
						metadataExtractor.extractMetadata(session, asset, assetHandler, sha1Enabled,
							(null != contentAwareMimeTypeService)
								? contentAwareMimeTypeService
								: mimeTypeService);
						assetHandler.processRelated(asset);
					} else {
						log.debug("execute: Metadata not extracted on Asset : {}. Property dam:extractMetadata is " +
							"found to be false", asset.getPath());
                        update.ignore();
					}
					removeExtractMetadataProperty(assetNode);
				} else {
					log.error("execute: cannot extract metadata, no handler found for asset [{}] with mime type [{}]",
							asset.getPath(), asset.getMimeType());
                    update.ignore();
				}
				processingProfileApplier.applyProcessingProfile(session, asset);
				processXSSProtectedProperties(asset, getResourceResolver(session));
                //workItem.getWorkflow().getMetaDataMap().put(METADATA_EXTRACED, Boolean.TRUE);
                log.debug("remembering execution in workflow {}", workItem.getWorkflow().getId());
			}
		} catch (Exception e) {
            update.error(e);
			log.warn("unexpected error occurred during metadata extraction. Cause: {}",
					e.getMessage(), e);
		}
		finally {
		    cache.release();
            update.done();
        }
    }

    /**
     * applies xss protection to all the properties in asset's metdata that
     * matches with xssProtectedProperties
     *
     * @param asset
     * @param resourceResolver
     */

    private void processXSSProtectedProperties(Asset asset,
            ResourceResolver resourceResolver) {
        try {
            Resource assetResource = resourceResolver.getResource(asset.getPath());
            Resource metadataResource = assetResource.getChild(JcrConstants.JCR_CONTENT
                + "/" + DamConstants.METADATA_FOLDER);
            ModifiableValueMap metadataVM = metadataResource.adaptTo(ModifiableValueMap.class);
            for (String prop : xssProtectedProperties) {
                String propValue = asset.getMetadataValue(prop);
                if (StringUtils.isNotBlank(propValue)) {
                    metadataVM.put(prop, xssApi.encodeForHTML(propValue));
                }
            }
        } catch (Exception e) {
            log.error(
                "Exception occured while applying for xss to xss protected properties",
                e.getMessage());
        }
    }


    @Activate
    @SuppressWarnings("unused")
    protected void Actiate(final ComponentContext context) throws RepositoryException {
        sha1Enabled = OsgiUtil.toBoolean(context.getProperties().get(ENABLE_SHA1_GEN), true);
        xssProtectedProperties = OsgiUtil.toStringArray(
            context.getProperties().get(XSS_PROTECTED_PROPERTIES),
            DEFAULT_XSS_PROTECTED_PROPERTIES);
    }

	private static boolean extractMetadataRequired(Node assetNode){
		boolean retVal = true;
		try {
			if (assetNode.hasNode(JcrConstants.JCR_CONTENT)) {
                Node contentNode = assetNode.getNode(JcrConstants.JCR_CONTENT);
                if(contentNode.hasProperty(ATTRIBUTE_EXTRACT_METADATA)) {
                    retVal = contentNode.getProperty(ATTRIBUTE_EXTRACT_METADATA).getBoolean();
                }
            }
		} catch (RepositoryException e) {}
		return retVal;
	}

	private static void removeExtractMetadataProperty(Node assetNode) throws RepositoryException {
		try {
			if (assetNode.hasNode(JcrConstants.JCR_CONTENT)) {
				Node contentNode = assetNode.getNode(JcrConstants.JCR_CONTENT);
				if(contentNode.hasProperty(ATTRIBUTE_EXTRACT_METADATA)) {
					contentNode.getProperty(ATTRIBUTE_EXTRACT_METADATA).remove();
				}
			}
		} catch (RepositoryException e) {}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy