net.dankito.utils.resources.ResourceFilesExtractor.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-utils Show documentation
Show all versions of java-utils Show documentation
Some basic utils needed in many projects
package net.dankito.utils.resources
import net.dankito.utils.PackageInfo
import net.dankito.utils.io.FileUtils
import org.slf4j.LoggerFactory
import java.io.*
import java.util.jar.JarFile
import kotlin.concurrent.thread
open class ResourceFilesExtractor {
companion object {
private val log = LoggerFactory.getLogger(ResourceFilesExtractor::class.java)
}
open fun extractAsync(resourceFilesToExtract: List, destinationDirectory: File,
extractionDone: (() -> Unit)? = null) {
thread {
extract(resourceFilesToExtract, destinationDirectory)
extractionDone?.invoke()
}
}
open fun extract(resourceFilesToExtract: List, destinationDirectory: File) {
val absoluteDestinationDirectory = destinationDirectory.absoluteFile
if(absoluteDestinationDirectory.exists() == false) {
absoluteDestinationDirectory.mkdirs()
}
copyResourceFilesToDestination(resourceFilesToExtract, absoluteDestinationDirectory)
}
open fun extractAllFilesFromFolderAsync(aClassFromJarFile: Class<*>, folder: File, destinationDirectory: File,
extractionDone: (() -> Unit)? = null) {
thread {
extractAllFilesFromFolder(aClassFromJarFile, folder, destinationDirectory)
extractionDone?.invoke()
}
}
open fun extractAllFilesFromFolder(aClassFromJarFile: Class<*>, folder: File, destinationDirectory: File) {
PackageInfo().getClassJarPath(aClassFromJarFile)?.let { jarPath ->
log.info("Jar file: ${jarPath.absolutePath}")
if (jarPath.isFile) {
extractAllFilesFromJarFolder(jarPath, folder, destinationDirectory)
}
else {
extractAllFilesFromFolder(jarPath, folder, destinationDirectory)
}
}
}
protected open fun extractAllFilesFromJarFolder(jarPath: File, folder: File, destinationDirectory: File) {
val jar = JarFile(jarPath)
val subDirectory = folder.path.replace("\\", "/") // necessary as Windows uses '\' where as paths in jar are separated with '/'
jar.entries().toList().forEach { entry ->
if (entry.name.startsWith(subDirectory)) {
if (entry.isDirectory == false) {
val relativePath = entry.name.substring(subDirectory.length)
val destinationFile = File(destinationDirectory, relativePath)
log.info("Going to copy Jar entry ${entry.name} with relative path $relativePath to " +
"$destinationFile")
writeToFile(jar.getInputStream(entry), destinationFile)
}
}
}
}
protected open fun extractAllFilesFromFolder(jarPath: File, folder: File, destinationDirectory: File) {
var sourceFolder = File(jarPath, folder.path)
val fileUtils = FileUtils()
var filesInSourceFolder = fileUtils.getFilesOfDirectory(sourceFolder, folderDepth = Int.MAX_VALUE)
if (filesInSourceFolder == null) {
if (jarPath.name == "classes") {
sourceFolder = File(File(jarPath.parent, "resources"), folder.path)
}
else if (jarPath.path.endsWith("classes/kotlin/test")) {
sourceFolder = File(File(File(jarPath.parentFile.parentFile.parent, "resources"), "test"), folder.path)
}
filesInSourceFolder = fileUtils.getFilesOfDirectory(sourceFolder, folderDepth = Int.MAX_VALUE)
}
filesInSourceFolder?.forEach { file ->
val relativeFilePath = file.relativeTo(sourceFolder).path
writeToFile(FileInputStream(file), File(File(destinationDirectory, folder.path), relativeFilePath))
}
}
protected open fun copyResourceFilesToDestination(resourceFilesToExtract: List, destinationDirectory: File) {
val classLoader = ResourceFilesExtractor::class.java.classLoader
resourceFilesToExtract.forEach { filename ->
try {
copyResourceFileToDestination(destinationDirectory, filename, classLoader)
} catch(e: Exception) {
log.error("Could not copy resource file $filename to destination directory $destinationDirectory", e)
}
}
}
protected open fun copyResourceFileToDestination(destinationDirectory: File, filename: String,
classLoader: ClassLoader) {
// TODO: what to do if resource couldn't be found?
classLoader.getResourceAsStream(filename)?.let { inputStream ->
val destination = File(destinationDirectory, filename)
writeToFile(inputStream, destination)
}
}
@Throws(Exception::class)
private fun writeToFile(inputStream: InputStream, destinationFile: File) {
try {
destinationFile.parentFile.mkdirs()
} catch (e: Exception) { log.error("Could not create parent directory for $destinationFile")}
var outputStream: OutputStream? = null
try {
outputStream = BufferedOutputStream(FileOutputStream(destinationFile))
inputStream.buffered().copyTo(outputStream, FileUtils.DefaultFileOperationBufferSize)
} catch (e: IOException) {
log.error("Could not write InputStream to file " + destinationFile.absolutePath, e)
throw e
} finally {
try {
outputStream?.flush()
outputStream?.close()
inputStream.close()
} catch (e: IOException) { }
}
}
}