//# 0 errors, 58 messages
//#
/*
    //#fileutils.java:1:1: class: net.sourceforge.pebble.util.FileUtils
 * Copyright (c) 2003-2006, Simon Brown
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   - Neither the name of Pebble nor the names of its contributors may
 *     be used to endorse or promote products derived from this software
 *     without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package net.sourceforge.pebble.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.util.Properties;

/**
 * A collection of utility methods for manipulating files.
 *
 * @author    Simon Brown
 */
public final class FileUtils {
    //#fileutils.java:48: method: void net.sourceforge.pebble.util.FileUtils.net.sourceforge.pebble.util.FileUtils()
    //#fileutils.java:48: end of method: void net.sourceforge.pebble.util.FileUtils.net.sourceforge.pebble.util.FileUtils()

  /** the logger used by this class */
  private static final Log log = LogFactory.getLog(FileUtils.class);
    //#fileutils.java:51: method: net.sourceforge.pebble.util.FileUtils.net.sourceforge.pebble.util.FileUtils__static_init
    //#fileutils.java:51: Warning: method not available
    //#    -- call on Log org.apache.commons.logging.LogFactory:getLog(Class)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.util.FileUtils
    //#    method: net.sourceforge.pebble.util.FileUtils__static_init
    //#    unanalyzed callee: Log org.apache.commons.logging.LogFactory:getLog(Class)
    //#output(net.sourceforge.pebble.util.FileUtils__static_init): __Descendant_Table[net/sourceforge/pebble/util/FileUtils]
    //#output(net.sourceforge.pebble.util.FileUtils__static_init): localFileNameMap
    //#output(net.sourceforge.pebble.util.FileUtils__static_init): log
    //#output(net.sourceforge.pebble.util.FileUtils__static_init): new Properties(FileUtils__static_init#1) num objects
    //#new obj(net.sourceforge.pebble.util.FileUtils__static_init): new Properties(FileUtils__static_init#1)
    //#presumption(net.sourceforge.pebble.util.FileUtils__static_init): java.lang.Class:getClassLoader(...)@59 != null
    //#presumption(net.sourceforge.pebble.util.FileUtils__static_init): org.apache.commons.logging.LogFactory:getLog(...)@51 != null
    //#post(net.sourceforge.pebble.util.FileUtils__static_init): __Descendant_Table[net/sourceforge/pebble/util/FileUtils] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.util.FileUtils__static_init): localFileNameMap in Addr_Set{null,&new Properties(FileUtils__static_init#1)}
    //#post(net.sourceforge.pebble.util.FileUtils__static_init): (soft) log != null
    //#post(net.sourceforge.pebble.util.FileUtils__static_init): new Properties(FileUtils__static_init#1) num objects <= 1
    //#test_vector(net.sourceforge.pebble.util.FileUtils__static_init): java.lang.ClassLoader:getResourceAsStream(...)@59: Addr_Set{null}, Inverse{null}

  /** the local content type map */
  private static Properties localFileNameMap;

  static {
    try {
      localFileNameMap = new Properties();
      InputStream in = FileUtils.class.getClassLoader().getResourceAsStream("content-types.properties");
      if (in != null) {
        localFileNameMap.load(in);
        in.close();
      }
    } catch (IOException ioe) {
      log.error("Could not load content types.", ioe);
    //#fileutils.java:65: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:error(Object, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.util.FileUtils
    //#    method: net.sourceforge.pebble.util.FileUtils__static_init
    //#    unanalyzed callee: void org.apache.commons.logging.Log:error(Object, Throwable)
    //#fileutils.java:65: end of method: net.sourceforge.pebble.util.FileUtils.net.sourceforge.pebble.util.FileUtils__static_init
    }
  }

  /**
   * Determines whether a given file is underneath a given root.
   *
   * @param root    the root directory
   * @param file    the file to test
   * @return    true if the file is underneath the root,
   *            false otherwise or if this can not be determined because
   *            of security constraints in place
   */
  public static boolean underneathRoot(File root, File file) {
    try {
      // first of all, find the root directory for this type of file
      root = root.getCanonicalFile();
    //#fileutils.java:81: method: bool net.sourceforge.pebble.util.FileUtils.underneathRoot(File, File)
    //#input(bool underneathRoot(File, File)): file
    //#input(bool underneathRoot(File, File)): root
    //#output(bool underneathRoot(File, File)): return_value
    //#pre[1] (bool underneathRoot(File, File)): (soft) file != null
    //#pre[2] (bool underneathRoot(File, File)): (soft) root != null
    //#post(bool underneathRoot(File, File)): init'ed(return_value)
    //#test_vector(bool underneathRoot(File, File)): java.io.File:equals(...)@84: {0}, {1}
      file = file.getCanonicalFile();
      while (file != null) {
        if (file.equals(root)) {
          return true;
        } else {
          file = file.getParentFile();
        }
      }
    } catch (IOException ioe) {
      return false;
    }

    return false;
    //#fileutils.java:94: end of method: bool net.sourceforge.pebble.util.FileUtils.underneathRoot(File, File)
  }

