org.structr.web.function.CreateArchiveFunction.java Source code

Java tutorial

Introduction

Here is the source code for org.structr.web.function.CreateArchiveFunction.java

Source

/**
 * Copyright (C) 2010-2018 Structr GmbH
 *
 * This file is part of Structr <http://structr.org>.
 *
 * Structr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Structr 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Structr.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.structr.web.function;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.structr.common.error.FrameworkException;
import org.structr.core.app.StructrApp;
import org.structr.schema.ConfigurationProvider;
import org.structr.schema.action.ActionContext;
import org.structr.web.common.FileHelper;
import org.structr.web.entity.AbstractFile;
import org.structr.web.entity.File;
import org.structr.web.entity.Folder;

public class CreateArchiveFunction extends UiFunction {

    public static final String ERROR_MESSAGE_CREATE_ARCHIVE = "Usage: ${create_archive(archiveFileName, files [, CustomFileType])}. Example: ${create_archive(\"archive\", find(\"File\"))}";
    public static final String ERROR_MESSAGE_CREATE_ARCHIVE_JS = "Usage: ${{Structr.createArchive(archiveFileName, files [, CustomFileType])}}. Example: ${{Structr.createArchive(\"archive\", Structr.find(\"File\"))}}";

    @Override
    public String getName() {
        return "archive()";
    }

    @Override
    public Object apply(ActionContext ctx, Object caller, Object[] sources) throws FrameworkException {

        if (!(sources[1] instanceof File || sources[1] instanceof Folder || sources[1] instanceof Collection
                || sources.length < 2)) {

            logParameterError(caller, sources, ctx.isJavaScriptContext());

            return usage(ctx.isJavaScriptContext());
        }

        final ConfigurationProvider config = StructrApp.getConfiguration();

        try {

            java.io.File newArchive = java.io.File.createTempFile(sources[0].toString(), "zip");

            ZipArchiveOutputStream zaps = new ZipArchiveOutputStream(newArchive);
            zaps.setEncoding("UTF8");
            zaps.setUseLanguageEncodingFlag(true);
            zaps.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.ALWAYS);
            zaps.setFallbackToUTF8(true);

            if (sources[1] instanceof File) {

                File file = (File) sources[1];
                addFileToZipArchive(file.getProperty(AbstractFile.name), file, zaps);

            } else if (sources[1] instanceof Folder) {

                Folder folder = (Folder) sources[1];
                addFilesToArchive(folder.getProperty(Folder.name) + "/", folder.getFiles(), zaps);
                addFoldersToArchive(folder.getProperty(Folder.name) + "/", folder.getFolders(), zaps);

            } else if (sources[1] instanceof Collection) {

                for (Object fileOrFolder : (Collection) sources[1]) {

                    if (fileOrFolder instanceof File) {

                        File file = (File) fileOrFolder;
                        addFileToZipArchive(file.getProperty(AbstractFile.name), file, zaps);
                    } else if (fileOrFolder instanceof Folder) {

                        Folder folder = (Folder) fileOrFolder;
                        addFilesToArchive(folder.getProperty(Folder.name) + "/", folder.getFiles(), zaps);
                        addFoldersToArchive(folder.getProperty(Folder.name) + "/", folder.getFolders(), zaps);
                    } else {

                        logParameterError(caller, sources, ctx.isJavaScriptContext());
                        return usage(ctx.isJavaScriptContext());
                    }
                }
            } else {

                logParameterError(caller, sources, ctx.isJavaScriptContext());
                return usage(ctx.isJavaScriptContext());
            }

            zaps.close();

            Class archiveClass = null;

            if (sources.length > 2) {

                archiveClass = config.getNodeEntityClass(sources[2].toString());

            }

            if (archiveClass == null) {

                archiveClass = org.structr.web.entity.File.class;
            }

            try (final FileInputStream fis = new FileInputStream(newArchive)) {
                return FileHelper.createFile(ctx.getSecurityContext(), fis, "application/zip", archiveClass,
                        sources[0].toString() + ".zip");
            }

        } catch (IOException e) {

            logException(caller, e, sources);
        }
        return null;
    }

    @Override
    public String usage(boolean inJavaScriptContext) {

        return (inJavaScriptContext ? ERROR_MESSAGE_CREATE_ARCHIVE_JS : ERROR_MESSAGE_CREATE_ARCHIVE);
    }

    @Override
    public String shortDescription() {

        return "Packs the given files and folders into zipped archive.";
    }

    private void addFileToZipArchive(String path, File file, ArchiveOutputStream aps) throws IOException {

        logger.info("Adding File \"{}\" to new archive...", path);

        ZipArchiveEntry entry = new ZipArchiveEntry(path);
        aps.putArchiveEntry(entry);

        try (final InputStream in = file.getInputStream()) {

            IOUtils.copy(in, aps);
        }

        aps.closeArchiveEntry();
    }

    private void addFilesToArchive(String path, Iterable<File> list, ArchiveOutputStream aps) throws IOException {

        for (File fileForArchive : list) {

            addFileToZipArchive(path + fileForArchive.getProperty(AbstractFile.name), fileForArchive, aps);
        }
    }

    private void addFoldersToArchive(String path, Iterable<Folder> list, ArchiveOutputStream aps)
            throws IOException {

        for (Folder folder : list) {

            addFilesToArchive(path + folder.getProperty(Folder.name) + "/", folder.getFiles(), aps);
            addFoldersToArchive(path + folder.getProperty(Folder.name) + "/", folder.getFolders(), aps);
        }
    }
}