Package v7db.files

Source Code of v7db.files.ZipFile$ContentFromZipFile

/**
* Copyright (c) 2011-2012, Thilo Planz. All rights reserved.
*
* 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.
*
* 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 v7db.files;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.lingala.zip4j.core.HeaderReader;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipModel;
import net.lingala.zip4j.unzip.UnzipEngine;

import org.apache.commons.io.IOUtils;

import v7db.files.spi.Content;
import v7db.files.spi.ContentPointer;
import v7db.files.spi.ContentStorage;
import v7db.files.spi.InlineContent;
import v7db.files.spi.StorageScheme;

/**
* Utility to store and index a ZipFile.
* <p>
* In addition to just storing the ZipFile as a whole, references to all the
* contents of all its files are also added to the database (so that if one of
* those is uploaded later separately, it will not take up extra storage).
* <p>
* Cannot be used for files protected by password or otherwise encrypted.
*
*
*/

public class ZipFile {

  public static final class ContentFromZipFile implements StorageScheme {

    public Content getContent(ContentStorage storage,
        Map<String, Object> data) throws IOException {
      byte[] base = MapUtils.getRequiredBytes(data, "base.sha");
      long offset = MapUtils.getRequiredLong(data, "off");
      long length = MapUtils.getRequiredLong(data, "end") - offset;
      byte[] unzipped = IOUtils.toByteArray(Compression.unzip(storage
          .getContent(base).getInputStream(offset, length)));
      return new InlineContent(unzipped);
    }

    public String getId() {
      return "zip";
    }

  }

  /**
   * index all individual files found in a zip archive already in storage
   *
   * @throws IOException
   */
  public static final void index(ContentStorage storage,
      ContentPointer zipFile) throws IOException {
    Content zip = storage.getContent(zipFile);
    if (zip == null)
      throw new IllegalArgumentException("invalid ContentPointer "
          + zipFile);

    File tmp = File.createTempFile("v7files_zipfile_extractfile_", ".zip");
    try {
      OutputStream f = new FileOutputStream(tmp);
      IOUtils.copy(zip.getInputStream(), f);
      f.close();

      // open up the zip file
      HeaderReader r = new HeaderReader(new RandomAccessFile(tmp, "r"));
      ZipModel model = r.readAllHeaders();
      model.setZipFile(tmp.getAbsolutePath());
      Map<String, Object> map = zipFile.serialize();
      List<?> fhs = model.getCentralDirectory().getFileHeaders();
      for (Object _fh : fhs) {
        FileHeader fh = (FileHeader) _fh;
        UnzipEngine en = new UnzipEngine(model, fh);
        // this will read the local file header
        en.getInputStream();
        LocalFileHeader lh = en.getLocalFileHeader();

        store(storage, map, fh, lh);

      }

    } catch (ZipException e) {
      throw new IllegalArgumentException(
          "ContentPointer does not refer to a zip file: " + zipFile,
          e);
    } finally {
      tmp.delete();
    }

  }

  /**
   * find the data indicated by the ContentPointer, treats it as a zip
   * archive, extracts the named file inside the archive, stores a reference
   * to it in the ContentStorage and returns a ContentPointer to it.
   *
   * @throws FileNotFoundException
   *             if the archive exists, but does not contain the named file
   * @throws IllegalArgumentException
   *             if the ContentPointer does not refer to a zip archive
   *
   */
  public static final ContentPointer extractFile(ContentStorage storage,
      ContentPointer zipFile, String fileName) throws IOException {
    Content zip = storage.getContent(zipFile);
    if (zip == null)
      throw new IllegalArgumentException("invalid ContentPointer "
          + zipFile);

    File tmp = File.createTempFile("v7files_zipfile_extractfile_", ".zip");
    try {
      OutputStream f = new FileOutputStream(tmp);
      IOUtils.copy(zip.getInputStream(), f);
      f.close();

      // open up the zip file
      HeaderReader r = new HeaderReader(new RandomAccessFile(tmp, "r"));
      ZipModel model = r.readAllHeaders();
      model.setZipFile(tmp.getAbsolutePath());

      List<?> fhs = model.getCentralDirectory().getFileHeaders();
      for (Object _fh : fhs) {
        FileHeader fh = (FileHeader) _fh;
        if (fileName.equals(fh.getFileName())) {
          UnzipEngine en = new UnzipEngine(model, fh);
          // this will read the local file header
          en.getInputStream();
          LocalFileHeader lh = en.getLocalFileHeader();
          return store(storage, zipFile.serialize(), fh, lh);
        }

      }

    } catch (ZipException e) {
      throw new IllegalArgumentException(
          "ContentPointer does not refer to a zip file: " + zipFile,
          e);
    } finally {
      tmp.delete();
    }
    throw new FileNotFoundException("ContentPointer does not contain "
        + fileName + ": " + zipFile);
  }

  private static ContentPointer store(ContentStorage storage,
      Map<String, Object> zipFile, FileHeader fh, LocalFileHeader lh)
      throws IOException {
    Map<String, Object> cat = new HashMap<String, Object>();
    cat.put("store", "zip");
    cat.put("base", zipFile);
    cat.put("off", fh.getOffsetLocalHeader());
    cat.put("length", fh.getUncompressedSize());
    cat.put("end", lh.getOffsetStartOfData() + lh.getCompressedSize());
    return storage.storeContent(cat);
  }

}
TOP

Related Classes of v7db.files.ZipFile$ContentFromZipFile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.