org.alfresco.extension.pdftoolkit.repo.action.executer.PDFEncryptionActionExecuter.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.extension.pdftoolkit.repo.action.executer.PDFEncryptionActionExecuter.java

Source

/*
 * Copyright 2008-2012 Alfresco Software Limited.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * 
 * This file is part of an unsupported extension to Alfresco.
 */

package org.alfresco.extension.pdftoolkit.repo.action.executer;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.extension.pdftoolkit.constraints.MapConstraint;
import org.alfresco.extension.pdftoolkit.model.PDFToolkitModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;

public class PDFEncryptionActionExecuter extends BasePDFActionExecuter {

    /**
     * The logger
     */
    private static Log logger = LogFactory.getLog(PDFEncryptionActionExecuter.class);

    /**
     * Flag for use of "pdft:encrypted" aspect, enable search by encryption metadata
     */
    private boolean useAspect = true;

    /**
     * Constraints
     */
    public static HashMap<String, String> encryptionLevelConstraint = new HashMap<String, String>();

    /**
     * Action constants
     */
    public static final String NAME = "pdf-encryption";
    public static final String PARAM_DESTINATION_FOLDER = "destination-folder";

    /**
     * Encryption constants
     */
    public static final String PARAM_USER_PASSWORD = "user-password";
    public static final String PARAM_OWNER_PASSWORD = "owner-password";
    public static final String PARAM_ALLOW_PRINT = "allow-print";
    public static final String PARAM_ALLOW_COPY = "allow-copy";
    public static final String PARAM_ALLOW_CONTENT_MODIFICATION = "allow-content-modification";
    public static final String PARAM_ALLOW_ANNOTATION_MODIFICATION = "allow-annotation-modification";
    public static final String PARAM_ALLOW_FORM_FILL = "allow-form-fill";
    public static final String PARAM_ALLOW_SCREEN_READER = "allow-screen-reader";
    public static final String PARAM_ALLOW_DEGRADED_PRINT = "allow-degraded-print";
    public static final String PARAM_ALLOW_ASSEMBLY = "allow-assembly";
    public static final String PARAM_ENCRYPTION_LEVEL = "encryption-level";
    public static final String PARAM_EXCLUDE_METADATA = "exclude-metadata";
    public static final String PARAM_OPTIONS_LEVEL = "level-options";

    /**
     * Setter for constraint bean
     * 
     * @param encryptionLevelConstraint
     */
    public void setEncryptionLevelConstraint(MapConstraint mc) {
        encryptionLevelConstraint.putAll(mc.getAllowableValues());
    }

    public void setUseAspect(boolean useAspect) {
        this.useAspect = useAspect;
    }

