/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache 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.apache.org/licenses/LICENSE-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.apache.uima.pear.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.file.CopyOption;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.uima.util.impl.Constants;

/**
 * The <code>FileUtil</code> class provides utility methods for working with general files.
 */
public class FileUtil {
  private static final char DOT = '.';
  private static final String UTF8_ENCODING = "UTF-8";
  private static final String ASCII_ENCODING = "ASCII";
  private static final String XML_EXTENSION = DOT + "xml";
  private static final String BACKUP_EXTENSION = DOT + "bak";
  private static final String ZIP_EXTENSION = DOT + "zip";
  private static final char UNIX_SEPARATOR_CHAR = '/';
  private static final char WINDOWS_SEPARATOR_CHAR = '\\';
  private static final String UNIX_SEPARATOR = String.valueOf(UNIX_SEPARATOR_CHAR);
  private static final String WINDOWS_SEPARATOR = String.valueOf(WINDOWS_SEPARATOR_CHAR);

  /**
   * The <code>FileTimeComparator</code> class allows comparing 'last modified' time in 2 given
   * <code>File</code> objects.
   */
  public static class FileTimeComparator implements Comparator<File> {
    /**
     * @return A negative integer, zero, or a positive integer as the first argument is less than,
     *         equal to, or greater than the second.
     * @throws java.lang.ClassCastException
     *           if the arguments' types prevent them from being compared by this
     *           <code>Comparator</code>.
     */
    @Override
    public int compare(File o1, File o2) throws ClassCastException {
      long t1 = o1.lastModified();
      long t2 = o2.lastModified();
      return (t1 >= t2) ? -1 : 1;
    }

    /**
     * @param obj
     *          The reference object with which to compare.
     * @return <code>true</code> only if the specified object is also a
     *         <code>FileTimeComparator</code>, and it imposes the same ordering as this comparator.
     */
    @Override
    public boolean equals(Object obj) {
      return (obj instanceof FileTimeComparator);
    }
  } // FileTimeComparator end

  /**
   * The <code>DirFileFilter</code> class allows to filter files based on specified directory path
   * and filename extension.
   */
  public static class DirFileFilter implements FileFilter {
    // attributes
    private String _dirPath;

    private String _fileExt;

    /**
     * Constructs <code>DirFileFilter</code> object for specified directory and file extension.
     * 
     * @param dirPath
     *          The given directory.
     * @param fileExt
     *          The given file extension.
     */
    public DirFileFilter(String dirPath, String fileExt) {
      _dirPath = (dirPath != null) ? dirPath.replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR)
              : null;
      if (fileExt != null) {
        _fileExt = fileExt.startsWith(".") ? fileExt.toLowerCase() : "." + fileExt.toLowerCase();
      } else {
        _fileExt = null;
      }
    }

