All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.specs.io.FileSystem.scala Maven / Gradle / Ivy

/**
 * Copyright (c) 2007-2009 Eric Torreborre 
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software. Neither the name of specs nor the names of its contributors may be used to endorse or promote
 * products derived from this software without specific prior written permission.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
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
import java.net.URL
import java.util.zip._
import org.specs.specification.Tagged
import org.specs.specification.Tag
/**
 * 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.
 * 

* It mixes the FileReader and FileWriter traits to provide easy read/write operations. */ trait FileSystem extends FileReader with FileWriter { import org.specs.collection.JavaCollectionsConversion._ object logger extends Log with ConsoleOutput /** * @param path glob expression, for example: ./dir/**/*.xml * @return the list of paths represented by the "glob" definition 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 = "" 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 /** * 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 /** * copy the content of a directory to another. * @param url url of the directory to copy * @param dest destination directory path */ def copyDir(url: URL, dest: String): Unit = copyDir(new File(url.toURI).getPath, dest) /** * copy the content of a directory to another. * @param url url of the directory to copy * @param dest destination directory path * @param included names for included files * @param excluded names for excluded files */ def copyDir(url: URL, dest: String, tagged: Tagged): Unit = copyDir(new File(url.toURI).getPath, dest, tagged) /** * copy the content of a directory to another. * @param path path of the directory to copy * @param dest destination directory path */ def copyDir(src: String, dest: String): Unit = copyDir(src, dest, new Tagged() {}) /** * copy the content of a directory to another. * @param path path of the directory to copy * @param dest destination directory path * @param included names for included files * @param excluded names for excluded files */ def copyDir(src: String, dest: String, tagged: Tagged): Unit = listFiles(src).foreach { name => if (tagged.makeTagged(src + "/" + name).isAccepted) copyFile(src + "/" + name, dest) } /** * Copy the content of a directory to another. * @param path path of the file to copy * @param dest destination directory path */ def copyFile(path: String, dest: String) = { mkdirs(dest) val destFilePath = dest + "/" + new File(path).getName new File(destFilePath).createNewFile val input = new BufferedInputStream(new FileInputStream(path)) val output = new BufferedOutputStream(new FileOutputStream(destFilePath), 2048) copy(input, output) output.flush output.close input.close } /** * Unjar the jar (or zip file) specified by "path" to the "dest" directory. * @param path path of the jar file * @param dest destination directory path */ def unjar(path: String, dest: String): Unit = unjar(path, dest, ".*") /** * Unjar the jar (or zip file) specified by "path" to the "dest" directory. * Filters files which shouldn't be extracted with a regular expression. * @param path path of the jar file * @param dest destination directory path * @param regexFilter regular expression filtering files which shouldn't be extracted */ def unjar(path: String, dirPath: String, regexFilter: String) = { mkdirs(dirPath) val fis = new FileInputStream(path) val zis = new ZipInputStream(new BufferedInputStream(fis)) var entry: ZipEntry = null def extractEntry(entry: ZipEntry): Unit = { if (entry != null) { if (entry.getName.matches(regexFilter)) { if (entry.isDirectory()){ createDir(dirPath + "/" + entry.getName) } else { createFile(dirPath + "/" + entry.getName) val fos = new FileOutputStream(dirPath + "/" + entry.getName) val dest = new BufferedOutputStream(fos, 2048) copy(zis, dest) dest.flush dest.close } } extractEntry(zis.getNextEntry) } } extractEntry(zis.getNextEntry) zis.close } /** * Copy an input stream to an output stream. * @param input input stream * @param output output stream */ def copy(input: InputStream, output: OutputStream) = { val data = new Array[Byte](2048) def readData(count: Int): Unit = { if (count != -1) { output.write(data, 0, count) output.flush readData(input.read(data, 0, 2048)) } } readData(input.read(data, 0, 2048)) } /** * Copy specs resources found either in the specs jar or in the classpath directories to an output directory. * Current limitations!! This only works if the jar holding the resources contains the word "specs". * @param src name of the resource directory to copy * @param outputDir output directory where to copy the files to */ def copySpecResourcesDir(src: String, outputDir: String) = { val dirUrls = getResourcesNamed(src) Set(dirUrls.toList:_*) foreach { dirUrl => if (dirUrl.toString.startsWith("jar")) { if (dirUrl.toString.toLowerCase.contains("specs")) unjar(dirUrl.toString.replace("jar:file:/", "").takeWhile(_ != '!').mkString, outputDir, ".*" + src + "/.*") } else { copyDir(dirUrl, outputDir + src, new Tagged() {}.accept(Tag(".*")).reject(Tag(".*\\.svn.*"), Tag(".*CVS.*"))) } } } /** * Return urls of the resources containing the name "name" from this ClassLoader and the System classLoader. * @param name name of the resource to find * @return a list of URL */ def getResourcesNamed(name: String): List[URL] = { ClassLoader.getSystemResource(name) :: this.getClass.getClassLoader.getResources(name) } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy