
org.opalj.io.package.scala Maven / Gradle / Ivy
The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
import java.nio.file.Files
import java.nio.file.Path
import java.io.File
import java.io.IOException
import java.io.Closeable
import java.awt.Desktop
import java.io.FileOutputStream
import java.util.zip.GZIPOutputStream
import scala.io.Source
import scala.xml.Node
/**
* Various io-related helper methods and classes.
*
* @note The implementations of the methods rely on Java NIO(2).
*
* @author Michael Eichberg
* @author Andreas Muttscheller
*/
package object io {
/**
* Replaces characters in the given file name (segment) that are (potentially) problematic
* on some file system and also shortens the filename
*
* @see For more information visit https://en.wikipedia.org/wiki/Filename
*
* @param fileName The filename or a suffix/prefix thereof which should be sanitized.
*
* @return The sanitized file name.
*
*/
def sanitizeFileName(fileName: String): String = {
// take(128+64) ... to have some space for something else...
fileName.filterNot(_ == ' ').replaceAll("[\\/:*?\"<>|\\[\\]=!@,]", "_").take(128 + 64)
}
/**
* Writes the XML document to a temporary file and opens the file in the
* OS's default application.
*
* @param filenamePrefix A string the identifies the content of the file. (E.g.,
* "ClassHierarchy" or "CHACallGraph")
* @param filenameSuffix The suffix of the file that identifies the used file format.
* (E.g., ".xhtml")
* @return The name of the file if it was possible to write the file and open
* the native application.
*/
@throws[IOException]("if it is not possible to create a temporary file")
@throws[OpeningFileFailedException]("if it is not possible to open the file")
def writeAndOpen(
node: Node,
filenamePrefix: String,
filenameSuffix: String
): File = {
val data = node.toString
writeAndOpen(data, filenamePrefix, filenameSuffix)
}
/**
* Writes the given string (`data`) to a temporary file using the given prefix and suffix.
* Afterwards the system's native application that claims to be able to handle
* files with the given suffix is opened. If this fails, the string is printed to
* the console.
*
* The string is always written using UTF-8 as the encoding.
*
* @param filenamePrefix A string the identifies the content of the file. (E.g.,
* "ClassHierarchy" or "CHACallGraph")
* @param filenameSuffix The suffix of the file that identifies the used file format.
* (E.g., ".txt")
* @return The name of the file if it was possible to write the file and open
* the native application.
* @example
* Exemplary usage:
* {{{
* try {
* util.writeAndOpen("The Message", "Result", ".txt")
* } catch {
* case OpeningFileFailedException(file, _) ⇒
* Console.err.println("Details can be found in: "+file.toString)
* }}}
*/
@throws[IOException]("if it is not possible to create a temporary file")
@throws[OpeningFileFailedException]("if it is not possible to open the file")
def writeAndOpen(
data: String,
filenamePrefix: String,
filenameSuffix: String
): File = {
val file = write(data, filenamePrefix, filenameSuffix).toFile
open(file)
file
}
def open(file: File): Unit = {
try {
Desktop.getDesktop.open(file)
} catch {
case t: Throwable ⇒ throw OpeningFileFailedException(file, t)
}
}
def write(
data: String,
filenamePrefix: String,
filenameSuffix: String
): Path = {
write(Seq(data), filenamePrefix, filenameSuffix)
}
def write(
data: TraversableOnce[String],
filenamePrefix: String,
filenameSuffix: String
): Path = {
val path = Files.createTempFile(
sanitizeFileName(filenamePrefix),
sanitizeFileName(filenameSuffix)
)
write(data.map(_.getBytes("UTF-8")), path)
path
}
def writeGZip(
data: String,
filenamePrefix: String,
filenameSuffix: String
): Path = {
writeGZip(Seq(data), filenamePrefix, filenameSuffix)
}
def writeGZip(
data: TraversableOnce[String],
filenamePrefix: String,
filenameSuffix: String
): Path = {
val path = Files.createTempFile(
sanitizeFileName(filenamePrefix),
sanitizeFileName(filenameSuffix)
)
writeGZip(data.map(_.getBytes("UTF-8")), path)
path
}
/**
* A simple wrapper for `java.nio.Files.write(Path,byte[])`.
*/
def write(data: Array[Byte], path: Path): Unit = Files.write(path, data)
def write(data: TraversableOnce[Array[Byte]], path: Path): Unit = {
val out = new FileOutputStream(path.toFile)
try {
data.foreach(out.write)
} finally {
out.close()
}
}
def writeGZip(data: Array[Byte], path: Path): Unit = {
writeGZip(Seq(data), path)
}
def writeGZip(data: TraversableOnce[Array[Byte]], path: Path): Unit = {
val out = new GZIPOutputStream(new FileOutputStream(path.toFile))
try {
data.foreach(out.write)
} finally {
out.close()
}
}
/**
* This function takes a `Closeable` resource and a function `r` that will
* process the `Closeable` resource.
* This function takes care of the correct handling of `Closeable` resources.
* When `r` has finished processing the resource or throws an exception, the
* resource is closed.
*
* @note If `closable` is `null`, `null` is passed to `r`.
*
* @param closable The `Closeable` resource.
* @param r The function that processes the `resource`.
*/
def process[C <: Closeable, T](closable: C)(r: C ⇒ T): T = {
// Implementation Note
// Creating the closeable (I) in the try block doesn't make sense, hence
// we don't need a by-name parameter. (If creating the closable fails,
// then there is nothing to close.)
try {
r(closable)
} finally {
if (closable != null) closable.close()
}
}
/**
* This function takes a `Source` object and a function `r` that will
* process the source.
* This function takes care of the correct handling of resources.
* When `r` has finished processing the source or throws an exception,
* the source is closed.
*
* @note If `source` is `null`, `null` is passed to `r`.
*/
def processSource[C <: Source, T](source: C)(r: C ⇒ T): T = {
try {
r(source)
} finally {
if (source != null) source.close()
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy