org.silverpeas.applicationbuilder.WriteOnlyArchive.java Source code

Java tutorial

Introduction

Here is the source code for org.silverpeas.applicationbuilder.WriteOnlyArchive.java

Source

/**
 * Copyright (C) 2000 - 2012 Silverpeas
 *
 * This program 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.
 *
 * As a special exception to the terms and conditions of version 3.0 of the GPL, you may
 * redistribute this Program in connection with Free/Libre Open Source Software ("FLOSS")
 * applications as described in Silverpeas's FLOSS exception. You should have received a copy of the
 * text describing the FLOSS exception, and it is also available here:
 * "http://www.silverpeas.org/docs/core/legal/floss_exception.html"
 *
 * This program 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 this program.
 * If not, see <http://www.gnu.org/licenses/>.
 */
package org.silverpeas.applicationbuilder;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

import org.apache.commons.io.IOUtils;
import org.silverpeas.util.Console;

/**
 * Convenient class for building archive
 *
 * @author Silverpeas
 * @version 1.0/B
 * @since 1.0/B
 */
public class WriteOnlyArchive extends ApplicationBuilderItem {

    protected Console console;
    protected static final String MANIFEST_PATH = "META-INF" + File.separator + "MANIFEST.MF";
    private Set<String> alreadyAddedDirs = new HashSet<String>();
    private Map<String, String> alreadyAddedFiles = new HashMap<String, String>();
    private JarOutputStream jarOut = null;

    /**
     * Builder for a write only archive.
     *
     * @param directory The absolute path to the directory hosting the archive
     * @param fileName The name of the archive in the file system
     * @since 1.0
     */
    public WriteOnlyArchive(File directory, String fileName, Console sonsole) throws AppBuilderException {
        super(directory, fileName);
        this.console = console;
        setOutputStream();
    }

    /**
     * Adds an XML file in the archive by the means of streams.
     *
     * @param xmlDoc the XML document to add in the archive
     * @since 1.0
     * @roseuid 3AAF4D630303
     */
    public void add(XmlDocument xmlDoc) throws AppBuilderException {
        try {
            addDirectory(xmlDoc.getLocation());
            ZipEntry entry = getNormalizedEntry(xmlDoc.getArchivePath());
            entry.setSize(xmlDoc.getDocumentSize());
            jarOut.putNextEntry(entry);
            xmlDoc.saveTo(getOutputStream());
            getOutputStream().flush();
            getOutputStream().closeEntry();
        } catch (Exception e) {
            throw new AppBuilderException(
                    getName() + " : impossible to add the document \"" + xmlDoc.getArchivePath() + '"', e);
        }
    }

    /**
     * Adds an entry to the archive. The entry added is fetched from the file system
     *
     * @param entry the file to add
     * @since 1.0
     * @roseuid 3AAF55F2017D
     */
    public void add(ApplicationBuilderItem entry) throws AppBuilderException {
        try {
            add(entry, entry.getPath().toURI().toURL().openStream());
        } catch (MalformedURLException mue) {
            throw new AppBuilderException(getName() + " : could not add \"" + entry.getName() + '"', mue);
        } catch (IOException ioe) {
            throw new AppBuilderException(getName() + " : could not add \"" + entry.getName() + '"', ioe);
        }
    }

    /**
     * Merges an archive with this archive.
     *
     * @param archive the archive to merge
     * @since 1.0
     */
    public void mergeWith(ReadOnlyArchive archive) throws AppBuilderException {
        mergeWith(archive, (Set) null);
    }

    /**
     * Merges an archive with this archive filtering the entries to exclude one of them.
     *
     * @param archive the archive to merge
     * @param entryToExclude the entry to exclude from merge. Contains the archive path of the entry
     * to exclude.
     * @since 1.0
     */
    public void mergeWith(ReadOnlyArchive archive, String entryToExclude) throws AppBuilderException {
        Set<String> excludeSet = new HashSet<String>(1);
        excludeSet.add(entryToExclude);
        mergeWith(archive, excludeSet);
    }

