org.alfresco.repo.exporter.ACPExportPackageHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.repo.exporter.ACPExportPackageHandler.java

Source

/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.repo.exporter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.Path.ChildAssocElement;
import org.alfresco.service.cmr.view.ExportPackageHandler;
import org.alfresco.service.cmr.view.ExporterException;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.UnicodeExtraFieldPolicy;

/**
 * Handler for exporting Repository to ACP (Alfresco Content Package) file
 * 
 * @author David Caruana
 */
public class ACPExportPackageHandler implements ExportPackageHandler {
    /** ACP File Extension */
    public final static String ACP_EXTENSION = "acp";

    protected MimetypeService mimetypeService;
    protected NodeService nodeService;
    protected OutputStream outputStream;
    protected File dataFile;
    protected File contentDir;
    protected File tempDataFile;
    protected OutputStream tempDataFileStream;
    protected ZipArchiveOutputStream zipStream;
    protected int iFileCnt = 0;
    protected boolean exportAsFolders;

    /**
     * Construct
     * 
     * @param destDir File
     * @param zipFile File
     * @param dataFile File
     * @param contentDir File
     * @param overwrite boolean
     * @param mimetypeService MimetypeService
     */
    public ACPExportPackageHandler(File destDir, File zipFile, File dataFile, File contentDir, boolean overwrite,
            MimetypeService mimetypeService) {
        try {
            // Ensure ACP file has appropriate ACP extension
            String zipFilePath = zipFile.getPath();
            if (!zipFilePath.endsWith("." + ACP_EXTENSION)) {
                zipFilePath += (zipFilePath.charAt(zipFilePath.length() - 1) == '.') ? ACP_EXTENSION
                        : "." + ACP_EXTENSION;
            }

            File absZipFile = new File(destDir, zipFilePath);
            log("Exporting to package zip file " + absZipFile.getAbsolutePath());

            if (absZipFile.exists()) {
                if (overwrite == false) {
                    throw new ExporterException(
                            "Package zip file " + absZipFile.getAbsolutePath() + " already exists.");
                }
                log("Warning: Overwriting existing package zip file " + absZipFile.getAbsolutePath());
            }

            this.outputStream = new FileOutputStream(absZipFile);
            this.dataFile = dataFile;
            this.contentDir = contentDir;
            this.mimetypeService = mimetypeService;
        } catch (FileNotFoundException e) {
            throw new ExporterException("Failed to create zip file", e);
        }
    }

    /**
     * Construct
     * 
     * @param outputStream OutputStream
     * @param dataFile File
     * @param contentDir File
     * @param mimetypeService MimetypeService
     */
    public ACPExportPackageHandler(OutputStream outputStream, File dataFile, File contentDir,
            MimetypeService mimetypeService) {
        this.outputStream = outputStream;
        this.dataFile = dataFile;
        this.contentDir = contentDir;
        this.mimetypeService = mimetypeService;
    }

    /**
     * @param nodeService NodeService
     */
    public void setNodeService(NodeService nodeService) {
        this.nodeService = nodeService;
    }

    /**
     * Export content into folder structure of nodes
     * 
     * @param exportAsFolders boolean
     */
    public void setExportAsFolders(boolean exportAsFolders) {
        this.exportAsFolders = exportAsFolders;
    }

    /* (non-Javadoc)
     * @see org.alfresco.service.cmr.view.ExportPackageHandler#startExport()
     */
    public void startExport() {
        // ALF-2016
        zipStream = new ZipArchiveOutputStream(outputStream);
        // NOTE: This encoding allows us to workaround bug...
        //       http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4820807
        zipStream.setEncoding("UTF-8");
        zipStream.setCreateUnicodeExtraFields(UnicodeExtraFieldPolicy.ALWAYS);
        zipStream.setUseLanguageEncodingFlag(true);
        zipStream.setFallbackToUTF8(true);
        zipStream.setUseZip64(Zip64Mode.Always);
    }

    /* (non-Javadoc)
     * @see org.alfresco.service.cmr.view.ExportPackageHandler#createDataStream()
     */
    public OutputStream createDataStream() {
        tempDataFile = TempFileProvider.createTempFile("exportDataStream", ".xml");
        try {
            tempDataFileStream = new FileOutputStream(tempDataFile);
            return tempDataFileStream;
        } catch (FileNotFoundException e) {
            throw new ExporterException("Failed to create data file stream", e);
        }
    }

