package org.specs.io;
import java.io._
import java.util.regex._
import org.specs.collection.JavaConversions
import scala.collection.mutable.Queue
import org.specs.log.Log
/**
* The fs object offers a simple interface to the file system (see the description of the FileSystem trait)
*/
object fs extends FileSystem
/**
* The FileSystem trait abstracts file system operations to allow easier mocking of file system related functionalities.
* <p>
* It mixes the <code>FileReader</code> and <code>FileWriter</code> traits to provide easy read/write operations.
*/
trait FileSystem extends FileReader with FileWriter with JavaConversions {
object logger extends Log with ConsoleOutput
/**
* @param path glob expression, for example: <code>./dir/**/*.xml</code>
* @return the list of paths represented by the "glob" definition <code>path</path>
*/
def filePaths(path: String): List[String] = {
var pattern = globToPattern(path)
if (isDir(path))
pattern += "/*.*"
val result = new Queue[String]
collectFiles(result, new File("."), pattern)
result.toList
}
/**
* @param result list of collected file paths
* @param file current file being examined
* @param pattern regular expression which should be matching the file path
*/
private def collectFiles(result: Queue[String], file: File, pattern: String): Unit = {
logger.debug("try to accept " + file.getPath.replace("\\", "/") + " with " + pattern)
if (file.isFile && file.getPath.replace("\\", "/").matches(pattern)) {
logger.debug("got a match")
result += (file.getPath)
}
else if (file.listFiles != null) {
file.listFiles.foreach { collectFiles(result, _, pattern) }
}
}
/**
* @return the regular expression equivalent to a glob pattern (see the specs for examples)
*/
def globToPattern(glob: String): String = {
val star = "<STAR>"
val authorizedNamePattern = "[^\\/\\?<>\\|\\" + star + ":\"]" + star
var pattern = glob.replace("\\", "/")
.replace(".", "\\.")
.replace("**/", "(" + authorizedNamePattern + "/)" + star)
.replace("*", authorizedNamePattern)
.replace(star, "*")
if (!pattern.startsWith("\\./"))
pattern = "\\./" + pattern
pattern
}
/**
* @return true if the File represented by this path is a directory
*/
def isDir(path: String) = isDirectory(path)
/**
* creates a directory for a given path
*/
def createDir(path: String) = (new File(path)).mkdirs
/**
* creates a file for a given path. Create the parent directory if necessary
*/
def createFile(path: String) = {
if (!new File(path).getParentFile.exists) createDir(new File(path).getParent)
new File(path).createNewFile
}
/**
* deletes the directory and all directory contents at the specified path and return the parent path of that directory
*/
def removeDir(path: String): String = {
val dir = new File(path)
if (dir.isDirectory) {
if (dir.listFiles == null || dir.listFiles.isEmpty)
dir.delete
else {
dir.listFiles.foreach { file =>
if (file.isFile)
file.delete
else
removeDir(file.getPath)
}
dir.delete
}
}
dir.getParent
}
/** @return true if the file exists */
def exists(path: String) = path != null && new File(path).exists
/** @return true if the file can be read */
def canRead(path: String) = path != null && new File(path).canRead
/** @return true if the file can be written */
def canWrite(path: String) = path != null && new File(path).canWrite
/** @return true if the file is absolute */
def isAbsolute(path: String) = path != null && new File(path).isAbsolute
/** @return true if the file is a file */
def isFile(path: String) = path != null && new File(path).isFile
/** @return true if the file is a directory */
def isDirectory(path: String) = path != null && new File(path).isDirectory
/** @return true if the file is hidden */
def isHidden(path: String) = path != null && new File(path).isHidden
/** @return the file name */
def getName(path: String) = new File(path).getName
/** @return the file absolute path */
def getAbsolutePath(path: String) = new File(path).getAbsolutePath
/** @return the file canonical path */
def getCanonicalPath(path: String) = new File(path).getCanonicalPath
/** @return the file parent path */
def getParent(path: String) = new File(path).getParent
/** @return the files of that directory */
def listFiles(path: String): List[String] = if (new File(path).list == null) List() else new File(path).list.toList
}