    /**
     * @param file
     *          The given file to be tested.
     * @return <code>true</code> if the given file should be accepted, <code>false</code> otherwise.
     */
    @Override
    public boolean accept(File file) {
      boolean dirAccepted = true;
      boolean extAccepted = true;
      if (_dirPath != null) {
        String parentDir = file.getParent();
        dirAccepted = parentDir != null && parentDir
                .replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR).startsWith(_dirPath);
      }
      if (_fileExt != null) {
        extAccepted = file.getPath().toLowerCase().endsWith(_fileExt);
      }
      return dirAccepted && extAccepted;
    }
  } // DirFileFilter end

  /**
   * The <code>NameFileFilter</code> class allows to filter files based on specified file name.
   */
  public static class NameFileFilter implements FileFilter {
    // attributes
    private String _fileName;

    /**
     * Constructs <code>NameFileFilter</code> object for a given file name.
     * 
     * @param fileName
     *          The given file name for filtering.
     */
    public NameFileFilter(String fileName) {
      _fileName = fileName.replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR);
    }

    /**
     * @param file
     *          The given file to be tested.
     * @return <code>true</code> if the given file should be accepted, <code>false</code> otherwise.
     */
    @Override
    public boolean accept(File file) {
      String filePath = file.getAbsolutePath().replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR);
      if (filePath.endsWith(_fileName)) {
        if (filePath.length() > _fileName.length()) {
          char prevChar = filePath.charAt(filePath.length() - _fileName.length() - 1);
          if (prevChar == ':' || prevChar == UNIX_SEPARATOR_CHAR) {
            return true;
          }
        } else {
          return true;
        }
      }
      return false;
    }
  } // NameFileFilter end

  /**
   * The <code>ExtFileFilter</code> allows to filter file names based on the specified filename
   * extension.
   * 
   */
  public static class ExtFilenameFilter implements FilenameFilter {
    // attributes
    private String _fileExt;

    private boolean _ignoreCase;

    /**
     * Create instance of the <code>ExtFileFilter</code> class for a given filename extension. By
     * default, this filename filter is case insensitive. If the given filename extension does not
     * start from the '.' character, adds this character at the beginning.
     * 
     * @param fileExt
     *          The given filename extension.
     */
    public ExtFilenameFilter(String fileExt) {
      this(fileExt, true);
    }

    /**
     * Create instance of the <code>ExtFileFilter</code> class for a given filename extension. If a
     * given <code>boolean</code> flag is <code>true</code>, this filename filter is case
     * insensitive, otherwise it's case sensitive. If the given filename extension does not start
     * from the '.' character, adds this character at the beginning.
     * 
     * @param fileExt
     *          The given filename extension.
     * @param ignoreCase
     *          The given 'case sensitivity' flag.
     */
    public ExtFilenameFilter(String fileExt, boolean ignoreCase) {
      _fileExt = fileExt.startsWith(".") ? fileExt : "." + fileExt;
      _ignoreCase = ignoreCase;
      if (ignoreCase) {
        _fileExt = _fileExt.toLowerCase();
      }
    }

    /**
     * Tests if a specified file should be included in a file list.
     * 
     * @param dir
     *          The directory in which the file was found.
     * @param name
     *          The given name of the file.
     * @return <code>true</code>, if the given file should be included in the list,
     *         <code>false</code> otherwise.
     */
    @Override
    public boolean accept(File dir, String name) {
      String fileName = _ignoreCase ? name.toLowerCase() : name;
      return fileName.endsWith(_fileExt);
    }
  } // ExtFilenameFilter end

  /**
   * Deletes all files and subdirectories in a given directory. In case of unsuccessful deletion,
   * calls the <code>deleteOnExit()</code> method to request that files and subdirs are deleted when
   * the JVM terminates.
   * 
   * @param directory
   *          The given directory to be cleaned-up.
   * @return The number of successfully deleted entries in the given directory.
   * @throws IOException
   *           If an I/O exception occurred.
   */
  public static int cleanUpDirectoryContent(File directory) throws IOException {
    int counter = 0;
    File[] allDirFiles = directory.listFiles();
    if (allDirFiles != null) {
      for (int i = 0; i < allDirFiles.length; i++) {
        File aFile = allDirFiles[i];
        if (aFile.isDirectory()) {
          counter += cleanUpDirectoryContent(aFile);
          if (aFile.delete()) {
            counter++;
          } else {
            aFile.deleteOnExit();
          }
        } else if (aFile.isFile()) {
          if (aFile.delete()) {
            counter++;
          } else {
            aFile.deleteOnExit();
          }
        }
      }
    }
    return counter;
  }

  /**
   * Deletes all files in a given directory. In case of unsuccessful deletion, calls the
   * <code>deleteOnExit()</code> method to request that files are deleted when the JVM terminates.
   * 
   * @param directory
   *          The given directory to be cleaned-up.
   * @return The number of successfully deleted entries in the given directory.
   * @throws IOException
   *           If an I/O exception occurred.
   */
  public static int cleanUpDirectoryFiles(File directory) throws IOException {
    int counter = 0;
    File[] allDirFiles = directory.listFiles();
    if (allDirFiles != null) {
      for (int i = 0; i < allDirFiles.length; i++) {
        File aFile = allDirFiles[i];
        if (aFile.isFile()) {
          if (aFile.delete()) {
            counter++;
          } else {
            aFile.deleteOnExit();
          }
        }
      }
    }
    return counter;
  }

  /**
   * Cleans-up a given directory by keeping the number of files within a given limit. Deletes the
   * oldest files first. In case of unsuccessful deletion, calls the <code>deleteOnExit()</code>
   * method to request that files are deleted when the JVM terminates.
   * 
   * @param directory
   *          The given directory.
   * @param maxLimit
   *          The given maximum limit of the number of files in the given directory.
   * @return The number of actually deleted files.
   * @throws IOException
   *           If an I/O exception occurred.
   */
  public static int cleanUpDirectoryFiles(File directory, int maxLimit) throws IOException {
    int counter = 0;
    Collection<File> fileList = createFileList(directory, false);
    SortedSet<File> sortedFileSet = sortFileListByTime(fileList);
    if (sortedFileSet.size() > maxLimit) {
      Iterator<File> list = sortedFileSet.iterator();
      int no = 0;
      while (list.hasNext()) {
        File file = list.next();
        no++;
        if (no > maxLimit) {
          if (file.delete()) {
            counter++;
          } else {
            file.deleteOnExit();
          }
        }
      }
    }
    return counter;
  }

  private static String normalizeToUnix(String aPath) {
    if (aPath == null) {
      return null;
    }

    return aPath.replace(WINDOWS_SEPARATOR_CHAR, UNIX_SEPARATOR_CHAR);
  }

  /**
   * Computes relative path to a given file from a given reference directory, if both the reference
   * directory and the file are in the same logical file system (partition).
   * 
   * @param referenceDir
   *          The given reference directory.
   * @param file
   *          The given file.
   * @return The relative path to the given file from the given reference directory, or
   *         <code>null</code>, if the relative path does not exist.
   * @throws IOException
   *           If an I/O error occurs, which is possible because the construction of the canonical
   *           pathname may require filesystem queries.
   */
  public static String computeRelativePath(File referenceDir, File file) throws IOException {
    // get canonical path expressions
    String refPath = normalizeToUnix(referenceDir.getCanonicalPath());
    String filePath = normalizeToUnix(file.getCanonicalPath());
    // compute relative path from reference dir to file dir-tree
    StringBuffer relBuffer = new StringBuffer();
    while (refPath != null && !filePath.startsWith(refPath)) {
      relBuffer.append("../");
      refPath = normalizeToUnix((new File(refPath)).getParent());
    }

    if (refPath != null) {
      // construct relative path
      String subPath = filePath.substring(refPath.length());
      if (relBuffer.length() == 0) {
        relBuffer.append("./");
      }
      if (subPath.startsWith("/")) {
        relBuffer.append(subPath.substring(1));
      } else {
        relBuffer.append(subPath);
      }
      return relBuffer.toString();
    }
    // relative path does not exist
    return null;
  }

  /**
   * Copies the content of a given source file to a given destination file.
   * 
   * @param source
   *          The given source file.
   * @param destination
   *          The given destination file.
   * @return <code>true</code> if the copy operation completed successfully, <code>false</code>
   *         otherwise.
   * @throws IOException
   *           If any I/O exception occurred.
   * @deprecated use Java 7 for this see {@link java.nio.file.Files#copy(Path, Path, CopyOption...)}
   */
  @Deprecated
  public static boolean copyFile(File source, File destination) throws IOException {
    try (BufferedInputStream iStream = new BufferedInputStream(new FileInputStream(source));
            BufferedOutputStream oStream = new BufferedOutputStream(
                    new FileOutputStream(destination))) {
      byte[] block = new byte[4096];
      int bCount = 0;
      while ((bCount = iStream.read(block)) > 0) {
        oStream.write(block, 0, bCount);
      }
    }
    return true;
  }

  /**
   * Copies the content of a given remote source file to a given destination file.
   * 
   * @param sourceUrl
   *          The given source file URL.
   * @param destination
   *          The given destination file.
   * @return <code>true</code> if the copy operation completed successfully, <code>false</code>
   *         otherwise.
   * @throws IOException
   *           If any I/O exception occurred.
   * @deprecated use Java 7 for this see
   *             {@link java.nio.file.Files#copy(InputStream, Path, CopyOption...)}
   */
  @Deprecated
  public static boolean copyFile(URL sourceUrl, File destination) throws IOException {
    try (BufferedInputStream iStream = new BufferedInputStream(sourceUrl.openStream());
            BufferedOutputStream oStream = new BufferedOutputStream(
                    new FileOutputStream(destination))) {
      byte[] block = new byte[4096];
      int bCount = 0;
      while ((bCount = iStream.read(block)) > 0) {
        oStream.write(block, 0, bCount);
      }
    }
    return true;
  }

  /**
   * Creates list of subdirectories in a given root directory, including all its subdirectories.
   * 
   * @param rootDir
   *          The given root directory.
   * @return <code>Collection</code> of <code>File</code> objects, representing subdirectories in
   *         the given root directory and all its subdirectories.
   * 
   * @throws java.io.IOException
   *           If any I/O exception occurs.
   */
  public static Collection<File> createDirList(File rootDir) throws IOException {
    return createDirList(rootDir, true);
  }

  /**
   * Creates list of subdirectories in a given root directory. If a given <code>boolean</code> flag
   * is <code>true</code>, all the subdirectories of the given root directory are also scanned,
   * otherwise only subdirectories in the given root directory are included.
   * 
   * @return <code>Collection</code> of <code>File</code> objects, representing subdirectories in
   *         the given root directory.
   * @param rootDir
   *          The given root directory.
   * @param includeSubdirs
   *          If <code>true</code>, the returned list includes sub-directories from all
   *          sub-directories of the given root directory, otherwise it includes only
   *          sub-directories from the given root directory itself.
   * 
   * @exception java.io.IOException
   *              If any I/O exception occurs.
   */
  public static Collection<File> createDirList(File rootDir, boolean includeSubdirs)
          throws IOException {
    ArrayList<File> listOfDirs = new ArrayList<>();
    File[] allDirFiles = rootDir.listFiles();
    if (allDirFiles == null) {
      throw new FileNotFoundException("invalid directory specified");
    }
    for (int i = 0; i < allDirFiles.length; i++) {
      File aFile = allDirFiles[i];
      if (aFile.isDirectory()) {
        listOfDirs.add(aFile);
        if (includeSubdirs) {
          listOfDirs.addAll(createDirList(aFile, includeSubdirs));
        }
      }
    }
    return listOfDirs;
  }

  /**
   * Creates a list of directories in a given archive (JAR) file. The root directory path, used to
   * represent the directories, is set to the input archive file path without the file name
   * extension.
   * 
   * @param archive
   *          The input archive (JAR) file.
   * @return <code>Collection</code> of <code>File</code> objects, representing directories in the
   *         given archive file.
   * @throws IOException
   *           If any I/O exception occurs.
   */
  public static Collection<File> createDirList(JarFile archive) throws IOException {
    ArrayList<File> listOfDirs = new ArrayList<>();
    // set root_dir_path = archive_file_path (w/o file name extension)
    int nameEndIndex = archive.getName().lastIndexOf(DOT);
    String rootDirPath = (nameEndIndex > 0) ? archive.getName().substring(0, nameEndIndex)
            : archive.getName();
    File rootDir = new File(rootDirPath);
    // add directories to the list
    Enumeration<JarEntry> entries = archive.entries();
    while (entries.hasMoreElements()) {
      JarEntry entry = entries.nextElement();
      File file = new File(rootDir, entry.getName());
      if (entry.isDirectory()) {
        listOfDirs.add(file);
      } else {
        // make sure the parent dir is added
        File parentDir = file.getParentFile();
        while (!parentDir.equals(rootDir)) {
          if (!listOfDirs.contains(parentDir)) {
            listOfDirs.add(parentDir);
          }
          parentDir = parentDir.getParentFile();
        }
      }
    }
    return listOfDirs;
  }

  /**
   * Creates list of files in a given directory, including all its subdirectories.
   * 
   * @return <code>Collection</code> of <code>File</code> objects in the given directory, including
   *         all its subdirectories.
   * @param filesDir
   *          The given directory.
   * 
   * @exception java.io.IOException
   *              If any I/O exception occurs.
   */
  public static Collection<File> createFileList(File filesDir) throws IOException {
    return createFileList(filesDir, true);
  }

  /**
   * Creates list of files in a given directory. If a given <code>boolean</code> flag is
   * <code>true</code>, all the sub-directories of the given directory are also scanned, otherwise
   * only files in the given directory are included.
   * 
   * @return <code>Collection</code> of <code>File</code> objects in the given directory.
   * @param filesDir
   *          The given directory.
   * @param includeSubdirs
   *          If <code>true</code>, the returned file list includes files from all the
   *          sub-directories of the given directory, otherwise it includes only files from the
   *          given directory itself.
   * 
   * @exception java.io.IOException
   *              If any I/O exception occurs.
   */
  public static Collection<File> createFileList(File filesDir, boolean includeSubdirs)
          throws IOException {
    ArrayList<File> listOfFiles = new ArrayList<>();
    File[] allDirFiles = filesDir.listFiles();
    if (allDirFiles == null) {
      throw new FileNotFoundException("invalid directory specified");
    }
    for (int i = 0; i < allDirFiles.length; i++) {
      File aFile = allDirFiles[i];
      if (aFile.isDirectory() && includeSubdirs) {
        listOfFiles.addAll(createFileList(aFile, includeSubdirs));
      } else if (!aFile.isDirectory()) {
        listOfFiles.add(aFile);
      }
    }
    return listOfFiles;
  }

  /**
   * Creates a list of files in a given archive (JAR) file. The root directory path, used to
   * represent the files, is set to the input archive file path without the file name extension.
   * 
   * @param archive
   *          The input archive (JAR) file.
   * @return <code>Collection</code> of <code>File</code> objects, representing files in the given
   *         archive file.
   * @throws IOException
   *           If any I/O exception occurs.
   */
  public static Collection<File> createFileList(JarFile archive) throws IOException {
    ArrayList<File> listOfFiles = new ArrayList<>();
    // set root_dir_path = archive_file_path (w/o file name extension)
    int nameEndIndex = archive.getName().lastIndexOf(DOT);
    String rootDirPath = (nameEndIndex > 0) ? archive.getName().substring(0, nameEndIndex)
            : archive.getName();
    File rootDir = new File(rootDirPath);
    // add directories to the list
    Enumeration<JarEntry> entries = archive.entries();
    while (entries.hasMoreElements()) {
      JarEntry entry = entries.nextElement();
      File file = new File(rootDir, entry.getName());
      if (!entry.isDirectory()) {
        listOfFiles.add(file);
      }
    }
    return listOfFiles;
  }

  /**
   * Creates a new empty file in a directory specified by the 'java.io.tmpdir' or the 'user.home'
   * system property, using given prefix and suffix strings to generate its name. For more
   * information see the documentation on the <code>java.io.File.createTempFile()</code> method.
   * 
   * @param prefix
   *          The given prefix string to be used in generating the file's name; must be at least
   *          three characters long.
   * @param suffix
   *          The given suffix string to be used in generating the file's name; may be
   *          <code>null</code>, in which case the suffix ".tmp" will be used.
   * @return The <code>File</code> object denoting the newly created file.
   * @throws IOException
   *           If a temporary directory not found or other I/O exception occurred.
   * @deprecated use Java 7 method for this see
   *             {@link java.io.File#createTempFile(String, String, File)}
   */
  @Deprecated
  public static File createTempFile(String prefix, String suffix) throws IOException {
    String tempDirPath = System.getProperty("java.io.tmpdir");
    if (tempDirPath == null) {
      tempDirPath = System.getProperty("user.home");
    }
    if (tempDirPath == null) {
      throw new IOException("could not find temporary directory");
    }
    File tempDir = new File(tempDirPath);
    if (!tempDir.isDirectory()) {
      throw new IOException("temporary directory not available");
    }
    return File.createTempFile(prefix, suffix, tempDir);
  }

  /**
   * Deletes a given directory, including all its subdirectories and files. Returns
   * <code>true</code> if the deletion was successful, otherwise returns <code>false</code>. In case
   * of unsuccessful deletion, calls <code>deleteOnExit()</code> method to request that files and
   * subdirs be deleted when the virtual machine terminates.
   * 
   * @param dir
   *          The given directory to be deleted.
   * @return <code>true</code> if the deletion was successful, otherwise <code>false</code>.
   * @throws java.io.IOException
   *           If any I/O exception occurs.
   */
  public static boolean deleteDirectory(File dir) throws IOException {
    boolean done = true;
    // list immediate files/subdirs in this dir
    File[] fileList = dir.listFiles();
    // first, delete plain files and sub-directories (recursive)
    for (int i = 0; i < fileList.length; i++) {
      File entry = fileList[i];
      if (entry.isDirectory()) {
        done = deleteDirectory(entry);
      } else if (!entry.delete()) {
        entry.deleteOnExit();
        done = false;
      }
    }
    // second, delete the root dir itself
    if (!dir.delete()) {
      dir.deleteOnExit();
      done = false;
    }
    return done;
  }

  /**
   * Extracts all files in a given JAR directory (including all its subdirectories) from a given JAR
   * file to a given target directory.
   * 
   * @param jarFile
   *          The given JAR file.
   * @param dirPath
   *          The given JAR directory.
   * @param targetDir
   *          The given target directory.
   * @return Total number of bytes extracted.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static long extractDirectoryFromJar(JarFile jarFile, String dirPath, File targetDir)
          throws IOException {
    return extractFilesFromJar(jarFile, targetDir, new DirFileFilter(dirPath, null));
  }

  /**
   * Extracts all files that have a given extension from a given JAR file to a given target
   * directory. To extract files without extension, use <code>null</code> as the
   * <code>fileExt</code> parameter.
   * 
   * @param jarFile
   *          The given JAR file.
   * @param fileExt
   *          The given file extension.
   * @param targetDir
   *          The given target directory.
   * @return Total number of bytes extracted.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static long extractFilesWithExtFromJar(JarFile jarFile, String fileExt, File targetDir)
          throws IOException {
    return extractFilesFromJar(jarFile, targetDir, new DirFileFilter(null, fileExt));
  }

  /**
   * Extracts all files from a given JAR file to a given target directory.
   * 
   * @param jarFile
   *          The given JAR file.
   * @param targetDir
   *          The given target directory.
   * @return Total number of bytes extracted.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static long extractFilesFromJar(JarFile jarFile, File targetDir) throws IOException {
    return extractFilesFromJar(jarFile, targetDir, null);
  }

  /**
   * Extracts files from a given JAR file to a given target directory, based on a given
   * <code>FileFilter</code> object.
   * 
   * @param jarFile
   *          The given JAR file.
   * @param targetDir
   *          The given target directory.
   * @param filter
   *          The given <code>FileFilter</code> object.
   * @return Total number of bytes extracted.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static long extractFilesFromJar(JarFile jarFile, File targetDir, FileFilter filter)
          throws IOException {
    long totalBytes = 0;
    byte[] block = new byte[4096];

    String prefix = normalizeToUnix(targetDir.getCanonicalPath());
    if (!prefix.endsWith(UNIX_SEPARATOR)) {
      prefix = prefix + UNIX_SEPARATOR_CHAR;
    }

    Enumeration<JarEntry> jarList = jarFile.entries();
    while (jarList.hasMoreElements()) {
      JarEntry jarEntry = jarList.nextElement();
      if (jarEntry.isDirectory()) {
        continue;
      }

      // check that file is accepted
      if (filter != null && !filter.accept(new File(jarEntry.getName()))) {
        continue;
      }

      // make sure the file directory exists
      File file = new File(targetDir, jarEntry.getName());

      if (!normalizeToUnix(file.getCanonicalPath()).startsWith(prefix)) {
        throw new IOException("Can only write within target folder [" + targetDir.getAbsolutePath()
                + "]. Please validate ZIP contents.");
      }

      File dir = file.getParentFile();
      if (!dir.exists() && !dir.mkdirs()) {
        throw new IOException("Could not create directory [" + dir.getAbsolutePath() + "]");
      }

      // extract file
      try (BufferedInputStream iStream = new BufferedInputStream(jarFile.getInputStream(jarEntry));
              BufferedOutputStream oStream = new BufferedOutputStream(new FileOutputStream(file))) {
        int bCount = 0;
        while ((bCount = iStream.read(block)) > 0) {
          totalBytes += bCount;
          oStream.write(block, 0, bCount);
        }
      }
    }

    return totalBytes;
  }

  /**
   * Constructs an absolute path of a given object, located in a given root directory, based on its
   * relative path in this directory.
   * 
   * @param rootDir
   *          The given root directory.
   * @param relativePath
   *          The given relative path of the object.
   * @return The absolute path for the given object, located in the given root directory.
   */
  public static String getAbsolutePath(File rootDir, String relativePath) {
    File object = new File(rootDir, relativePath);
    return object.getAbsolutePath();
  }

  /**
   * Identifies a given file name extension.
   * 
   * @param fileName
   *          The given file name.
   * @return The file name extension
   */
  public static String getFileNameExtension(String fileName) {
    StringBuffer buffer = new StringBuffer();
    int begIndex = fileName.lastIndexOf(DOT);
    if (begIndex > 0) {
      buffer.append(DOT);
      for (int i = begIndex + 1; i < fileName.length(); i++) {
        char ch = fileName.charAt(i);
        if (Character.isLetterOrDigit(ch)) {
          buffer.append(ch);
        } else {
          break;
        }
      }
    }
    return buffer.toString();
  }

  /**
   * Returns file size for a given file.
   * 
   * @param fileLocation
   *          The given file location - local file path or URL.
   * @return The given file size, if the specified file can be accessed, -1 otherwise.
   * @deprecated use Java 7 method for this see {@link java.nio.file.Files#size(Path)}
   */
  @Deprecated
  public static long getFileSize(String fileLocation) {
    long fileSize = 0;
    // choose file size method: local FS or HTTP
    File file = new File(fileLocation);
    if (file.isFile()) {
      fileSize = file.length();
    } else {
      try {
        URL fileUrl = new URL(fileLocation);
        URLConnection urlConn = fileUrl.openConnection();
        // See https://issues.apache.org/jira/browse/UIMA-1746
        urlConn.setUseCaches(false);
        fileSize = urlConn.getContentLength();
      } catch (IOException e) {
        fileSize = -1;
      }
    }
    return fileSize;
  }

  /**
   * Constructs a relative path of a given object, located in a given root directory, based on its
   * absolute path.
   * 
   * @param rootDir
   *          The given root directory.
   * @param absolutePath
   *          The given absolute path of the object.
   * @return The relative path of the given object, located in the given root directory.
   */
  public static String getRelativePath(File rootDir, String absolutePath) {
    String rootDirPath = normalizeToUnix(rootDir.getAbsolutePath());
    String objectPath = normalizeToUnix(absolutePath);
    if (objectPath.startsWith(rootDirPath)) {
      objectPath = objectPath.substring(rootDirPath.length());
    }
    if (objectPath.startsWith("/")) {
      objectPath = objectPath.substring(1);
    }
    return objectPath;
  }

  /**
   * Makes and attempt to identify possible UTF signature (BOM) in a given sequence of bytes.
   * Returns the identified UTF signature name or <code>null</code>, if the signature could not be
   * identified. For more on UTF and its signatures see
   * <a href="http://www.unicode.org/faq/utf_bom.html" target="_blank"> FAQ - UTF and BOM</a>.
   * 
   * @param prefix
   *          The given sequence of bytes to analyze.
   * @param length
   *          The length of the given sequence of bytes.
   * @return The UTF signature name or <code>null</code>, if the signature could not be identified.
   */
  public static String identifyUtfSignature(int[] prefix, int length) {
    String utfSignature = null;
    if (length == 3) {
      // check for UTF-8 signature
      if (prefix[0] == 0xEF && prefix[1] == 0xBB && prefix[2] == 0xBF) {
        utfSignature = UTF8_ENCODING;
      }
    } else if (length == 2) {
      // check for UTF-16 signature
      if (prefix[0] == 0xFE && prefix[1] == 0xFF) {
        utfSignature = "UTF-16BE";
      } else if (prefix[0] == 0xFF && prefix[1] == 0xFE) {
        utfSignature = "UTF-16LE";
      }
    } else if (length == 4) {
      // check for UTF-32 signature
      if (prefix[0] == 0x00 && prefix[1] == 0x00 && prefix[2] == 0xFE && prefix[3] == 0xFF) {
        utfSignature = "UTF-32BE";
      } else if (prefix[0] == 0xFF && prefix[1] == 0xFE && prefix[2] == 0x00 && prefix[3] == 0x00) {
        utfSignature = "UTF-32LE";
      }
    }
    return utfSignature;
  }

  /**
   * Returns <code>true</code>, if a given text file contains only ASCII characters, otherwise
   * returns <code>false</code>.
   * 
   * @param textFile
   *          The given text file.
   * @return <code>true</code>, if the given text file contains only ASCII characters,
   *         <code>false</code> otherwise.
   * @throws IOException
   *           If an I/O exception occurred.
   */
  public static boolean isAsciiFile(File textFile) throws IOException {
    try (FileInputStream iStream = new FileInputStream(textFile)) {
      return isAsciiStream(iStream);
    }
  }

  /**
   * Returns <code>true</code>, if a given input stream contains only ASCII characters, otherwise
   * returns <code>false</code>.
   * 
   * @param iStream
   *          The given input stream.
   * @return <code>true</code>, if the given input stream contains only ASCII characters,
   *         <code>false</code> otherwise.
   * @throws IOException
   *           If an I/O exception occurred.
   */
  public static boolean isAsciiStream(InputStream iStream) throws IOException {
    boolean isAscii = true;
    int nextByte = 0;
    while ((nextByte = iStream.read()) >= 0) {
      if (nextByte > 127) {
        isAscii = false;
        break;
      }
    }
    return isAscii;
  }

  /**
   * Loads a list of non-empty EOL-delimited strings from a given text stream.
   * 
   * @param iStream
   *          The given input text stream.
   * @return The array of non-empty strings loaded from the given text stream.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static String[] loadListOfStrings(BufferedReader iStream) throws IOException {
    String[] outputArray = null;
    List<String> outputList = new ArrayList<>();
    String line = null;
    while ((line = iStream.readLine()) != null) {
      String string = line.trim();
      if (string.length() > 0) {
        outputList.add(string);
      }
    }
    if (outputList.size() > 0) {
      outputArray = new String[outputList.size()];
      outputList.toArray(outputArray);
    }
    return (outputArray != null) ? outputArray : Constants.EMPTY_STRING_ARRAY;
  }

  /**
   * Loads a list of non-empty EOL-delimited strings from a given text file using the default file
   * encoding.
   * 
   * @param textFile
   *          The given text file.
   * @return The array of non-empty strings loaded from the given text file.
   * @throws IOException
   *           If any I/O exception occurred.
   * @deprecated use Java 7 method for this see
   *             {@link java.nio.file.Files#readAllLines(Path, Charset)}
   */
  @Deprecated
  public static String[] loadListOfStrings(File textFile) throws IOException {
    String[] outputArray;
    try (BufferedReader iStream = new BufferedReader(
            new InputStreamReader(new FileInputStream(textFile)))) {
      outputArray = loadListOfStrings(iStream);
    }
    return (outputArray != null) ? outputArray : Constants.EMPTY_STRING_ARRAY;
  }

  /**
   * Loads a list of non-empty EOL-delimited strings from a given remote text file.
   * 
   * @param textFileURL
   *          The URL of the given input text file.
   * @return The array of non-empty strings loaded from the given text file.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static String[] loadListOfStrings(URL textFileURL) throws IOException {
    URLConnection urlConnection = textFileURL.openConnection();
    // See https://issues.apache.org/jira/browse/UIMA-1746
    urlConnection.setUseCaches(false);
    String[] outputArray;
    try (BufferedReader iStream = new BufferedReader(
            new InputStreamReader(urlConnection.getInputStream()))) {
      outputArray = loadListOfStrings(iStream);
    }
    return (outputArray != null) ? outputArray : Constants.EMPTY_STRING_ARRAY;
  }

  /**
   * Loads a specified properties file from a given JAR file.
   * 
   * @param propFilePath
   *          The given properties file path in the JAR file.
   * @param jarFile
   *          The given JAR file.
   * @return <code>Properties</code> object containing loaded properties, or <code>null</code>, if
   *         the properties file was not found in the given JAR file.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static Properties loadPropertiesFromJar(String propFilePath, JarFile jarFile)
          throws IOException {
    Properties properties = null;
    String name = normalizeToUnix(propFilePath);
    JarEntry jarEntry = jarFile.getJarEntry(name);
    if (jarEntry != null) {
      try (InputStream iStream = jarFile.getInputStream(jarEntry)) {
        properties = new Properties();
        properties.load(iStream);
      }
    }
    return properties;
  }

  /**
   * Loads a text file associated with a given input stream.
   * 
   * @param iStream
   *          The given text input stream.
   * @return The content of the text file.
   * @throws IOException
   *           If any I/O exception occurs.
   */
  public static String loadTextFile(BufferedReader iStream) throws IOException {
    try (StringWriter buffer = new StringWriter(); PrintWriter writer = new PrintWriter(buffer);) {
      String line = null;
      while ((line = iStream.readLine()) != null) {
        writer.println(line);
      }
      return buffer.toString();
    }
  }

  /**
   * Loads a given local text file using the default file encoding.
   * 
   * @return The content of the text file.
   * @param textFile
   *          The given text file.
   * @throws IOException
   *           If any I/O exception occurs.
   * @deprecated use main file util for this, see
   *             {@link org.apache.uima.util.FileUtils#file2String(File)} if using the default
   *             charset is OK
   */
  @Deprecated
  public static String loadTextFile(File textFile) throws IOException {
    try (BufferedReader iStream = new BufferedReader(new FileReader(textFile))) {
      return loadTextFile(iStream);
    }
  }

  /**
   * Loads a given local text file using a specified file encoding.
   * 
   * @return The content of the text file.
   * @param textFile
   *          The given text file.
   * @param encoding
   *          The given text file encoding name.
   * @throws IOException
   *           If any I/O exception occurs.
   * @deprecated use main file util for this, see
   *             {@link org.apache.uima.util.FileUtils#file2String(File, String)} if using the
   *             default Charset is OK
   */
  @Deprecated
  public static String loadTextFile(File textFile, String encoding) throws IOException {
    try (BufferedReader iStream = new BufferedReader(
            new InputStreamReader(new FileInputStream(textFile), encoding))) {
      return loadTextFile(iStream);
    }
  }

  /**
   * Loads a given remote text file.
   * 
   * @param textFileURL
   *          The given text file URL.
   * @return The content of the text file.
   * @throws IOException
   *           If any I/O exception occurs.
   */
  public static String loadTextFile(URL textFileURL) throws IOException {
    URLConnection urlConnection = textFileURL.openConnection();
    // See https://issues.apache.org/jira/browse/UIMA-1746
    urlConnection.setUseCaches(false);
    return loadTextFile(urlConnection);
  }

  /**
   * Loads a given remote text file.
   * 
   * @param urlConnection
   *          The given URL connection.
   * @return The content of the text file.
   * @throws IOException
   *           If any I/O exception occurs.
   */
  public static String loadTextFile(URLConnection urlConnection) throws IOException {
    // See https://issues.apache.org/jira/browse/UIMA-1746
    urlConnection.setUseCaches(false);
    try (BufferedReader iStream = new BufferedReader(
            new InputStreamReader(urlConnection.getInputStream()))) {
      return loadTextFile(iStream);
    }
  }

  /**
   * Loads a specified text file from a given JAR file.
   * 
   * @param filePath
   *          The specified text file path inside the JAR file.
   * @param jarFile
   *          The given JAR file.
   * @return The content of the text specified file, or <code>null</code>, if the text file was not
   *         found in the given JAR file.
   * @throws IOException
   *           If any I/O exception occurs.
   */
  public static String loadTextFileFromJar(String filePath, JarFile jarFile) throws IOException {
    String content = null;
    String name = normalizeToUnix(filePath);
    JarEntry jarEntry = jarFile.getJarEntry(name);
    if (jarEntry != null) {
      try (BufferedReader iStream = new BufferedReader(
              new InputStreamReader(jarFile.getInputStream(jarEntry)))) {
        content = loadTextFile(iStream);
      }
    }
    return content;
  }

  /**
   * Converts a given input file path into a valid file URL string.
   * 
   * @param path
   *          The given file path to be converted.
   * @return The file URL string for the specified file.
   */
  public static String localPathToFileUrl(String path) {
    // get absolute path
    File file = new File(path);
    String absPath = normalizeToUnix(file.getAbsolutePath());
    // construct file URL
    StringBuffer urlBuffer = new StringBuffer("file:///");
    urlBuffer.append(absPath.replace(':', '|'));
    String fileUrlString = urlBuffer.toString().replaceAll(" ", "%20");
    URL fileUrl = null;
    try {
      fileUrl = new URL(fileUrlString);
    } catch (MalformedURLException e) {
      fileUrl = null;
    }
    return (fileUrl != null) ? fileUrl.toExternalForm() : fileUrlString;
  }

  /**
   * Moves a given source file to a given destination directory.
   * 
   * @param source
   *          The given source file.
   * @param destinationDir
   *          The given destination directory.
   * @return <code>true</code> if the move operation completed successfully, <code>false</code>
   *         otherwise.
   * @throws IOException
   *           If any I/O exception occurred.
   * @deprecated use Java 7 for this see {@link java.nio.file.Files#move(Path, Path, CopyOption...)}
   */
  @Deprecated
  public static boolean moveFile(File source, File destinationDir) throws IOException {
    boolean completed = false;
    File destination = new File(destinationDir, source.getName());
    if (destination.exists()) {
      destination.delete();
    }
    if (copyFile(source, destination)) {
      completed = source.delete();
    }
    return completed;
  }

  /**
   * Replaces all occurrences of a given regular expression with a given string in a given text
   * file. Supports only 1 file encoding - ASCII - for all general text files. Supports 2 encodings
   * - UTF-8 (ASCII) and UTF-16 for XML files.
   * 
   * @param textFile
   *          The given text file.
   * @param subStringRegex
   *          The given regular expression string to be replaced.
   * @param replacement
   *          The given replacement string.
   * @return The number of actual string replacements performed.
   * @throws IOException
   *           If any I/O exception occurs.
   */
  public static int replaceStringInFile(File textFile, String subStringRegex, String replacement)
          throws IOException {
    int counter = 0;
    // for general text file - supporting ASCII encoding only
    String encoding = ASCII_ENCODING;
    // check file extension
    int extIndex = textFile.getName().lastIndexOf(DOT);
    String fileExt = (extIndex > 0) ? textFile.getName().substring(extIndex) : null;
    if (XML_EXTENSION.equalsIgnoreCase(fileExt)) {
      // for XML file - supporting UTF-8 (ASCII) and UTF-16 encodings
      String xmlEncoding = XMLUtil.detectXmlFileEncoding(textFile);
      if (xmlEncoding != null) {
        encoding = xmlEncoding;
      } else {
        encoding = UTF8_ENCODING;
      }
    }
    // load text file, using supported encoding
    String fileContent = loadTextFile(textFile, encoding);

    boolean done = false;
    File backupFile = null;
    // get pattern for given regex
    Pattern pattern = Pattern.compile(subStringRegex);
    // format replacement string
    String replaceWith = StringUtil.toRegExpReplacement(replacement);
    try {
      // save backup copy of input file
      backupFile = new File(textFile.getAbsolutePath() + BACKUP_EXTENSION);
      if (backupFile.exists()) {
        backupFile.delete();
      }
      if (!textFile.renameTo(backupFile)) {
        throw new IOException("can't save backup copy of " + textFile.getAbsolutePath());
      }
      try (BufferedReader sReader = new BufferedReader(new StringReader(fileContent));
              PrintStream fStream = new PrintStream(new FileOutputStream(textFile), true,
                      encoding);) {
        String srcLine = null;
        while ((srcLine = sReader.readLine()) != null) {
          // count pattern matches in the source string
          Matcher matcher = pattern.matcher(srcLine);
          while (matcher.find()) {
            counter++;
          }
          // replace all pattern matches in the source string
          String resLine = srcLine.replaceAll(subStringRegex, replaceWith);
          fStream.println(resLine);
        }
      }
      done = true;
    } catch (IOException exc) {
      throw exc;
    } catch (Throwable err) {
      if (err instanceof IOException) {
        throw new IOException(err.toString() + " in " + textFile.getAbsolutePath());
      }
      throw new RuntimeException(err.toString() + " in " + textFile.getAbsolutePath());
    } finally {
      if (done) {
        // remove backup file
        if (backupFile != null) {
          backupFile.delete();
        }
      } else {
        // restore input file
        textFile.delete();
        if (backupFile != null) {
          backupFile.renameTo(textFile);
        }
      }
    }
    return counter;
  }

  /**
   * Sorts a given list of files by the 'last modified' time in the descending order.
   * 
   * @param fileList
   *          The given list of files.
   * @return The list of files sorted by the 'last modified' time in the descending order.
   */
  public static SortedSet<File> sortFileListByTime(Collection<File> fileList) {
    TreeSet<File> set = new TreeSet<>(new FileTimeComparator());
    set.addAll(fileList);
    return set;
  }

  /**
   * Zips the contents of a given directory. The output ZIP file, by default, is created in the
   * given directory, and its name is the given directory name with 'zip' extension.
   * 
   * @param dir2zip
   *          The given directory to be zipped.
   * @return The output ZIP file.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static File zipDirectory(File dir2zip) throws IOException {
    // construct zipped file path
    String zipFileName = dir2zip.getName() + ZIP_EXTENSION;
    File zipFile = new File(dir2zip, zipFileName);
    return zipDirectory(dir2zip, zipFile);
  }

  /**
   * Zips the contents of a given directory to a given output ZIP file.
   * 
   * @param dir2zip
   *          The given directory to be zipped.
   * @param zippedFile
   *          The given output ZIP file.
   * @return The output ZIP file.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static File zipDirectory(File dir2zip, File zippedFile) throws IOException {
    try (ZipOutputStream zoStream = new ZipOutputStream(new FileOutputStream(zippedFile))) {
      // open compressed output stream
      // add output zip file to exclusions
      File[] excludeFiles = new File[1];
      excludeFiles[0] = zippedFile;
      zipDirectory(dir2zip, zoStream, dir2zip, excludeFiles);
    }
    return zippedFile;
  }

  /**
   * Zips the contents of a given directory to a given ZIP output stream. Paths of file entries in
   * the ZIP stream are taken relatively to a given reference directory. If the reference directory
   * is <code>null</code>, the file paths are taken relatively to the given directory to be zipped.
   * The method allows to specify the list of files (or dirs) that should not be zipped.
   * 
   * @param dir2zip
   *          The given directory to be zipped.
   * @param zoStream
   *          The given ZIP output stream.
   * @param referenceDir
   *          The given reference directory or <code>null</code>.
   * @param excludeFiles
   *          The given list of files (or dirs) that should not be zipped.
   * @return The ZIP output stream.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static ZipOutputStream zipDirectory(File dir2zip, ZipOutputStream zoStream,
          File referenceDir, File[] excludeFiles) throws IOException {
    byte[] block = new byte[4096];
    int inBytes = 0;

    // get list of all files/dirs in the given directory
    File[] dirFileList = dir2zip.listFiles();
    // compress all files and sub-dirs
    for (int i = 0; i < dirFileList.length; i++) {
      File entry = dirFileList[i];
      // check if this entry is not in the list of exclusions
      boolean isExcluded = false;
      for (int n = 0; n < excludeFiles.length; n++) {
        if (entry.equals(excludeFiles[n])) {
          isExcluded = true;
          break;
        }
      }
      if (isExcluded) {
        continue;
      }
      // for each file - add ZipEntry and compress the file
      if (entry.isFile()) {
        // open input stream
        try (FileInputStream iStream = new FileInputStream(entry)) {
          // put ZipEntry for the file
          String zipEntryName = (referenceDir != null)
                  ? getRelativePath(referenceDir, entry.getAbsolutePath())
                  : getRelativePath(dir2zip, entry.getAbsolutePath());
          ZipEntry zipEntry = new ZipEntry(zipEntryName);
          zoStream.putNextEntry(zipEntry);
          // read input stream and write to output stream
          while ((inBytes = iStream.read(block)) > 0) {
            zoStream.write(block, 0, inBytes);
          }
        }
      } else if (entry.isDirectory()) { // zip sub-dir recursively
        zipDirectory(entry, zoStream, referenceDir, excludeFiles);
      }
    }

    return zoStream;
  }

  /**
   * Zips a given file. The output ZIP file, by default, is created in the same directory, as the
   * given input file, and has the same name, as the given input file with 'zip' extension.
   * 
   * @param file2zip
   *          The file to be zipped.
   * @return The output ZIP file.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static File zipFile(File file2zip) throws IOException {
    // construct zipped file path
    String zipFileName = file2zip.getName();
    int extIndex = zipFileName.lastIndexOf(DOT);
    zipFileName = (extIndex >= 0) ? zipFileName.substring(0, extIndex) + ZIP_EXTENSION
            : zipFileName + ZIP_EXTENSION;
    File zipFile = new File(file2zip.getParentFile(), zipFileName);
    return zipFile(file2zip, zipFile);
  }

  /**
   * Zips a given file to a given output ZIP file.
   * 
   * @param file2zip
   *          The file to be zipped.
   * @param zippedFile
   *          The given output ZIP file.
   * @return The output ZIP file.
   * @throws IOException
   *           If any I/O exception occurred.
   */
  public static File zipFile(File file2zip, File zippedFile) throws IOException {
    byte[] block = new byte[4096];
    int inBytes = 0;
    try (FileInputStream iStream = new FileInputStream(file2zip);
            ZipOutputStream oStream = new ZipOutputStream(new FileOutputStream(zippedFile));) {
      // create ZipEntry, using input file name
      ZipEntry zipEntry = new ZipEntry(file2zip.getName());
      // add new ZipEntry
      oStream.putNextEntry(zipEntry);
      // read input stream and write to output stream
      while ((inBytes = iStream.read(block)) > 0) {
        oStream.write(block, 0, inBytes);
      }
    }
    return zippedFile;
  }
}
