package org.broadinstitute.sting.queue.util import java.io.{IOException, File} /** * A collection of utilities for modifying java.io. */ object IOUtils { /** The current directory "." */ val CURRENT_DIR = new File(".") /** * Returns the sub path rooted at the parent. * If the sub path is already absolute, returns the sub path. * If the parent is the current directory, returns the sub path. * If the sub bath is the current directory, returns the parent. * Else returns new File(parent, subPath) * @param parent The parent directory * @param path The sub path to append to the parent, if the path is not absolute. * @return The absolute path to the file in the parent dir if the path was not absolute, otherwise the original path. */ def subDir(dir: File, path: String): File = subDir(dir, new File(path)) /** * Returns the sub path rooted at the parent. * If the sub path is already absolute, returns the sub path. * If the parent is the current directory, returns the sub path. * If the sub path is the current directory, returns the parent. * Else returns new File(parent, subPath) * @param parent The parent directory * @param file The sub path to append to the parent, if the path is not absolute. * @return The absolute path to the file in the parent dir if the path was not absolute, otherwise the original path. */ def subDir(parent: File, file: File): File = { val parentAbs = absolute(parent) val fileAbs = absolute(file) val currentAbs = absolute(CURRENT_DIR) if (parentAbs == currentAbs && fileAbs == currentAbs) absolute(CURRENT_DIR.getCanonicalFile) else if (parentAbs == currentAbs || file.isAbsolute) fileAbs else if (fileAbs == currentAbs) parentAbs else absolute(new File(parentAbs, file.getPath)) } /** * Resets the parent of the file to the directory. * @param dir New parent directory. * @param file Path to the file to be re-rooted. * @return Absolute path to the new file. */ def resetParent(dir: File, file: File) = absolute(subDir(dir, file.getName)) /** * Creates a scatterGatherTempDir directory with the prefix and optional suffix. * @param prefix Prefix for the directory name. * @param suffix Optional suffix for the directory name. Defaults to "". * @return The created temporary directory. * @throws IOException if the directory could not be created. */ def tempDir(prefix: String, suffix: String = "") = { // Keep the temp directory from having pluses in it, which can cause problems with the Google Reflections library. // see also: http://benjchristensen.com/2009/09/22/mac-osx-10-6-java-java-io-tmpdir/ if (System.getProperty("java.io.tmpdir").startsWith("/var/folders/")) System.setProperty("java.io.tmpdir", "/tmp/"); val tempDirParent = new File(System.getProperty("java.io.tmpdir")) if (!tempDirParent.exists && !tempDirParent.mkdirs) throw new IOException("Could not create temp directory: " + tempDirParent) val temp = File.createTempFile(prefix + "-", suffix) if (!temp.delete) throw new IOException("Could not delete sub file: " + temp.getAbsolutePath()) if (!temp.mkdir) throw new IOException("Could not create sub directory: " + temp.getAbsolutePath()) absolute(temp) } /** * Returns the directory at the number of levels deep. * For example 2 levels of /path/to/dir will return /path/to * @param dir Directory path. * @param level how many levels deep from the root. * @return The path to the parent directory that is level-levels deep. */ def dirLevel(dir: File, level: Int): File = { var directories = List.empty[File] var parentDir = absolute(dir) while (parentDir != null) { directories +:= parentDir parentDir = parentDir.getParentFile } if (directories.size <= level) directories.last else directories(level) } def absolute(file: File) = { var fileAbs = file.getAbsoluteFile var names = List.empty[String] while (fileAbs != null) { val name = fileAbs.getName fileAbs = fileAbs.getParentFile if (name == ".") { /* skip */ /* TODO: What do we do for ".."? } else if (name == "..") { CentOS tcsh says use getCanonicalFile: ~ $ mkdir -p test1/test2 ~ $ ln -s test1/test2 test3 ~ $ cd test3/.. ~/test1 $ Mac bash says keep going with getAbsoluteFile: ~ $ mkdir -p test1/test2 ~ $ ln -s test1/test2 test3 ~ $ cd test3/.. ~ $ For now, leave it and let the shell figure it out. */ } else { names +:= name } } new File(names.mkString("/", "/", "")) } }