Package org.molgenis.util

Source Code of org.molgenis.util.TarGz

package org.molgenis.util;

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.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.io.FileUtils;

import com.ice.tar.InvalidHeaderException;
import com.ice.tar.TarArchive;
import com.ice.tar.TarBuffer;
import com.ice.tar.TarEntry;

public class TarGz
{

  public static File tarDir(File dir) throws IOException
  {
    File archiveLocation = new File(dir.getParentFile() + File.separator + dir.getName() + ".tar.gz");

    boolean unixArchiveFormat = true;

    TarArchive archive = null;

    OutputStream outStream = System.out;

    if (outStream != null)
    {

      try
      {
        outStream = new GZIPOutputStream(new FileOutputStream(archiveLocation));
      }
      catch (IOException ex)
      {
        outStream = null;
        ex.printStackTrace(System.err);
      }

      archive = new TarArchive(outStream, TarBuffer.DEFAULT_BLKSIZE);
    }

    // write

    File[] files = dir.listFiles();
    for (File file : files)
    {
      if (!file.isDirectory())
      {
        // make regular entry
        TarEntry entry = new TarEntry(file);
        if (unixArchiveFormat)
        {
          entry.setUnixTarFormat();
        }
        else
        {
          entry.setUSTarFormat();
        }
        // FIXME: index -1 wanneer verkeerde file sep!
        entry.setName(entry.getName().substring(entry.getName().lastIndexOf("/") + 1, entry.getName().length()));

        // add to tar. just a file, no need for recursion ('false')
        archive.writeEntry(entry, false);

      }
      else
      {
        // entry is a directory, so tar the content :)
        TarEntry entry = new TarEntry(TarGz.tarDir(file));

        if (unixArchiveFormat)
        {
          entry.setUnixTarFormat();
        }
        else
        {
          entry.setUSTarFormat();
        }
        // FIXME: index -1 wanneer verkeerde file sep!
        entry.setName(entry.getName().substring(entry.getName().lastIndexOf("/") + 1, entry.getName().length()));

        // write entry (now a tar) to tar
        archive.writeEntry(entry, false);
      }
    }

    // close
    if (archive != null) // CLOSE ARCHIVE
    {
      try
      {
        archive.closeArchive();
      }
      catch (IOException ex)
      {
        ex.printStackTrace(System.err);
      }
    }

    return archiveLocation;

  }

  /**
   *
   * @param archive
   * @param extractDir
   * @param keepNested
   *            Extract nested tar.gz files as usual, but do not attempt to
   *            delete the nested tar.gz files after extraction. This was
   *            added because MS Windows machines do not always have
   *            permission to delete these files, causing failed regression
   *            tests for no good reason. Default call is and should be
   *            'false'.
   * @return
   * @throws InvalidHeaderException
   * @throws IOException
   * @throws InterruptedException
   */
  private static File tarExtract(File archive, File extractDir, boolean nested, List<File> markedDeleted)
      throws InvalidHeaderException, IOException, InterruptedException
  {
    InputStream inStream = System.in;

    try
    {
      inStream = new FileInputStream(archive);
    }
    catch (IOException ex)
    {
      inStream = null;
      ex.printStackTrace(System.err);
    }
    return tarExtract(inStream, extractDir, nested, markedDeleted);

  }