  /**
   * Deletes a file, including all files and sub-directories if the
   * specified file is a directory.
   *
   * @param directory   a File instance representing the directory to delete
   */
  public static void deleteFile(File directory) {
    File files[] = directory.listFiles();
    //#fileutils.java:104: method: void net.sourceforge.pebble.util.FileUtils.deleteFile(File)
    //#input(void deleteFile(File)): directory
    //#pre[1] (void deleteFile(File)): directory != null
    //#presumption(void deleteFile(File)): files.length@104 <= 4_294_967_295
    //#presumption(void deleteFile(File)): files[i]@104 != null
    //#unanalyzed(void deleteFile(File)): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(void deleteFile(File)): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(void deleteFile(File)): Effects-of-calling:deleteFile
    //#unanalyzed(void deleteFile(File)): Effects-of-calling:java.io.File:delete
    //#test_vector(void deleteFile(File)): java.io.File:isDirectory(...)@107: {0}, {1}
    //#test_vector(void deleteFile(File)): java.io.File:listFiles(...)@104: Addr_Set{null}, Inverse{null}
    if (files != null) {
      for (int i = 0; i < files.length; i++) {
        if (files[i].isDirectory()) {
          deleteFile(files[i]);
        } else {
          files[i].delete();
        }
      }
    }

    directory.delete();
  }
    //#fileutils.java:116: end of method: void net.sourceforge.pebble.util.FileUtils.deleteFile(File)

  /**
   * Copies a file.
   *
   * @param source        the source File
   * @param destination   the destination File
   */
  public static void copyFile(File source, File destination) throws IOException {
    FileChannel srcChannel = new FileInputStream(source).getChannel();
    //#fileutils.java:125: method: void net.sourceforge.pebble.util.FileUtils.copyFile(File, File)
    //#input(void copyFile(File, File)): destination
    //#input(void copyFile(File, File)): source
    //#presumption(void copyFile(File, File)): java.io.FileInputStream:getChannel(...)@125 != null
    //#presumption(void copyFile(File, File)): java.io.FileOutputStream:getChannel(...)@126 != null
    FileChannel dstChannel = new FileOutputStream(destination).getChannel();
    dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
    srcChannel.close();
    dstChannel.close();
  }
    //#fileutils.java:130: end of method: void net.sourceforge.pebble.util.FileUtils.copyFile(File, File)

  /**
   * Gets the content type for the specified filename.
   *
   * @param name    the name of a file
   * @return  a MIME type, or application/octet-stream if one can't be found
   */
  public static String getContentType(String name) {
    String contentType;
    FileNameMap fileNameMap = URLConnection.getFileNameMap();
    //#fileutils.java:140: method: String net.sourceforge.pebble.util.FileUtils.getContentType(String)
    //#input(String getContentType(String)): localFileNameMap
    //#input(String getContentType(String)): name
    //#output(String getContentType(String)): return_value
    //#pre[1] (String getContentType(String)): (soft) localFileNameMap != null
    //#pre[2] (String getContentType(String)): (soft) name != null
    //#presumption(String getContentType(String)): java.net.URLConnection:getFileNameMap(...)@140 != null
    //#post(String getContentType(String)): init'ed(return_value)
    //#test_vector(String getContentType(String)): java.lang.String:lastIndexOf(...)@144: {-2_147_483_648..-1}, {0..4_294_967_295}
    //#test_vector(String getContentType(String)): java.net.FileNameMap:getContentTypeFor(...)@141: Inverse{null}, Addr_Set{null}
    contentType = fileNameMap.getContentTypeFor(name);

    if (contentType == null) {
      int index = name.lastIndexOf(".");
      if (index > -1) {
        contentType = localFileNameMap.getProperty(name.substring(index));
      }
    }

    return contentType;
    //#fileutils.java:150: end of method: String net.sourceforge.pebble.util.FileUtils.getContentType(String)
  }

}    //#fileutils.java:: end of class: net.sourceforge.pebble.util.FileUtils