    /**
     * Add parameter definitions
     */
    @Override
    protected void addParameterDefinitions(List<ParameterDefinition> paramList) {

        paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF, false,
                getParamDisplayLabel(PARAM_DESTINATION_FOLDER)));
        paramList.add(new ParameterDefinitionImpl(PARAM_USER_PASSWORD, DataTypeDefinition.TEXT, true,
                getParamDisplayLabel(PARAM_USER_PASSWORD)));
        paramList.add(new ParameterDefinitionImpl(PARAM_OWNER_PASSWORD, DataTypeDefinition.TEXT, true,
                getParamDisplayLabel(PARAM_OWNER_PASSWORD)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ALLOW_PRINT, DataTypeDefinition.BOOLEAN, true,
                getParamDisplayLabel(PARAM_ALLOW_PRINT)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ALLOW_COPY, DataTypeDefinition.BOOLEAN, true,
                getParamDisplayLabel(PARAM_ALLOW_COPY)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ALLOW_CONTENT_MODIFICATION, DataTypeDefinition.BOOLEAN,
                true, getParamDisplayLabel(PARAM_ALLOW_CONTENT_MODIFICATION)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ALLOW_ANNOTATION_MODIFICATION, DataTypeDefinition.BOOLEAN,
                true, getParamDisplayLabel(PARAM_ALLOW_ANNOTATION_MODIFICATION)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ALLOW_FORM_FILL, DataTypeDefinition.BOOLEAN, true,
                getParamDisplayLabel(PARAM_ALLOW_FORM_FILL)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ALLOW_SCREEN_READER, DataTypeDefinition.BOOLEAN, true,
                getParamDisplayLabel(PARAM_ALLOW_SCREEN_READER)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ALLOW_DEGRADED_PRINT, DataTypeDefinition.BOOLEAN, true,
                getParamDisplayLabel(PARAM_ALLOW_DEGRADED_PRINT)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ALLOW_ASSEMBLY, DataTypeDefinition.BOOLEAN, true,
                getParamDisplayLabel(PARAM_ALLOW_ASSEMBLY)));
        paramList.add(new ParameterDefinitionImpl(PARAM_ENCRYPTION_LEVEL, DataTypeDefinition.TEXT, true,
                getParamDisplayLabel(PARAM_ENCRYPTION_LEVEL), false, "pdfc-encryptionlevel"));
        paramList.add(new ParameterDefinitionImpl(PARAM_EXCLUDE_METADATA, DataTypeDefinition.BOOLEAN, true,
                getParamDisplayLabel(PARAM_EXCLUDE_METADATA)));

        super.addParameterDefinitions(paramList);
    }

    /**
     * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.repository.NodeRef,
     * org.alfresco.service.cmr.repository.NodeRef)
     */
    @Override
    protected void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) {
        if (serviceRegistry.getNodeService().exists(actionedUponNodeRef) == false) {
            // node doesn't exist - can't do anything
            return;
        }

        ContentReader actionedUponContentReader = getReader(actionedUponNodeRef);

        if (actionedUponContentReader != null) {
            // Encrypt the document with the requested options
            doEncrypt(ruleAction, actionedUponNodeRef, actionedUponContentReader);

            {
                if (logger.isDebugEnabled()) {
                    logger.debug("Can't execute rule: \n" + "   node: " + actionedUponNodeRef + "\n" + "   reader: "
                            + actionedUponContentReader + "\n" + "   action: " + this);
                }
            }
        }
    }

    /**
     * @see org.alfresco.repo.action.executer.TransformActionExecuter#doTransform(org.alfresco.service.cmr.action.Action,
     * org.alfresco.service.cmr.repository.ContentReader,
     * org.alfresco.service.cmr.repository.ContentWriter)
     */
    protected void doEncrypt(Action ruleAction, NodeRef actionedUponNodeRef,
            ContentReader actionedUponContentReader) {

        Map<String, Object> options = new HashMap<String, Object>(INITIAL_OPTIONS);

        options.put(PARAM_DESTINATION_FOLDER, ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER));
        options.put(PARAM_USER_PASSWORD, ruleAction.getParameterValue(PARAM_USER_PASSWORD));
        options.put(PARAM_OWNER_PASSWORD, ruleAction.getParameterValue(PARAM_OWNER_PASSWORD));
        options.put(PARAM_ALLOW_PRINT, ruleAction.getParameterValue(PARAM_ALLOW_PRINT));
        options.put(PARAM_ALLOW_COPY, ruleAction.getParameterValue(PARAM_ALLOW_COPY));
        options.put(PARAM_ALLOW_CONTENT_MODIFICATION,
                ruleAction.getParameterValue(PARAM_ALLOW_CONTENT_MODIFICATION));
        options.put(PARAM_ALLOW_ANNOTATION_MODIFICATION,
                ruleAction.getParameterValue(PARAM_ALLOW_ANNOTATION_MODIFICATION));
        options.put(PARAM_ALLOW_FORM_FILL, ruleAction.getParameterValue(PARAM_ALLOW_FORM_FILL));
        options.put(PARAM_ALLOW_SCREEN_READER, ruleAction.getParameterValue(PARAM_ALLOW_SCREEN_READER));
        options.put(PARAM_ALLOW_DEGRADED_PRINT, ruleAction.getParameterValue(PARAM_ALLOW_DEGRADED_PRINT));
        options.put(PARAM_ALLOW_ASSEMBLY, ruleAction.getParameterValue(PARAM_ALLOW_ASSEMBLY));
        options.put(PARAM_ENCRYPTION_LEVEL, ruleAction.getParameterValue(PARAM_ENCRYPTION_LEVEL));
        options.put(PARAM_EXCLUDE_METADATA, ruleAction.getParameterValue(PARAM_EXCLUDE_METADATA));
        options.put(PARAM_OPTIONS_LEVEL, ruleAction.getParameterValue(PARAM_OPTIONS_LEVEL));

        try {
            this.action(ruleAction, actionedUponNodeRef, actionedUponContentReader, options);
        } catch (AlfrescoRuntimeException e) {
            throw new AlfrescoRuntimeException(e.getMessage(), e);
        }
    }

    /**
     * @param reader
     * @param writer
     * @param options
     * @throws Exception
     */
    protected final void action(Action ruleAction, NodeRef actionedUponNodeRef,
            ContentReader actionedUponContentReader, Map<String, Object> options) {

        PdfStamper stamp = null;
        File tempDir = null;
        ContentWriter writer = null;

        try {
            // get the parameters
            String userPassword = (String) options.get(PARAM_USER_PASSWORD);
            String ownerPassword = (String) options.get(PARAM_OWNER_PASSWORD);
            int permissions = buildPermissionMask(options);
            int encryptionType = Integer.parseInt((String) options.get(PARAM_ENCRYPTION_LEVEL));

            // if metadata is excluded, alter encryption type
            if ((Boolean) options.get(PARAM_EXCLUDE_METADATA)) {
                encryptionType = encryptionType | PdfWriter.DO_NOT_ENCRYPT_METADATA;
            }

            // get temp file
            File alfTempDir = TempFileProvider.getTempDir();
            tempDir = new File(alfTempDir.getPath() + File.separatorChar + actionedUponNodeRef.getId());
            tempDir.mkdir();
            File file = new File(tempDir,
                    serviceRegistry.getFileFolderService().getFileInfo(actionedUponNodeRef).getName());

            // get the PDF input stream and create a reader for iText
            PdfReader reader = new PdfReader(actionedUponContentReader.getContentInputStream());
            stamp = new PdfStamper(reader, new FileOutputStream(file));

            // encrypt PDF
            stamp.setEncryption(userPassword.getBytes(Charset.forName("UTF-8")),
                    ownerPassword.getBytes(Charset.forName("UTF-8")), permissions, encryptionType);
            stamp.close();

            // write out to destination
            NodeRef destinationNode = createDestinationNode(file.getName(),
                    (NodeRef) ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER), actionedUponNodeRef);
            writer = serviceRegistry.getContentService().getWriter(destinationNode, ContentModel.PROP_CONTENT,
                    true);

            writer.setEncoding(actionedUponContentReader.getEncoding());
            writer.setMimetype(FILE_MIMETYPE);
            writer.putContent(file);
            file.delete();

            //if useAspect is true, store some additional info about the signature in the props
            if (useAspect) {
                serviceRegistry.getNodeService().addAspect(destinationNode, PDFToolkitModel.ASPECT_ENCRYPTED,
                        new HashMap<QName, Serializable>());
                serviceRegistry.getNodeService().setProperty(destinationNode, PDFToolkitModel.PROP_ENCRYPTIONDATE,
                        new java.util.Date());
                serviceRegistry.getNodeService().setProperty(destinationNode, PDFToolkitModel.PROP_ENCRYPTEDBY,
                        AuthenticationUtil.getRunAsUser());
            }

        } catch (IOException e) {
            throw new AlfrescoRuntimeException(e.getMessage(), e);
        } catch (DocumentException e) {
            throw new AlfrescoRuntimeException(e.getMessage(), e);
        } finally {
            if (tempDir != null) {
                try {
                    tempDir.delete();
                } catch (Exception ex) {
                    throw new AlfrescoRuntimeException(ex.getMessage(), ex);
                }
            }

            if (stamp != null) {
                try {
                    stamp.close();
                } catch (Exception ex) {
                    throw new AlfrescoRuntimeException(ex.getMessage(), ex);
                }
            }
        }
    }

    /**
     * Build the permissions mask for iText
     * 
     * @param options
     * @return
     */
    private int buildPermissionMask(Map<String, Object> options) {
        int permissions = 0;

        if ((Boolean) options.get(PARAM_ALLOW_PRINT)) {
            permissions = permissions | PdfWriter.ALLOW_PRINTING;
        }
        if ((Boolean) options.get(PARAM_ALLOW_COPY)) {
            permissions = permissions | PdfWriter.ALLOW_COPY;
        }
        if ((Boolean) options.get(PARAM_ALLOW_CONTENT_MODIFICATION)) {
            permissions = permissions | PdfWriter.ALLOW_MODIFY_CONTENTS;
        }
        if ((Boolean) options.get(PARAM_ALLOW_ANNOTATION_MODIFICATION)) {
            permissions = permissions | PdfWriter.ALLOW_MODIFY_ANNOTATIONS;
        }
        if ((Boolean) options.get(PARAM_ALLOW_SCREEN_READER)) {
            permissions = permissions | PdfWriter.ALLOW_SCREENREADERS;
        }
        if ((Boolean) options.get(PARAM_ALLOW_DEGRADED_PRINT)) {
            permissions = permissions | PdfWriter.ALLOW_DEGRADED_PRINTING;
        }
        if ((Boolean) options.get(PARAM_ALLOW_ASSEMBLY)) {
            permissions = permissions | PdfWriter.ALLOW_ASSEMBLY;
        }
        if ((Boolean) options.get(PARAM_ALLOW_FORM_FILL)) {
            permissions = permissions | PdfWriter.ALLOW_FILL_IN;
        }

        return permissions;
    }
}