  /**
   *
   * @param inStream
   *            = the inputstream from a file
   * @param extractDir
   * @param keepNested
   *            Extract nested tar.gz files as usual, but do not attempt to
   *            delete the nested tar.gz files after extraction. This was
   *            added because MS Windows machines do not always have
   *            permission to delete these files, causing failed regression
   *            tests for no good reason. Default call is and should be
   *            'false'.
   * @return
   * @throws InvalidHeaderException
   * @throws IOException
   * @throws InterruptedException
   */
  private static File tarExtract(InputStream inStream, File extractDir, boolean nested, List<File> markedDeleted)
      throws InvalidHeaderException, IOException, InterruptedException
  // private static File tarExtract(File archive, File extractDir, boolean
  // nested) throws InvalidHeaderException, IOException
  {
    if (!extractDir.exists())
    {
      extractDir.mkdir();
    }
    else
    {
      FileUtils.cleanDirectory(extractDir);
    }

    TarArchive tarchive = null;

    if (inStream != null)
    {
      try
      {
        inStream = new GZIPInputStream(inStream);
      }
      catch (IOException ex)
      {
        inStream = null;
        ex.printStackTrace(System.err);
      }

      tarchive = new TarArchive(inStream, TarBuffer.DEFAULT_BLKSIZE);
    }

    tarchive.extractContents(extractDir);

    for (File tarGzFile : findTarGzFiles(extractDir))
    {
      File subDir = new File(extractDir.getAbsolutePath() + File.separator
          + tarGzFile.getName().replace(".tar.gz", ""));
      markedDeleted.add(tarGzFile);
      tarExtract(tarGzFile, subDir, true, markedDeleted);
    }

    // When you try to delete it straight away, MS Windows will not delete
    // the file. Now it will.
    if (!nested)
    {
      for (File f : markedDeleted)
      {
        boolean delSuccess = f.delete();
        if (!delSuccess)
        {
          Thread.sleep(10);
          delSuccess = f.delete();
          if (!delSuccess)
          {
            System.out.println("WARNING could not delete " + f.getAbsolutePath());
          }
        }
      }
    }
    return extractDir;
  }

  /**
   * Wrapper for private static File tarExtract(File archive, File extractDir,
   * boolean nested, List<File> markedDeleted). Adds nested = false and empty
   * file list used ONLY in recursion to avoid MS Windows not deleting the
   * appropriate files.
   *
   * @param archive
   * @param extractDir
   * @return
   * @throws InvalidHeaderException
   * @throws IOException
   * @throws InterruptedException
   */
  public static File tarExtract(File archive, File extractDir) throws InvalidHeaderException, IOException,
      InterruptedException
  {
    return tarExtract(archive, extractDir, false, new ArrayList<File>());
  }

  /**
   * Wrapper for private static File tarExtract(InputStream inStream, File
   * extractDir, boolean nested, List<File> markedDeleted). Adds nested =
   * false and empty file list used ONLY in recursion to avoid MS Windows not
   * deleting the appropriate files.
   *
   * @param inStream
   *            = the inputstream from a file
   * @param extractDir
   * @return
   * @throws InvalidHeaderException
   * @throws IOException
   * @throws InterruptedException
   */
  public static File tarExtract(InputStream inStream, File extractDir) throws InvalidHeaderException, IOException,
      InterruptedException
  {
    return tarExtract(inStream, extractDir, false, new ArrayList<File>());
  }

  /**
   * Wrapper for public static File tarExtract(File archive, File extractDir).
   * Adds default extractDir by getting the java tmp dir and archive name.
   *
   * @param archive
   * @param keepNested
   *            Extract nested tar.gz files as usual, but do not attempt to
   *            delete the nested tar.gz files after extraction. This was
   *            added because MS Windows machines do not always have
   *            permission to delete these files, causing failed regression
   *            tests for no good reason. Default call is and should be
   *            'false'.
   * @return
   * @throws InvalidHeaderException
   * @throws IOException
   * @throws InterruptedException
   */
  public static File tarExtract(File archive) throws InvalidHeaderException, IOException, InterruptedException
  {
    String archiveName = archive.getName().substring(0, archive.getName().indexOf("."));
    File extractDir = new File(System.getProperty("java.io.tmpdir") + File.separator + archiveName + "_extract");
    return tarExtract(archive, extractDir);
  }

  /**
   * Wrapper for public static File tarExtract(File archive, File extractDir).
   * Adds default extractDir by getting the java tmp dir and archive name.
   *
   * @param inStream
   *            = the inputstream from a file
   * @param keepNested
   *            Extract nested tar.gz files as usual, but do not attempt to
   *            delete the nested tar.gz files after extraction. This was
   *            added because MS Windows machines do not always have
   *            permission to delete these files, causing failed regression
   *            tests for no good reason. Default call is and should be
   *            'false'.
   * @return
   * @throws InvalidHeaderException
   * @throws IOException
   * @throws InterruptedException
   */
  public static File tarExtract(InputStream inStream) throws InvalidHeaderException, IOException,
      InterruptedException
  {
    String archiveName = "inputstream_" + System.nanoTime();
    File extractDir = new File(System.getProperty("java.io.tmpdir") + File.separator + archiveName + "_extract");
    return tarExtract(inStream, extractDir);
  }

  private static List<File> findTarGzFiles(File dir)
  {
    ArrayList<File> tars = new ArrayList<File>();
    File[] files = dir.listFiles();
    for (File file : files)
    {
      // all dirs should be tarred at this point, but still check
      if (!file.isDirectory())
      {
        // if file is a .tar.gz, add as such
        if (file.getName().endsWith(".tar.gz"))
        {
          tars.add(file);
        }
      }

    }
    return tars;
  }

  /**
   * Based on: http://www.javalobby.org/java/forums/t17036.html Copy source
   * file to destination. If destination is a path then source file name is
   * appended. If destination file exists then: overwrite=true - destination
   * file is replaced; overwite=false - exception is thrown.
   *
   * @param src
   *            source file
   * @param dst
   *            destination file or path
   * @param overwrite
   *            overwrite destination file
   * @exception IOException
   *                I/O problem
   * @exception IllegalArgumentException
   *                illegal argument
   */

  public static void fileCopy(final File src, File dst, final boolean overwrite) throws IOException,
      IllegalArgumentException
  {
    // long startTimer = System.currentTimeMillis();

    // checks
    if (!src.isFile() || !src.exists())
    {
      throw new IllegalArgumentException("Source file '" + src.getAbsolutePath() + "' not found.");
    }

    if (dst.exists())
    {
      if (dst.isDirectory())
      { // Directory? -> use source file name
        dst = new File(dst, src.getName());
      }
      else if (dst.isFile())
      {
        if (!overwrite)
        {
          throw new IllegalArgumentException("Destination file '" + dst.getAbsolutePath()
              + "' already exists.");
        }
      }
      else
      {
        throw new IllegalArgumentException("Invalid destination object '" + dst.getAbsolutePath() + "'.");
      }
    }

    File dstParent = dst.getParentFile();

    if (!dstParent.exists())
    {
      if (!dstParent.mkdirs())
      {
        throw new IOException("Failed to create directory " + dstParent.getAbsolutePath());
      }
    }

    long fileSize = src.length();

    if (fileSize > 20971520l)
    { // for larger files (20Mb) use streams
      FileInputStream in = new FileInputStream(src);
      FileOutputStream out = new FileOutputStream(dst);

      try
      {
        int doneCnt = -1;
        int bufSize = 32768;
        byte buf[] = new byte[bufSize];

        while ((doneCnt = in.read(buf, 0, bufSize)) >= 0)
        {
          if (doneCnt == 0)
          {
            Thread.yield();
          }
          else
          {
            out.write(buf, 0, doneCnt);
          }
        }
        out.flush();
      }

      finally
      {
        in.close();
        out.close();
      }

    }

    else
    { // smaller files, use channels

      FileInputStream fis = new FileInputStream(src);
      FileOutputStream fos = new FileOutputStream(dst);
      FileChannel in = fis.getChannel();
      FileChannel out = fos.getChannel();

      try
      {
        long offs = 0, doneCnt = 0, copyCnt = Math.min(65536, fileSize);
        do
        {
          doneCnt = in.transferTo(offs, copyCnt, out);
          offs += doneCnt;
          fileSize -= doneCnt;
        }
        while (fileSize > 0);
      }

      finally
      { // cleanup
        in.close();
        out.close();
        fis.close();
        fos.close();
      }
    }

    // System.out.println("filecopied " + String.valueOf(src.length() /
    // 1024) + " Kb in " + String.valueOf(System.currentTimeMillis() -
    // startTimer));

  }

}
TOP

Related Classes of org.molgenis.util.TarGz

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.