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

com.day.cq.dam.handler.standard.ps.PostScriptHandler Maven / Gradle / Ivy

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * ___________________
 *
 *  Copyright 2012 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.handler.standard.ps;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.io.UnsupportedEncodingException;
import java.lang.Exception;
import java.lang.String;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

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

import com.adobe.granite.asset.api.AssetRelation;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.dam.api.DamConstants;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.FormatHandler;
import com.day.cq.dam.api.Rendition;
import com.day.cq.dam.api.ProcessorException;



import org.apache.commons.io.IOUtils;
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.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.internal.pdftoolkit.core.util.Utility;
import com.day.cq.dam.api.metadata.ExtractedMetadata;
import com.day.cq.dam.commons.handler.DefaultFormatHandler;
import com.day.cq.dam.handler.standard.pdf.PdfHandler;
import com.day.cq.dam.api.AssetReferenceResolver;
/**
 * PostScriptHandler Handles files with mimetype as application/postscript.
 * First it tries to see if the file is an illustrator file then it delegate the handling to pdfHandler
 * else, it tries to use the format handlers that are available for handle the file.
 *
 */
@Component(inherit = true, metatype = true)
@Service
public class PostScriptHandler extends PdfHandler {

    private static final Logger log = LoggerFactory.getLogger(PostScriptHandler.class);

    @Property(boolValue = false, name = "raster.annotation")
    private static final String RASTER_ANNOTATION = "raster_annotation";

    @Reference(policy = ReferencePolicy.STATIC)
    private AssetReferenceResolver childRefResolver;
    /**
     * Mime type
     */
    public static final String CONTENT_MIMETYPE = "application/postscript";

    public static final String XMP_MANIFEST_PATH = JcrConstants.JCR_CONTENT + "/" + DamConstants.METADATA_FOLDER + "/xmpMM:Manifest";
    public static final String FILE_REFERENCE_PATH = "stMfs:reference";
    
    /**
     * Number of bytes to pre-read to determine correct format handler.
     */
    private static final int MAGIC_SIZE = 1024;

    /**
     * {@inheritDoc}
     */
    public String[] getMimeTypes() {
        return new String[] { CONTENT_MIMETYPE };
    }

    /**
     * Bundle context.
     */
    protected BundleContext bundleContext;

    /**
     * Invoked on service activation.
     *
     * @param componentContext component context
     */
    protected void activate(ComponentContext componentContext) {
        bundleContext = componentContext.getBundleContext();
    }

    /**
     * Invoked on service deactivation.
     *
     * @param componentContext component context
     */
    protected void deactivate(ComponentContext componentContext) {
        bundleContext = null;
    }

    /**
     * {@inheritDoc}
     */
    public final ExtractedMetadata extractMetadata(final Asset asset) {
        ExtractedMetadata metadata = new ExtractedMetadata();
        InputStream in = null;

        try {
            in = asset.getOriginal().getStream();
            metadata = extractMetadata(in, asset);
        } finally {
            IOUtils.closeQuietly(in);
        }
        setMimetype(metadata, asset);
        return metadata;
    }

    /**
     * {@inheritDoc}
     */
    public BufferedImage getImage(final Rendition rendition, Dimension dim) throws IOException {
        InputStream in = null;
        try {
            in = rendition.getStream();
            return getThumbnailImage(in, rendition, dim);
        } finally {
            IOUtils.closeQuietly(in);
        }
    }

    /**
     * Extract metadata from an input stream and store it inside metadata provided.
     *
     * @param in       input stream
     * @param asset    asset being processed
     * @param metadata metadata
     */
    private ExtractedMetadata extractMetadata(final InputStream in, final Asset asset) {
        ExtractedMetadata metadata = new ExtractedMetadata();
        PushbackInputStream pin = new PushbackInputStream(in, MAGIC_SIZE);
        byte[] data = new byte[MAGIC_SIZE];
        int len;

        try {
            // prefetch some bytes to find correct handler
            if ((len = pin.read(data)) <= 0) {
                // no content
                return metadata;
            }
            pin.unread(data, 0, len);
            //check if it is an isAIFile with application/postscript as mimetype
            if (isAIFile(data, 0, len)) {

                /* On updation of asset, metadata gets updated with previous versions. Changing the behaviour for MANIFEST node of AI files such that references
                 doesn't gets effected.
                  */
                try {
                    Node assetNode = asset.adaptTo(Node.class);
                    if(assetNode.hasNode(XMP_MANIFEST_PATH)) {
                        Node manifestNode = assetNode.getNode(XMP_MANIFEST_PATH);
                        manifestNode.remove();
                    }
                } catch(RepositoryException e) {
                    log.error("Error while deleting MANIFEST node of AI file", e);
                }
                return super.extractMetadata(asset);
            } else {
                FormatHandler handler = getHandler(data, 0, len);
                if (handler == null) {
                    handler = new DefaultFormatHandler();
                }
                InputStream xmp = handler.getMetadata(pin);
                if (xmp != null) {
                    metadata.setXmp(xmp);
                }
            }

        } catch (IOException e) {
            log.warn("I/O error while getting metadata.", e);
        } catch (ProcessorException e) {
            log.warn("Error while processing {}: {}", asset.getPath(), e.getMessage());
            if (log.isDebugEnabled()) {
                log.debug("Stack trace.", e);
            }
        }
        return metadata;
    }

    /**
     * Find a thumbnail image inside an asset given as input stream.
     *
     * @param in        input stream
     * @param rendition being processed
     *                  

* As a last resort, try to locate a JPEG inside the asset input stream or a Base64 encoded image * in XMP. * @return The graphical representation. */ protected BufferedImage getThumbnailImage(final InputStream in, final Rendition rendition, Dimension dim) { PushbackInputStream pin = new PushbackInputStream(in, MAGIC_SIZE); byte[] data = new byte[MAGIC_SIZE]; int len; try { // prefetch some bytes to find correct handler if ((len = pin.read(data)) <= 0) { // no content return null; } pin.unread(data, 0, len); //check if it is an isAIFile with application/postscript as mimetype if (isAIFile(data, 0, len)) { return super.getImage(rendition, dim); } else { FormatHandler handler = getHandler(data, 0, len); if (handler == null) { handler = new DefaultFormatHandler(); } return handler.getThumbnailImage(pin); } } catch (IOException e) { log.warn("I/O error while getting thumbnail image.", e); } catch (ProcessorException e) { log.warn("Error while processing {}: {}", rendition.getPath(), e.getMessage()); if (log.isDebugEnabled()) { log.debug("Stack trace.", e); } } return null; } /** * Return the handler that will accept the bytes given. * * @param data first bytes of stream * @param off off * @param len len * @return handler or null if no handler is willing to handle */ private FormatHandler getHandler(byte[] data, int off, int len) { if (bundleContext == null) { log.warn("No bundle context available."); return null; } try { ServiceReference[] refs = bundleContext.getServiceReferences( FormatHandler.class.getName(), "(mimetype=*)"); if (refs != null) { for (ServiceReference ref : refs) { FormatHandler handler = (FormatHandler) bundleContext.getService(ref); if (handler.accepts(data, off, len)) { return handler; } bundleContext.ungetService(ref); } } } catch (InvalidSyntaxException e) { log.warn("Unexpected exception while getting all format handlers.", e); } return null; } /** * Return a flag indicating whether the handler is able to handle the Illustrator poastscript file. * * @param data data buffer * @param off offset * @param len number of valid bytes * @return true if the handler is able to handle the data; false otherwise */ private boolean isAIFile(byte[] data, int off, int len){ // Is this stream a PDF data stream? // See if you can find the PDF marker in the first 1024 bytes. // see PDF 1.5, Appendix H, note 13 byte[]pdfMarker = {'%', 'P', 'D', 'F', '-'}; int size = 1024; if (size > len) size = len; byte[] header = new byte[size]; System.arraycopy(data, off, header, 0, size); long result = Utility.KMPFindFirst(pdfMarker, Utility.ComputeKMPNextArray(pdfMarker), header); return (result >= 0); } /** * Extracts and create sub asset for the asset. For illustrator file, it tries to extract the subassets, * for application/postscript files generated from other applications, it is a no-op * */ public List processSubAssets(final Asset asset) { InputStream in = null; try { in = asset.getOriginal().getStream(); PushbackInputStream pin = new PushbackInputStream(in, MAGIC_SIZE); byte[] data = new byte[MAGIC_SIZE]; int len; try { // prefetch some bytes to find correct handler if ((len = pin.read(data)) <= 0) { // no content return null; } pin.unread(data, 0, len); //check if it is an isAIFile with application/postscript as mimetype if (isAIFile(data, 0, len)) { return super.processSubAssets(asset); } } catch (IOException e) { log.warn("I/O error while getting processing subassets.", e); } } finally { IOUtils.closeQuietly(in); } // noop log.debug("processSubAssets: no subassets to process for asset [{}].", asset.getPath()); return new ArrayList(); } public Iterator processRelated(final Asset asset) { return childRefResolver.resolve(asset); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy