Package eu.planets_project.services.utils

Source Code of eu.planets_project.services.utils.ZipUtils

/*******************************************************************************
* Copyright (c) 2007, 2010 The Planets Project Partners.
*
* All rights reserved. This program and the accompanying
* materials are made available under the terms of the
* Apache License, Version 2.0 which accompanies
* this distribution, and is available at
* http://www.apache.org/licenses/LICENSE-2.0
*
*******************************************************************************/
package eu.planets_project.services.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import java.util.zip.ZipException;

import org.apache.commons.io.IOUtils;

import ch.enterag.utils.zip.EntryInputStream;
import ch.enterag.utils.zip.EntryOutputStream;
import ch.enterag.utils.zip.FileEntry;
import ch.enterag.utils.zip.Zip64File;
import eu.planets_project.services.datatypes.Checksum;



public class ZipUtils {
 
  private static Logger log = Logger.getLogger(ZipUtils.class.getName());
 
  /**
   * Creates a Zip64File zip file.
   * @param srcFolder the folder containing the files to be written to the zip
   * @param destFolder the folder to write the Zip file to
   * @param zipName the name the zip file should have. If no zipName is passed, the name of the folder will be used.
   * @param compress true if the file shoukld be compressed, false if not.
   * @return a zip(64) File
   */
  public static File createZip(File srcFolder, File destFolder, String zipName, boolean compress) {
    Zip64File zipFile = null;
   
    if(!srcFolder.isDirectory()) {
      log.severe("[createZip] The File object you have passed is NOT a folder! Nothing has been done, sorry.");
      return null;
    }
   
    if(zipName==null) {
      zipName = srcFolder.getName();
      log.info("[createZip] No zipName specified, using folder name instead: " + zipName);
    }
   
    try {
      File newZip = new File(destFolder, zipName);
      zipFile = new Zip64File(newZip);
      List<String> listOfFiles = listAllFilesAndFolders(srcFolder, new ArrayList<String> ());
      if(listOfFiles.size()==0) {
        log.info("[createZip] Found no files to put in the zip. Created empty Zip file anyway...");
        zipFile.close();
        return new File(zipFile.getDiskFile().getFileName());
      }
      log.info("[createZip] Working on zipFile: " + zipFile.getDiskFile().getFileName());
      log.info("[createZip] Normalizing paths...");
      List<String> normalizedPaths = normalizePaths(srcFolder);
     
      for(int i=0;i<normalizedPaths.size();i++) {
        String currentZipEntryPath = normalizedPaths.get(i);
        FileEntry entry = new FileEntry(currentZipEntryPath);
        File currentFile = new File(listOfFiles.get(i));
       
        writeEntry(zipFile, entry, currentFile, compress);
      }
      log.info("[createZip] All Files written to zip file: " + zipFile.getDiskFile().getFileName());
      zipFile.close();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return new File(zipFile.getDiskFile().getFileName());
  }
 
 
  /**
   * Creates a Zip64File containing all the files in srcFolder and write it to destFolder using the passed zipName.
   * After creating the zip file, a checksum is calculated. 
   * @param srcFolder the folder containing the files to be written to the zip
   * @param destFolder the folder to write the Zip file to
   * @param zipName the name the zip file should have. If no zipName is passed, the name of the folder will be used.
   * @param compress has no effect TODO implement compression
   * @return a ZipResult, containing the zip as a file and the created checksum (MD5)
   */
  public static ZipResult createZipAndCheck(File srcFolder, File destFolder, String zipName, boolean compress) {
    if(zipName==null) {
      zipName = srcFolder.getName();
    }
    File newZipFile = createZip(srcFolder, destFolder, zipName, compress);
    log.info("[createZipAndCheck] Zip file created: " + zipName);
    ZipResult zipResult = new ZipResult();
    try {
      byte[] digest = Checksums.md5(newZipFile);
      zipResult.setZipFile(newZipFile);
      zipResult.setChecksum(new Checksum("MD5", Arrays.toString(digest)));
      log.info("[createZipAndCheck] Checksum (MD5) created: " + zipResult.getChecksum());
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return zipResult;
  }
 
 
  /**
   * Unzips a zip file and writes the contained files to destFolder.
   *
   * @param zipFile the zip file to unpack.
   * @param destFolder the folder to write the extracted files to.
   * @return a List with all extracted files.
   */
  @SuppressWarnings("unchecked")
  public static List<File> unzipTo(File zipFile, File destFolder) {
    List<File> extractedFiles = null;
    try {
      Zip64File zip64File = new Zip64File(zipFile);
     
      List<FileEntry> entries = zip64File.getListFileEntries();
      extractedFiles = new ArrayList<File>();
      for (FileEntry fileEntry : entries) {
       
        File currentFile = readEntry(zip64File, fileEntry, destFolder);
        extractedFiles.add(currentFile);
       
      }
      zip64File.close();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return extractedFiles;
  }
 
  private static void readFileEntry(Zip64File zip64File, FileEntry fileEntry, File destFolder) {
    FileOutputStream fileOut;
    File target = new File(destFolder, fileEntry.getName());
    File targetsParent = target.getParentFile();
    if(targetsParent!=null) {
      targetsParent.mkdirs();
    }
    try {
//      boolean madeFolder = target.createNewFile();
      fileOut = new FileOutputStream(target);
      log.info("[readFileEntry] writing entry: " + fileEntry.getName() + " to file: " + target.getAbsolutePath());
      EntryInputStream entryReader = zip64File.openEntryInputStream(fileEntry.getName());
      IOUtils.copyLarge(entryReader, fileOut);
      entryReader.close();
      fileOut.close();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    catch (ZipException e) {
      log.warning("ATTENTION PLEASE: Some strange, but obviously not serious ZipException occured! Extracted file '" + target.getName() + "' anyway! So don't Panic!" + "\n");
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
 
  private static void readFolderEntry(Zip64File zip64File, FileEntry folderEntry, File dest) {
    log.info("[readFolderEntry] The target you have specified is a folder: " + folderEntry.getName());
    File currentFolder = new File(dest, folderEntry.getName());
    currentFolder.mkdirs();
    List<String> containedFiles = getFileEntryChildren(zip64File, folderEntry);
   
    if(containedFiles.size()>0) {
      for (String currentFilePath : containedFiles) {
        FileEntry currentEntry = zip64File.getFileEntry(currentFilePath);
        File destination = new File(dest, currentEntry.getName());
        if(!currentEntry.isDirectory()) {
          readFileEntry(zip64File, currentEntry, dest);
        }
        else {
          destination.mkdirs();
          log.info("[readFolderEntry] Created folder in file system: " + destination.getAbsolutePath());
//          readFolderEntry(zip64File, currentEntry, destination);
        }
      }
    }
  }

 
  /**
   * Unzips a zip file and writes the content to destFolder, checking if the checksum is correct.
   *
   * @param zipFile the file to unpack
   * @param destFolder the folder to write the content of the zip to
   * @param checksum the checksum to check
   * @return a list containing all extracted files.
   */
  public static List<File> checkAndUnzipTo(File zipFile, File destFolder, Checksum checksum) {
    try {
      byte[] fileDigest = Checksums.md5(zipFile);
      String fileDigestString = Arrays.toString(fileDigest);
      if(!fileDigestString.equals(checksum.getValue())) {
        log.warning("[checkAndUnzipTo] WARNING: The calculated checksum of the zip file is NOT equal to the passed checksum. File might be corrupted!");
        log.warning("[checkAndUnzipTo] Checksum Algorithm: " + checksum.getAlgorithm());
        log.warning("[checkAndUnzipTo] Passed checksum: " + checksum.getValue());
        log.warning("[checkAndUnzipTo] Calculated checksum: " + fileDigestString);
      }
      else {
        log.info("[checkAndUnzipTo] Success!! Checksum correct!");
      }
      return unzipTo(zipFile, destFolder);
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }
 
 
  /**
   * A convenience method. It creates an array of fragments from all entries in a given zip file.
   * Fragments can be used to adress entries in a zip file.
   *
   * @param zip the zip file to scan
   * @return an String[] containing all file entries in this zip.
   *
   */
  public static String[] getAllFragments(File zip) {
//    String[] fragments = null;
//    try {
//      Zip64File zip64File = new Zip64File(zip);
//      List<FileEntry> entries = zip64File.getListFileEntries();
//      if(entries.size() > 0) {
//        int i = 0;
//        fragments = new String[entries.size()];
//        for (FileEntry fileEntry : entries) {
//          fragments[i] = new String(fileEntry.getName());
//          i++;
//        }
//      }
//      else {
//        return new String[]{};
//      }
//      zip64File.close();
   
      List<String> entries = listZipEntries(zip);
      if(entries.size()>0) {
        return entries.toArray(new String[] {});
      }
      else {
        log.severe("[ZipUtils] getAllFragments(): No file entries found! This file is not a valid ZIP file!");
        return new String[] {};
      }
     
//    } catch (ZipException e) {
//      log.severe("[ZipUtils] getAllFragments(): No file entries found! This file is not a valid ZIP file!");
////      e.printStackTrace();
//      return new String[] {};
//    } catch (FileNotFoundException e) {
//      e.printStackTrace();
//    } catch (IOException e) {
//      e.printStackTrace();
//    }
//    return fragments;
  }
 
 
  /**
   * Extracts a file specified by targetPathInZipfile from the passed zip and writes it to destFolder.
   * If the targetPathInZipfile points to a folder, all files in the folder will be extracted as well
   * and the parent folder, containing all these files, is returned.
   *
   * @param zip the zip to extract targetPathInZipfile from
   * @param targetPathInZipfile the file to extract
   * @param destFolder the folder to write the extrcated file to
   * @return the extracted File.
   */
  public static File getFileFrom(File zip, String targetPathInZipfile, File destFolder) {
    File target = null;
    try {
      Zip64File zip64File = new Zip64File(zip);
      FileEntry targetEntry = getFileEntry(zip64File, targetPathInZipfile);
     
      if(targetEntry!=null) {
        target = readEntry(zip64File, targetEntry, destFolder);
      }
      else {
        log.severe("[getFileFrom] Sorry, the file/folder you ask for could not be found in this zip: " + targetPathInZipfile);
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return target;
  }
 
 
//  private static List<String> checkFilesForDeletion(Zip64File zip64File, FileEntry parentFolderEntry, File folderToInsert) {
//    List<String> entryChildren = getFileEntryChildren(zip64File, parentFolderEntry);
//    List<String> filesToAdd = normalizePaths(folderToInsert);
//   
//    List<String> filesToDelete = new ArrayList<String>();
//   
//    for (String currentChild : entryChildren) {
//      for (String currentToAdd : filesToAdd) {
//        if(currentChild.endsWith(currentToAdd)) {
//          filesToDelete.add(currentChild);
//        }
//      }
//    }
//   
//    return filesToDelete;
//  }
 
 
  /**
   * Inserts a file into a given zip at a location specified by targetPath.
   * If toInsert points to a folder, all files in this folder will be added to the zip.
   * If the zip already contains a file specified by targetPath, the existing entry (and all files contained in it)
   * will be deleted and toInsert (and all contained files) is inserted.
   *
   * @param zipFile the zip file where the file toInsert will be added.
   * @param toInsert the file to add to the zip
   * @param targetPath the location the file should have in this zip
   * @return the modified zip, containing the file toInsert.
   */
  public static File insertFileInto(File zipFile, File toInsert, String targetPath) {
    Zip64File zip64File = null;
    try {
      boolean compress = false;
     
      zip64File = new Zip64File(zipFile);
     
      FileEntry testEntry = getFileEntry(zip64File, targetPath);
     
      if(testEntry!= null && testEntry.getMethod() == FileEntry.iMETHOD_DEFLATED) {
        compress = true;
      }
     
      processAndCreateFolderEntries(zip64File, parseTargetPath(targetPath, toInsert), compress);
     
      if(testEntry!=null) {
        log.info("[insertFileInto] Entry exists: " + testEntry.getName());
        log.info("[insertFileInto] Will delete this entry before inserting: " + toInsert.getName());
        if(!testEntry.isDirectory()) {
          zip64File.delete(testEntry.getName());
        }
        else {
          log.info("[insertFileInto] Entry is a directory. " +
              "Will delete all files contained in this entry and insert " + toInsert.getName()
              "and all nested files.");
         
          if(!targetPath.contains("/")) {
            targetPath = targetPath + "/";
          }
          deleteFileEntry(zip64File, testEntry);
          log.info("[insertFileInto] Entry successfully deleted.");
        }
       
        log.info("[insertFileInto] Writing new Entry: " + targetPath);
        EntryOutputStream out = null;
        if(!compress) {
          out = zip64File.openEntryOutputStream(targetPath, FileEntry.iMETHOD_STORED, new Date(toInsert.lastModified()));
        }
        else {
          out = zip64File.openEntryOutputStream(targetPath, FileEntry.iMETHOD_DEFLATED, new Date(toInsert.lastModified()));
        }
       
        if(toInsert.isDirectory()) {
          out.flush();
          out.close();
          log.info("[insertFileInto] Finished writing entry: " + targetPath);
         
          List<String> containedPaths = normalizePaths(toInsert);
          List<File> containedFiles = listAllFilesAndFolders(toInsert, new ArrayList<File>());
         
          log.info("[insertFileInto] Added entry is a folder.");
          log.info("[insertFileInto] Adding all nested files: ");
          for(int i=0;i<containedPaths.size();i++) {
            File currentFile = containedFiles.get(i);
            String currentPath = targetPath.replace("/", "") + File.separator + containedPaths.get(i);
            EntryOutputStream loop_out = null;
            if(!compress) {
              loop_out = zip64File.openEntryOutputStream(currentPath, FileEntry.iMETHOD_STORED, new Date(currentFile.lastModified()));
            }
            else {
              loop_out = zip64File.openEntryOutputStream(currentPath, FileEntry.iMETHOD_DEFLATED, new Date(currentFile.lastModified()));
            }
            if(currentFile.isFile()) {
              InputStream loop_in = new FileInputStream(currentFile);
              IOUtils.copyLarge(loop_in, loop_out);
              loop_in.close();
            }
            log.info("[insertFileInto] Added: " + currentPath);
            loop_out.flush();
            loop_out.close();
          }
        }
        else {
          InputStream in = new FileInputStream(toInsert);
          IOUtils.copyLarge(in, out);
          in.close();
          out.flush();
          out.close();
        }
      }
      else {
        EntryOutputStream out = null;
        if(!compress) {
          out = zip64File.openEntryOutputStream(targetPath, FileEntry.iMETHOD_STORED, new Date(toInsert.lastModified()));
        }
        else {
          out = zip64File.openEntryOutputStream(targetPath, FileEntry.iMETHOD_DEFLATED, new Date(toInsert.lastModified()));
        }
       
        if(toInsert.isDirectory()) {
          out.flush();
          out.close();
          log.info("[insertFileInto] Finished writing entry: " + targetPath);
         
          List<String> containedPaths = normalizePaths(toInsert);
          List<File> containedFiles = listAllFilesAndFolders(toInsert, new ArrayList<File>());
         
          log.info("[insertFileInto] Added entry is a folder.");
          log.info("[insertFileInto] Adding all nested files: ");
         
          for(int i=0;i<containedPaths.size();i++) {
            File currentFile = containedFiles.get(i);
            String currentPath = targetPath.replace("/", "") + File.separator + containedPaths.get(i);
            EntryOutputStream loop_out = null;
            if(!compress) {
              loop_out = zip64File.openEntryOutputStream(currentPath, FileEntry.iMETHOD_STORED, new Date(currentFile.lastModified()));
            }
            else {
              loop_out = zip64File.openEntryOutputStream(currentPath, FileEntry.iMETHOD_DEFLATED, new Date(currentFile.lastModified()));
            }
           
            if(currentFile.isFile()) {
              InputStream loop_in = new FileInputStream(currentFile);
              IOUtils.copyLarge(loop_in, loop_out);
              loop_in.close();
            }
            log.info("[insertFileInto] Added: " + currentPath);
            loop_out.flush();
            loop_out.close();
          }
        }
        else {
          InputStream in = new FileInputStream(toInsert);
          IOUtils.copyLarge(in, out);
          in.close();
          out.flush();
          out.close();
        }
      }
      log.info("[insertFileInto] Done! Added " + toInsert.getName() + " to zip.");
      zip64File.close();
     
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return new File(zip64File.getDiskFile().getFileName());
  }
 
  private static List<String> parseTargetPath(String targetPath, File toInsert) {
    List<String> cleanedParts = new ArrayList<String>();
   
    if(targetPath.contains("\\")) {
      targetPath = targetPath.replace("\\", "#");
      String[] parts = targetPath.split("#");
      if(parts.length > 1) {
        String accumulatedPath = "";
        for (int i = 0; i < parts.length-1; i++) {
          String thisPath = accumulatedPath + "\\" + parts[i] + "/";
          cleanedParts.add(thisPath.substring(1));
          accumulatedPath = accumulatedPath + "\\" + parts[i];
        }
      }
      else {
        return null;
      }
      return cleanedParts;
    }
    else {
      return null;
    }
  }
 
  private static void processAndCreateFolderEntries(Zip64File zip64File, List<String> pathParts, boolean compress) {
    if(pathParts==null) {
      return;
    }
    for (String string : pathParts) {
      FileEntry currentEntry = zip64File.getFileEntry(string);
      if(currentEntry!=null) {
        continue;
      }
      else {
        currentEntry = zip64File.getFileEntry(string + "/");
        if(currentEntry!=null) {
          continue;
        }
        else {
          try {
            EntryOutputStream entryWriter = null;
           
            if(!compress) {
              entryWriter = zip64File.openEntryOutputStream(string, FileEntry.iMETHOD_STORED, null);
            }
            else {
              entryWriter = zip64File.openEntryOutputStream(string, FileEntry.iMETHOD_DEFLATED, null);
            }
           
            entryWriter.flush();
            entryWriter.close();
          } catch (FileNotFoundException e) {
            e.printStackTrace();
          } catch (ZipException e) {
            e.printStackTrace();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
 

 
  /**
   * Removes the file 'fileToRemove' from zipFile.
   * 'fileToRemove' points to the location of the file to delete inside the zip file.
   *
   * @param zipFile the zip file to remove fileToRemove from.
   * @param fileToRemove the path of the file to remove from zipFile.
   * @return the modified zipFile.
   */
  public static File removeFileFrom(File zipFile, String fileToRemove) {
    Zip64File zip64File = null;
    try {
      zip64File = new Zip64File(zipFile);
     
      FileEntry testEntry = getFileEntry(zip64File, fileToRemove);
     
      if(testEntry==null) {
        log.info("File not found: " + fileToRemove);
        log.info("Nothing has been deleted...");
      }
      else {
        if(testEntry.isDirectory()) {
          deleteFileEntry(zip64File, testEntry);
        }
        else {
          FileEntry deletedEntry = zip64File.delete(fileToRemove);
          log.info("Deleted entry from zip: " + deletedEntry.getName());
          zip64File.close();
        }
      }
     
      zip64File.close();
     
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return new File(zip64File.getDiskFile().getFileName());
  }
 
  @SuppressWarnings("unchecked")
  public static boolean isZipFile(File file) {
    try {
      Zip64File zip = new Zip64File(file);
      List<FileEntry> entries = zip.getListFileEntries();
      if(entries==null) {
        return false;
      }
      else {
        return true;
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (ZipException e) {
      log.info("File '" + file.getName() + "' is NOT a ZIP.");
      return false;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return false;
  }

 
  /**
   * Lists all entries in this zip file. Each entry is a file/folder in this zip.
   * @param zip the zip file to scan
   * @return a list with all entry paths
   */
  @SuppressWarnings("unchecked")
  public static List<String> listZipEntries(File zip) {
    List<String> entryList = new ArrayList<String>();
    try {
      Zip64File zip64File = new Zip64File(zip);
      List<FileEntry> entries = zip64File.getListFileEntries();
     
//      zip64File.close();
     
      if(entries.size() > 0) {
        for (FileEntry fileEntry : entries) {
          List<String> parents = getParents(fileEntry);
          if(parents!=null) {
            for (String currentPart : parents) {
              if(!entryList.contains(currentPart)) {
                entryList.add(currentPart);
              }
            }
          }
          entryList.add(fileEntry.getName());
        }
      }
      else {
        return new ArrayList<String>();
      }
     
    } catch (ZipException e) {
      log.severe("[ZipUtils] listZipEntries(): " + e.getMessage());
//      e.printStackTrace();
      return entryList;
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return entryList;
  }
 
  private static List<String> getParents(FileEntry fileEntry) {
    List<String> parentsList = new ArrayList<String>();
    String path = fileEntry.getName();
    String[] parents = null;
    if(path.contains("/")) {
      parents = path.split("/");
      String tmp = "";
      for (int i=0;i<parents.length-1;i++) {
        if(tmp.equalsIgnoreCase("")) {
          parentsList.add(tmp + parents[i] + "/");
          tmp = tmp + parents[i];
        }
        else {
          parentsList.add(tmp + "/" + parents[i] + "/");
          tmp = tmp + "/" + parents[i];
        }
      }
      return parentsList;
    }
    else {
      return null;
    }
  }
 

  private static File readEntry(Zip64File zip64File, FileEntry toRead, File destFolder) {
    File target = new File(destFolder, toRead.getName());
    if(!toRead.isDirectory()) {
      readFileEntry(zip64File, toRead, destFolder);
    }
    else {
      readFolderEntry(zip64File, toRead, destFolder);
    }
    return target;
  }
 
 
  private static FileEntry writeEntry(Zip64File zip64File, FileEntry targetPath, File toWrite, boolean compress) {
    InputStream in = null;
    EntryOutputStream out = null;
   
    processAndCreateFolderEntries(zip64File, parseTargetPath(targetPath.getName(), toWrite), compress);
   
    try {
     
      if(!compress) {
        out = zip64File.openEntryOutputStream(targetPath.getName(), FileEntry.iMETHOD_STORED, getFileDate(toWrite));
      }
      else {
        out = zip64File.openEntryOutputStream(targetPath.getName(), FileEntry.iMETHOD_DEFLATED, getFileDate(toWrite));
      }
     
     
      if(!targetPath.isDirectory()) {
        in = new FileInputStream(toWrite);
        IOUtils.copyLarge(in, out);
        in.close();
      }
      out.flush();
      out.close();
      if(targetPath.isDirectory()) {
        log.info("[createZip] Written folder entry to zip: " + targetPath.getName());
      }
      else {
        log.info("[createZip] Written file entry to zip: " + targetPath.getName());
      }
       
     
    } catch (FileNotFoundException e1) {
      e1.printStackTrace();
    } catch (ZipException e1) {
      e1.printStackTrace();
    } catch (IOException e1) {
      e1.printStackTrace();
    }
    return targetPath;
  }

 
  private static Date getFileDate(File file) {
    Date date = new Date(file.lastModified());
    return date;
  }
 
 
  @SuppressWarnings("unused")
  private static FileEntry testFileEntry(Zip64File zip64File, String targetPath) {
    FileEntry fileEntry = zip64File.getFileEntry(targetPath);
    return fileEntry;
  }
 
  @SuppressWarnings("unused")
  private static FileEntry testFolderEntry(Zip64File zip64File, String targetPath) {
    FileEntry folderEntry = zip64File.getFileEntry(targetPath + "/");
    return folderEntry;
  }
 
 
//  private static boolean containsEntry(Zip64File zip64File, String targetPath) {
//    FileEntry result = testFileEntry(zip64File, targetPath);
//    if(result!=null) {
//      return true;
//    }
//    else {
//      result = testFolderEntry(zip64File, targetPath);
//      if(result!=null) {
//        return true;
//      }
//      else {
//        return false;
//      }
//    }
//  }


  /**
   * Private method to delete a FileEntry including all nested entries "below" the FileEntry toDelete.
   * @param zip the zip64File to delete the FileEntry toDelete from
   * @param toDelete the FileEntry to delete
   * @return a list with all deleted file entries.
   */
  private static List<FileEntry> deleteFileEntry(Zip64File zip, FileEntry toDelete) {
    List<FileEntry> deletedEntries = deleteEntriesRecursively(zip, toDelete, new ArrayList<FileEntry>());
    return deletedEntries;
  }
 

  /**
   * Helper method to delete a FileEntry (and all nested entries) recursively.
   * If toDelete is a folder, all nested entries will be deleted.
   * @param zip the zip to delete the entry from
   * @param toDelete the entry to delete
   * @param deletedEntries a list where all deleted entries will be stored.
   * @return the list of deletedEntries
   */
  private static List<FileEntry> deleteEntriesRecursively(Zip64File zip, FileEntry toDelete, List<FileEntry> deletedEntries) {
    try {
      if(toDelete.isDirectory()) {
        log.info("[deleteEntriesRecursively] The FileEntry to delete is a folder. Deleting all nested entries: ");
        List<String> containedFiles = getFileEntryChildren(zip, toDelete);
       
        if(containedFiles.size()>0) {
          for (String currentEntryPath : containedFiles) {
            FileEntry current = zip.getFileEntry(currentEntryPath);
            if(current!=null) {
              deleteEntriesRecursively(zip, current, deletedEntries);
            }
          }
          log.info("[deleteEntriesRecursively] Deleted entry: " + toDelete.getName());
          deletedEntries.add(zip.delete(toDelete.getName()));
        }
        else {
          log.info("[deleteEntriesRecursively] Deleted entry: " + toDelete.getName());
          deletedEntries.add(zip.delete(toDelete.getName()));
        }
      }
      else {
        FileEntry current = zip.delete(toDelete.getName());
        log.info("[deleteEntriesRecursively] Deleted entry: " + toDelete.getName());
        deletedEntries.add(current);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return deletedEntries;
  }
 
 
  /**
   * Checks if a FileEntry named by entryPath is contained in the zip.
   *
   * @param zip the zip file to search.
   * @param entryPath the FileEntry to find
   * @return the found FileEntry or null, if entryPath is not a valid location.
   */
  private static FileEntry getFileEntry(Zip64File zip64File, String entryPath) {
    FileEntry testEntry = null;
    testEntry = zip64File.getFileEntry(entryPath);
    if(testEntry==null) {
      testEntry = zip64File.getFileEntry(entryPath + "/");
    }
    if(testEntry!=null) {
      log.info("[getFileEntry] Found entry: " + testEntry.getName());
    }
    else {
      log.severe("[getFileEntry] Entry NOT found: " + entryPath);
    }
    return testEntry;
  }
 
 
  /**
   * Returns all nested FileEntries for a given folder-FileEntry
   * @param zip the zip file
   * @param folderEntry the folder FileEntry to scan.
   * @return all entries nested in folderEntry.
   */
  private static List<String> getFileEntryChildren(Zip64File zip, FileEntry folderEntry) {
    List<String> list = listZipEntries(zip);
    List<String> resultList = new ArrayList<String>();
    String folderEntryName = folderEntry.getName();
    String testName = folderEntryName.substring(0, folderEntryName.length()-1);
    for (String currentPath : list) {
      if(currentPath.contains(testName)) {
        if(!currentPath.equalsIgnoreCase(folderEntry.getName())) {
          log.info("[getFileEntryChildren] Found child: " + currentPath);
          resultList.add(currentPath);
        }
      }
    }
    return resultList;
  }

 
  /**
   * Convenience method to get the file name as String from a given FileEntry.
   * This method returns the last part of the FileEntry.getName() String, starting with
   * the last index of "\".
   * @param entry the FileEntry to get the file name for.
   * @return the file name as String
   */
//  private static String getEntryFileName(FileEntry entry) {
//    String entryPath = entry.getName();
//    String name = null;
//    if(entryPath.contains(File.separator)) {
//      name = entryPath.substring(entryPath.lastIndexOf(File.separator)+1);
//      return name;
//    }
//    else {
//      return entryPath;
//    }
//  }

 
  /**
   * Utility method to list all entries in a zip file as a List<String>
   * @param zip64File the zip64 file to list the entries
   * @return all entries in this zip64File
   */
  @SuppressWarnings("unchecked")
  private static List<String> listZipEntries(Zip64File zip64File) {
    List<String> entryList = new ArrayList<String>();
   
    List<FileEntry> entries = zip64File.getListFileEntries();
   
    if(entries.size() > 0) {
      for (FileEntry fileEntry : entries) {
        entryList.add(fileEntry.getName());
      }
    }
    return entryList;
  }

  /**
     * @param dir The dir to list
     * @param list The list to add the contents of dir to
     * @return The given list, with the contents of dir added
     */
    private static ArrayList<String> listAllFilesAndFolders(final File dir,
            final ArrayList<String> list) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                File currentFile = files[i];
                boolean currentFileIsDir = currentFile.isDirectory();
                if (currentFileIsDir) {
                    // Ignore hidden folders
                    if (currentFile.isHidden()) {
                        continue;
                    }
                    if (currentFile.getName().equalsIgnoreCase("CVS")) {
                        continue;
                    }
                    if (currentFile.getName().equalsIgnoreCase(".svn")) {
                        continue;
                    }
                    list.add(currentFile.getPath() + "/");
                    /*
                     * the closing "/" has to be there to tell the
                     * ZipOutputStream that this is a folder...
                     */
                    listAllFilesAndFolders(currentFile, list);
                } else {
                    list.add(currentFile.getPath());
                }
            }
        }
        return list;
    }
   
   
    /**
     * Utility method to strip the absoulte part of a files path, starting with the index of folder.getName().
     *
     * @param folder the folder
     * @return
     */
    private static List<String> normalizePaths(File folder) {
    if(!folder.isDirectory()) {
      return null;
    }
   
    List<String> resultFileList = listAllFilesAndFolders(folder, new ArrayList<String>());
   
    if (resultFileList.size() == 0) {
          return null;
      }
    ArrayList<String> normalizedPaths = new ArrayList<String>();
      for (int i = 0; i < resultFileList.size(); i++) {
          String currentPath = resultFileList.get(i);
          // Strip the beginning of the String, except the "[FOLDER-NAME]
          // itself\"....
          int index = currentPath.indexOf(folder.getName());
          currentPath = currentPath.substring(index);
          // Delete the [FOLDER-NAME] part of the paths
          currentPath = currentPath.replace(folder.getName()
                  + File.separator, "");
          // add the normalized path to the list
          normalizedPaths.add(currentPath);
      }
      return normalizedPaths;
  }
   
    /**
     * @param dir The dir to list
     * @param list The list to add the contents of dir to
     * @return The given list, with the contents of dir added, including files and folders
     */
    static List<File> listAllFilesAndFolders(final File dir,
            final List<File> list) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                File currentFile = files[i];
                boolean currentFileIsDir = currentFile.isDirectory();
                if (currentFileIsDir) {
                    // Ignore hidden folders
                    if (currentFile.isHidden()) {
                        continue;
                    }
                    if (currentFile.getName().equalsIgnoreCase("CVS")) {
                        continue;
                    }
                    list.add(currentFile);
                    listAllFilesAndFolders(currentFile, list);
                } else {
                    list.add(currentFile);
                }
            }
        }
        return list;
    }

}
TOP

Related Classes of eu.planets_project.services.utils.ZipUtils

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.