    /**
     * Merges an archive with this archive filtering the entries to exclude some of them.
     *
     * @param archive the archive to merge
     * @param entriesToExclude the entries to exclude from merge. Contains the archive paths of the
     * entries to exclude.
     * @throws AppBuilderException
     */
    public void mergeWith(ReadOnlyArchive archive, Set<String> entriesToExclude) throws AppBuilderException {
        ApplicationBuilderItem[] entries = archive.getEntries();
        boolean filterOn = ((entriesToExclude != null) && (!entriesToExclude.isEmpty()));
        for (ApplicationBuilderItem myEntry : entries) {
            if (!filterOn || !entriesToExclude.contains(myEntry.getArchivePath())) {
                if (alreadyAddedFiles.containsKey(myEntry.getArchivePath())) {
                    console.printMessage(
                            getName() + " : already added from \"" + alreadyAddedFiles.get(myEntry.getArchivePath())
                                    + "\" : \"" + archive.getName() + '!' + myEntry.getArchivePath() + "\" ");
                } else {
                    alreadyAddedFiles.put(myEntry.getArchivePath(), archive.getName());
                    InputStream contents = archive.getEntry(myEntry);
                    try {
                        add(myEntry, contents);
                    } finally {
                        IOUtils.closeQuietly(contents);
                    }
                }
            }
        }
    }

    /**
     * When all entries have been added, call this method to close the archive
     *
     * @roseuid 3AB1EAFE02FD
     */
    public void close() throws AppBuilderException {
        try {
            getOutputStream().close();
        } catch (Exception e) {
            throw new AppBuilderException("Impossible to close the stream", e);
        }
    }

    /**
     * Adds a new entry from a stream. The entry is placed and named according to the entry. It can be
     * usefull when merging two archives.
     *
     * @param entry the description of the new entry
     * @param in the stream carrying the contents of the new entry
     * @since 1.0
     */
    public void add(ApplicationBuilderItem entry, InputStream contents) throws AppBuilderException {
        try {
            addDirectory(entry.getLocation());
            ZipEntry destEntry = getNormalizedEntry(entry.getArchivePath());
            destEntry.setSize(entry.getSize());
            getOutputStream().putNextEntry(destEntry);
        } catch (Exception e) {
            throw new AppBuilderException(
                    getName() + " : impossible to create new entry \"" + entry.getArchivePath() + '"', e);
        }
        try {
            IOUtils.copy(contents, getOutputStream());
            contents.close();
            getOutputStream().flush();
            getOutputStream().closeEntry();
        } catch (Exception e) {
            throw new AppBuilderException(
                    getName() + " : impossible to write contents of \"" + entry.getArchivePath() + '"', e);
        } finally {
            IOUtils.closeQuietly(contents);
        }
    }

    private JarOutputStream getOutputStream() {
        return jarOut;
    }

    private void setOutputStream() throws AppBuilderException {
        try {
            OutputStream out = new FileOutputStream(getPath().getAbsolutePath());
            jarOut = new JarOutputStream(out);
            jarOut.setMethod(JarOutputStream.DEFLATED);
        } catch (Exception e) {
            throw new AppBuilderException(getPath().getAbsolutePath() + " : impossible to create", e);
        }
    }

    private void addDirectory(String directory) throws IOException {
        if (directory == null) {
            return;
        }
        if (alreadyAddedDirs.contains(directory)) {
            return;
        }
        if (directory.lastIndexOf(File.separator) != -1) {
            addDirectory(directory.substring(0, directory.lastIndexOf(File.separator)));
        }
        getOutputStream().putNextEntry(getNormalizedEntry(directory + File.separator));
        alreadyAddedDirs.add(directory);
    }

    private ZipEntry getNormalizedEntry(String sysDependantPath) {
        String pathOK = sysDependantPath.replace(File.separatorChar, '/');
        return new ZipEntry(pathOK);
    }
}