    /* (non-Javadoc)
     * @see org.alfresco.service.cmr.view.ExportStreamHandler#exportStream(java.io.InputStream)
     */
    public ContentData exportContent(InputStream content, ContentData contentData) {
        // if the content stream to output is empty, then just return content descriptor as is
        if (content == null) {
            return contentData;
        }

        // create zip entry for stream to export
        String contentDirPath = contentDir.getPath();
        if (contentDirPath.charAt(contentDirPath.length() - 1) != '.' && contentDirPath.lastIndexOf('.') != -1) {
            contentDirPath = contentDirPath.substring(0, contentDirPath.lastIndexOf("."));
        }

        File file;
        if (exportAsFolders && nodeService != null && contentData instanceof NodeContentData) {
            NodeContentData nodeContentData = (NodeContentData) contentData;
            file = new File(contentDirPath + toDisplayPath(nodeService.getPath(nodeContentData.getNodeRef())));
        } else {
            String extension = "bin";
            if (mimetypeService != null) {
                String mimetype = contentData.getMimetype();
                if (mimetype != null && mimetype.length() > 0) {
                    try {
                        extension = mimetypeService.getExtension(mimetype);
                    } catch (AlfrescoRuntimeException e) {
                        // use default extension
                    }
                }
            }
            file = new File(contentDirPath, "content" + iFileCnt++ + "." + extension);
        }

        try {
            // ALF-2016
            ZipArchiveEntry zipEntry = new ZipArchiveEntry(file.getPath());
            zipStream.putArchiveEntry(zipEntry);

            // copy export stream to zip
            copyStream(zipStream, content);
        } catch (IOException e) {
            throw new ExporterException("Failed to zip export stream", e);
        }

        return new ContentData(file.getPath(), contentData.getMimetype(), contentData.getSize(),
                contentData.getEncoding());
    }

    /* (non-Javadoc)
     * @see org.alfresco.service.cmr.view.ExportPackageHandler#endExport()
     */
    public void endExport() {
        // ensure data file has .xml extension
        String dataFilePath = dataFile.getPath();
        if (!dataFilePath.endsWith(".xml")) {
            dataFilePath += (dataFilePath.charAt(dataFilePath.length() - 1) == '.') ? "xml" : ".xml";
        }

        // add data file to zip stream
        // ALF-2016
        ZipArchiveEntry zipEntry = new ZipArchiveEntry(dataFilePath);

        try {
            // close data file stream and place temp data file into zip output stream
            tempDataFileStream.close();
            // ALF-2016
            zipStream.putArchiveEntry(zipEntry);
            InputStream dataFileStream = new FileInputStream(tempDataFile);
            copyStream(zipStream, dataFileStream);
            // ALF-2016
            zipStream.closeArchiveEntry();
            dataFileStream.close();
        } catch (IOException e) {
            throw new ExporterException("Failed to zip data stream file", e);
        }

        try {
            // close zip stream
            zipStream.close();
        } catch (IOException e) {
            throw new ExporterException("Failed to close zip package stream", e);
        }
    }

    /**
     * Log Export Message
     * 
     * @param message  message to log
     */
    protected void log(String message) {
    }

    /**
     * Copy input stream to output stream
     * 
     * @param output  output stream
     * @param in  input stream
     * @throws IOException
     */
    private void copyStream(OutputStream output, InputStream in) throws IOException {
        byte[] buffer = new byte[2048 * 10];
        int read = in.read(buffer, 0, 2048 * 10);
        while (read != -1) {
            output.write(buffer, 0, read);
            read = in.read(buffer, 0, 2048 * 10);
        }
    }

    /**
     * @param path Path
     * @return  display path
     */
    private String toDisplayPath(Path path) {
        StringBuffer displayPath = new StringBuffer();
        if (path.size() == 1) {
            displayPath.append("/");
        } else {
            for (int i = 1; i < path.size(); i++) {
                Path.Element element = path.get(i);
                if (element instanceof ChildAssocElement) {
                    ChildAssociationRef assocRef = ((ChildAssocElement) element).getRef();
                    NodeRef node = assocRef.getChildRef();
                    displayPath.append("/");
                    displayPath.append(nodeService.getProperty(node, ContentModel.PROP_NAME));
                }
            }
        }
        return displayPath.toString();
    }

}