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

net.dankito.utils.resources.ResourceFilesExtractor.kt Maven / Gradle / Ivy

There is a newer version: 1.0.20
Show newest version
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) { }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy