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

com.day.cq.dam.commons.handler.XMPProcessor Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
/*
 * Copyright 1997-2009 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */
package com.day.cq.dam.commons.handler;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.adobe.xmp.XMPException;
import com.adobe.xmp.XMPMetaFactory;
import com.day.cq.dam.api.Context;
import com.day.cq.dam.api.Processor;
import com.day.cq.dam.api.ProcessorException;
import com.day.cq.dam.commons.metadata.XmpFilter;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Process bytes, extract metadata found in <xpacket> tags and add them to
 * a {@link Context}.
 *
 * @author dpfister
 */
public class XMPProcessor implements Processor, FilterStateListener {

    /**
     * Context.
     */
    private Context context;

    /**
     * Top filter we're passing bytes to.
     */
    private XPacketFilter topFilter;

    /**
     * Create a new instance of this class.
     *
     * @param context context
     */
    public XMPProcessor(Context context) {
        this.context = context;

        topFilter = new XPacketFilter();
        topFilter.setFilterStateListener(this);
        topFilter.setAutoReset(true);
    }

    //---------------------------------------------------------------- Processor

    /**
     * {@inheritDoc}
     */
    public final void process(byte[] buf, int off, int len) throws IOException {
        topFilter.filter(buf, off, len);
    }

    //------------------------------------------------------ FilterStateListener

    /**
     * {@inheritDoc}
     */
    public OutputStream started(Filter filter) {
        return new ByteArrayOutputStream(8192);
    }

    /**
     * {@inheritDoc}
     */
    public void ended(Filter filter, OutputStream out) {
        ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
        BundleContext bundleContext = getBundleContext();
        ServiceReference filterRef = bundleContext.getServiceReference(XmpFilter.class);

        try {
            if (filterRef != null) {
                XmpFilter xmpFilter = bundleContext.getService(filterRef);
                if (xmpFilter != null) {

                    byte[] buf = bos.toByteArray();

                    ByteArrayInputStream bis = new ByteArrayInputStream(buf);

                    // Test parsing the input stream
                    XMPMetaFactory.parse(xmpFilter.filter(bis));

                    // If this was valid, add the input stream (to be changed
                    // when ExtractedMetadata supports setting XMPMeta directly)
                    context.addMetadata(new ByteArrayInputStream(buf));
                } else {
                    String msg = "Unable to get XMPFilter service.";
                    context.addException(new ProcessorException(msg, new Exception(msg), this));
                }
            } else {
                String msg = "Unable to get XMPFilter service.";
                context.addException(new ProcessorException(msg, new Exception(msg), this));
            }
        } catch (XMPException | IOException e) {
            String msg = "Unable to get XMP object from input";
            context.addException(new ProcessorException(msg, e, this));
        } finally {
            if (filterRef != null) {
                bundleContext.ungetService(filterRef);
            }
        }
    }

    /**
     * Utility method that processes an input stream and returns the first
     * valid XMP input stream.
     *
     * @param in input stream
     * @throws IOException if an I/O error occurs
     * @throws ProcessorException if a processor error occurs
     */
    public static InputStream process(InputStream in)
            throws IOException, ProcessorException {

        SimpleContext context = new SimpleContext();
        XMPProcessor processor = new XMPProcessor(context);

        byte[] buf = new byte[8192];
        int len;

        while ((len = in.read(buf)) > 0) {
            processor.process(buf, 0, len);
        }
        InputStream[] metadata = context.getMetadata();
        if (metadata != null && metadata.length > 0) {
            return metadata[0];
        }
        ProcessorException[] exceptions = context.getExceptions();
        if (exceptions != null) {
            throw exceptions[exceptions.length - 1];
        }
        return null;
    }

    // For testability
    BundleContext getBundleContext() {
        return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy