Package com.mattc.argus.concurrent

Source Code of com.mattc.argus.concurrent.ZipProcess

  /*Argus -- A Zip Installer for Circumventing Common Educational Web Blocks
    Copyright (C) 2014 Matthew Crocco

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

package com.mattc.argus.concurrent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.ZipException;




//Apache Commons accounts much better for LARGE Zip Archives
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;

import com.mattc.argus.Notifications;
import com.mattc.argus.util.Console;
import com.mattc.argus.util.Utility;

/**
*
* Thread to manage Unzipping Zip Archives in an Appropriate Manner. <br />
* <br />
* Unzip's Archives using a Buffer to accelerate extraction speeds to far beyond <br />
* what is found on most secondary school computers. <br />
* <br />
* Threaded to Allow Multiple Extractions at Once
*
* @author Matthew Crocco
*/
public class ZipProcess implements DecompressProcess{

  /**Determined Appropriate Buffer Size*/
  public final int BUFFER_SIZE;

  private final File zipFile;            //Zip Archive to Extract
  private final File destDir;            //Root Destination Directory
  private ZipFile zip;
  private FileOutputStream fos;          //Output Stream to Extract With
  private final byte[] buffer;          //Allocation Buffer
  private final AtomicBoolean running;      //Thread Monitor Value
 
  public ZipProcess(File zipFile, String dest){
    this(zipFile, new File(dest));
  }
 
  public ZipProcess(File zipFile, File destDir){
    if(!zipFile.exists()) throw new IllegalArgumentException("The desired ZipFile Does Not Exist");
    if(!destDir.exists()){
      destDir.mkdirs();
    }
   
    //Get Buffer Size and Create Byte Buffer
    BUFFER_SIZE = 8192;         //Standard Cache Size
    buffer = new byte[BUFFER_SIZE];
    this.destDir = destDir;
    this.zipFile = zipFile;
   
    running = new AtomicBoolean(false);
  }
 
  public void run(){
    running.set(true);
   
    //Zip Archive Entry Input Stream
    InputStream zis = null;
   
    try{

      zip = new ZipFile(zipFile);
      ZipArchiveEntry entry;
      Enumeration<ZipArchiveEntry> entries;
     
      entries = zip.getEntriesInPhysicalOrder();
     
      //While there are still Entries to process, iterate
      while(entries.hasMoreElements()){
        entry = entries.nextElement();
        //Create the Empty File to Extract to and its Parent Directory
        //Notify Console and ProgressLog that a File is Being Extracted
        File destination = new File(destDir, entry.getName());
        File dirs = new File(destination.getParent());
        dirs.mkdirs();
        Console.info("EXT: " + Utility.relativizePath(destination, destDir.getParentFile()));
        Notifications.updateLog("Extracting " + destination.getName() + (entry.isDirectory() ? " as Directory" : " as File") +"...");
       
        /*
         * IMPORTANT
         *
         * Ensures that All Files have a Directory to go to.
         *
         * If a Folder is for some reason created as a File, this will
         * detect that. It will delete the file and re-create it as a Directory
         * so that installation can continue.
         *
         * If all else fails, print debug information and stop extracting.
         * It is unlikely the installed application will work without all files
         * being extracted.
         */
        try{
          if(!destination.getParentFile().isDirectory()){
            destination.getParentFile().delete();
            destination.getParentFile().mkdirs();
          }
          destination.createNewFile();
        }catch(IOException e){
          String errMsg = "Failure to Extract " + zipFile.getName();
          String errPath = "PATH = " + destination.getCanonicalPath();
          String errParent = "PARENT = " + destination.getParentFile().getCanonicalPath();
          String errIsDir = "PARENT_IS_DIRECTORY = " + destination.getParentFile().isDirectory();
         
          //Standard IO Error Information
          e.printStackTrace(System.err);
          System.err.println(errMsg);
          System.err.println(errPath);
          System.err.println(errParent);
          System.err.println(errIsDir);
         
          //Log File Error Information (Possibly Standard IO if DEBUG = True)
          Console.exception(e);
          Console.error(errMsg);
          Console.error(errPath);
          Console.error(errParent);
          Console.error(errIsDir);
         
          //GUI Error Information. For End User.
          String msg = errMsg + "\n" + errPath + "\n" + errParent + "\n" + errIsDir;
          Notifications.exception(msg, e);
         
          //Attempt to Delete the Partially Unzipped and Non-functional install Directory
          if(!Utility.deleteDirectory(destDir)){
            Console.error("Although extraction failed, the erroneous directory could not be removed!");
            Notifications.error("Failure to Delete Partially Unzipped Directory!");
          }else
            Console.info("Erroneous Directory Deleted Successfully!");
         
        }
       
       
        //Establish a Stream to output data to the destination file
        zis = zip.getInputStream(entry);
        fos = new FileOutputStream(destination);
       
        //Read Zip Entry data into buffer, output buffer to installation file
        for(int c = zis.read(buffer); c > 0; c = zis.read(buffer))
          fos.write(buffer, 0, c);
       
        //Close Current Entry and Destination OutputStream
        zis.close();
        fos.close();
      }
    }catch(ZipException e){
      Console.exception(e);
    }catch(IOException e){
      Console.exception(e);
    }finally{    //Ensure that All Streams Are Closed to prevent Memory Leaks
      Utility.closeStream(zis);
      Utility.closeStream(fos);
      Utility.closeStream(zip);
      running.set(false);
    }
  }
 
  public boolean isRunning(){
    return running.get();
  }

  public String getArchiveName() {
    return zipFile.getName();
  }

  public String getDestination() {
    return destDir.getAbsolutePath();
  }
}
TOP

Related Classes of com.mattc.argus.concurrent.ZipProcess

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.