org.sakaiproject.archive.impl.SiteZipper.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.archive.impl.SiteZipper.java

Source

/***********************************************************************************
 *
 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.
 *
 **********************************************************************************/

package org.sakaiproject.archive.impl;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.api.ServerConfigurationService;

public class SiteZipper {

    private static Log log = LogFactory.getLog(SiteZipper.class);

    protected ServerConfigurationService serverConfigurationService = null;

    public void setServerConfigurationService(ServerConfigurationService service) {
        serverConfigurationService = service;
    }

    /**
     * Unzip a zip file into the unzip directory. Return the NAME of the archive so we can then merge from it. The merger knows the base dir.
     * @param zipFilePath      path to ZIP file
     * @param m_unzipPath      unzip dir for zips
     * @return
     * @throws IOException
     */
    public String unzipArchive(String zipFilePath, String m_unzipPath) throws IOException {

        log.debug("zipFilePath: " + zipFilePath);

        ZipFile zipFile = new ZipFile(zipFilePath);
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();

            //destination file from zip. Straight into the normal archive directory
            File dest = new File(m_unzipPath, entry.getName());
            log.debug("Dest: " + dest.getAbsolutePath());

            if (entry.isDirectory()) {
                //create dir
                dest.mkdir();
            } else {
                //extract contents
                InputStream in = zipFile.getInputStream(entry);
                OutputStream out = new FileOutputStream(dest);
                IOUtils.copy(in, out);
                IOUtils.closeQuietly(in);
                IOUtils.closeQuietly(out);
            }
        }

        //get original filename, remove timestamp, add -archive
        String unzippedArchivePath = StringUtils.substringAfterLast(
                StringUtils.substringBeforeLast(zipFile.getName(), "-") + "-archive", File.separator);

        log.debug("unzippedArchivePath: " + unzippedArchivePath);

        return unzippedArchivePath;

    }

    /**
     * Zip a site archive. It is stored back in the zip directory
     * @param siteId         site that has already been archived
     * @param m_storagePath      path to where the archives are
     * @return
     * @throws IOException
     */
    public boolean zipArchive(String siteId, String m_storagePath) throws IOException {

        //get path to archive dir for this site
        //suffix of -archive is hardcoded as per archive service
        String archivePath = m_storagePath + siteId + "-archive";

        //setup timestamp
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String timestamp = dateFormat.format(Calendar.getInstance().getTime());

        //create path to compressed archive
        String compressedArchivePath = m_storagePath + siteId + "-" + timestamp + ".zip";
        File zipFile = new File(compressedArchivePath);

        if (!zipFile.exists()) {
            log.info("Creating zip file: " + compressedArchivePath);
            zipFile.createNewFile();
        }

        FileOutputStream fOut = null;
        FileInputStream zip = null;
        BufferedOutputStream bOut = null;
        ZipArchiveOutputStream zOut = null;

        try {
            fOut = new FileOutputStream(zipFile);
            bOut = new BufferedOutputStream(fOut);
            zOut = new ZipArchiveOutputStream(bOut);
            addFileToZip(zOut, archivePath, ""); //add the directory which will then add all files recursively

            //create a sha1 hash of the zip
            String hashPath = m_storagePath + siteId + "-" + timestamp + ".sha1";
            log.info("Creating hash: " + hashPath);
            zip = new FileInputStream(compressedArchivePath);
            String hash = DigestUtils.sha1Hex(zip);
            FileUtils.writeStringToFile(new File(hashPath), hash);
        } finally {
            zOut.finish();
            zOut.close();
            bOut.close();
            fOut.close();
            zip.close();
        }

        return true;
    }

    /**
      * Creates a zip entry for the path specified with a name built from the base passed in and the file/directory
      * name. If the path is a directory, a recursive call is made such that the full directory is added to the zip.
      *
      * @param zOut The zip file's output stream
      * @param path The filesystem path of the file/directory being added
      * @param base The base prefix to for the name of the zip file entry
      *
      * @throws IOException If anything goes wrong
      */
    private static void addFileToZip(ZipArchiveOutputStream zOut, String path, String base) throws IOException {
        File f = new File(path);
        String entryName = base + f.getName();
        ZipArchiveEntry zipEntry = new ZipArchiveEntry(f, entryName);

        zOut.putArchiveEntry(zipEntry);

        if (f.isFile()) {
            FileInputStream fInputStream = null;
            try {
                fInputStream = new FileInputStream(f);
                IOUtils.copy(fInputStream, zOut);
                zOut.closeArchiveEntry();
            } finally {
                IOUtils.closeQuietly(fInputStream);
            }

        } else {
            zOut.closeArchiveEntry();
            File[] children = f.listFiles();

            if (children != null) {
                for (File child : children) {
                    addFileToZip(zOut, child.getAbsolutePath(), entryName + "/");
                }
            }
        }
    }

}