mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
14.59.2021 9093ed105bd99dd88fad4238570150faf35934af
Kotlin and YAML introduced.
2 files deleted
3 files added
23 files modified
907 ■■■■■ changed files
.gitignore 1 ●●●● patch | view | raw | blame | history
borgbutler-core/build.gradle 40 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgJob.java 2 ●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java 4 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/JCSCache.java 2 ●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java 157 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java 138 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/demo/DemoRepos.java 2 ●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/json/JsonUtils.java 4 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/kotlin/org/micromata/borgbutler/config/Configuration.kt 133 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/kotlin/org/micromata/borgbutler/config/ConfigurationHandler.kt 158 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/kotlin/org/micromata/borgbutler/config/YamlUtils.kt 61 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java 4 ●●●● patch | view | raw | blame | history
borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java 1 ●●●● patch | view | raw | blame | history
borgbutler-server/build.gradle 49 ●●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java 4 ●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java 2 ●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java 4 ●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java 2 ●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/BorgRepoConfigsRest.java 2 ●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java 2 ●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/JobsRest.java 2 ●●● patch | view | raw | blame | history
borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgInstallationTest.java 2 ●●● patch | view | raw | blame | history
build.gradle 32 ●●●●● patch | view | raw | blame | history
gradle/wrapper/gradle-wrapper.jar patch | view | raw | blame | history
gradle/wrapper/gradle-wrapper.properties 3 ●●●● patch | view | raw | blame | history
gradlew 53 ●●●●● patch | view | raw | blame | history
gradlew.bat 43 ●●●●● patch | view | raw | blame | history
.gitignore
@@ -42,3 +42,4 @@
borgbutler-webapp/build
borgbutler-webapp/node_modules
borgbutler-docker/app/target
borgbutler-server-0.3-SNAPSHOT
borgbutler-core/build.gradle
@@ -1,22 +1,29 @@
plugins {
    id 'java'
        id "org.jetbrains.kotlin.jvm" version "1.4.32"
}
description = 'borgbutler-core'
dependencies {
    compile group: 'commons-io', name: 'commons-io', version: '2.6'
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
    compile group: 'org.apache.commons', name: 'commons-exec', version: '1.3'
    compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.2'
    compile group: 'org.apache.commons', name: 'commons-compress', version: '1.18'
    compile group: 'org.apache.commons', name: 'commons-jcs-core', version: '2.2.1'
    implementation group: 'commons-io', name: 'commons-io', version: '2.8.0'
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
    implementation group: 'org.apache.commons', name: 'commons-exec', version: '1.3'
    implementation group: 'org.apache.commons', name: 'commons-collections4', version: '4.2'
    implementation group: 'org.apache.commons', name: 'commons-compress', version: '1.18'
    implementation group: 'org.apache.commons', name: 'commons-jcs-core', version: '2.2.1'
    // https://mvnrepository.com/artifact/com.esotericsoftware/kryo
    compile group: 'com.esotericsoftware', name: 'kryo', version: '5.0.0-RC1'
    implementation group: 'com.esotericsoftware', name: 'kryo', version: '5.0.0-RC1'
    // Serialization (faster than Java built-in)
    implementation 'io.github.microutils:kotlin-logging-jvm:2.0.6'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.8'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.3'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.12.3'
    // https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310
    implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.12.3'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
repositories {
@@ -24,8 +31,23 @@
    jcenter()
}
sourceSets {
    main.kotlin.srcDirs += 'src/main/kotlin'
    main.java.srcDirs += 'src/main/java'
}
test {
    // set heap size for the test JVM(s)
    minHeapSize = "128m"
    maxHeapSize = "1500m"
}
compileKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}
compileTestKotlin {
    kotlinOptions {
        jvmTarget = "1.9"
    }
}
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgJob.java
@@ -1,7 +1,7 @@
package de.micromata.borgbutler;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.data.Archive;
import de.micromata.borgbutler.demo.DemoRepos;
import de.micromata.borgbutler.jobs.AbstractCommandLineJob;
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
@@ -3,8 +3,8 @@
import de.micromata.borgbutler.BorgCommandResult;
import de.micromata.borgbutler.BorgCommands;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.Configuration;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.Configuration;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.data.Archive;
import de.micromata.borgbutler.data.ArchiveShortInfo;
import de.micromata.borgbutler.data.FileSystemFilter;
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/JCSCache.java
@@ -1,6 +1,6 @@
package de.micromata.borgbutler.cache;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import org.apache.commons.jcs.JCS;
import org.apache.commons.jcs.access.CacheAccess;
import org.slf4j.Logger;
borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
File was deleted
borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java
File was deleted
borgbutler-core/src/main/java/de/micromata/borgbutler/demo/DemoRepos.java
@@ -3,7 +3,7 @@
import de.micromata.borgbutler.BorgCommand;
import de.micromata.borgbutler.BorgJob;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.config.Definitions;
import de.micromata.borgbutler.data.Repository;
import de.micromata.borgbutler.jobs.JobResult;
borgbutler-core/src/main/java/de/micromata/borgbutler/json/JsonUtils.java
@@ -1,8 +1,8 @@
package de.micromata.borgbutler.json;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core.util.BufferRecyclers;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
@@ -45,7 +45,7 @@
    public static String toJson(String str) {
        if (str == null) return "";
        return new String(BufferRecyclers.getJsonStringEncoder().quoteAsString(str));
        return new String(JsonStringEncoder.getInstance().quoteAsString(str));
    }
    public static <T> T fromJson(Class<T> clazz, String json) {
borgbutler-core/src/main/kotlin/org/micromata/borgbutler/config/Configuration.kt
New file
@@ -0,0 +1,133 @@
package org.micromata.borgbutler.config
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import de.micromata.borgbutler.config.BorgRepoConfig
import de.micromata.borgbutler.demo.DemoRepos
import org.apache.commons.lang3.StringUtils
import org.slf4j.LoggerFactory
import java.io.File
/**
 * Representation of ~/.borgbutler/borgbutler-config.json.
 */
open class Configuration {
    private val log = LoggerFactory.getLogger(Configuration::class.java)
    @JsonIgnore
    private var workingDir: File? = null
    /**
     * Optional borg command to use.
     */
    /**
     * The path of the borg command to use (optional).
     */
    var borgCommand: String? = null
        private set
    /**
     * The borg version to install from github (optional).
     */
    var borgVersion: String? = null
    /**
     * Default is 100 MB (approximately).
     */
    var maxArchiveContentCacheCapacityMb = 100
        private set
    var isShowDemoRepos = true
        private set
    /**
     * Default is restore inside BorgButler's home dir (~/.borgbutler/restore).
     */
    @JsonProperty("restoreDir")
    val restoreDirPath: String? = null
    @JsonIgnore
    private var restoreHomeDir: File? = null
    @JsonProperty
    private val repoConfigs = mutableListOf<BorgRepoConfig>()
    fun add(repoConfig: BorgRepoConfig) {
        synchronized(repoConfigs) { repoConfigs.add(repoConfig) }
    }
    fun remove(idOrName: String?): Boolean {
        if (idOrName == null) {
            return false
        }
        synchronized(repoConfigs) {
            for (repoConfig in allRepoConfigs) {
                if (StringUtils.equals(idOrName, repoConfig.repo) || StringUtils.equals(idOrName, repoConfig.id)) {
                    repoConfigs.remove(repoConfig)
                    return true
                }
            }
        }
        return false
    }
    fun getRepoConfig(idOrName: String?): BorgRepoConfig? {
        if (idOrName == null) {
            return null
        }
        for (repoConfig in allRepoConfigs) {
            if (StringUtils.equals(idOrName, repoConfig.repo) || StringUtils.equals(idOrName, repoConfig.id)) {
                return repoConfig
            }
        }
        return null
    }
    fun getRestoreHomeDir(): File {
        if (restoreHomeDir == null) {
            restoreDirPath?.let {
                restoreHomeDir = File(it)
            } ?: run {
                restoreHomeDir = File(workingDir, RESTORE_DIRNAME)
            }
            if (!restoreHomeDir!!.exists()) {
                log.info("Creating dir '" + restoreHomeDir?.absolutePath + "' for restoring backup files and directories.")
            }
        }
        return restoreHomeDir!!
    }
    fun copyFrom(other: Configuration) {
        borgCommand = other.borgCommand
        maxArchiveContentCacheCapacityMb = other.maxArchiveContentCacheCapacityMb
        isShowDemoRepos = other.isShowDemoRepos
    }
    @get:JsonIgnore
    val allRepoConfigs: List<BorgRepoConfig>
        get() = DemoRepos.getAllRepos(repoConfigs)
    fun getRepoConfigs(): List<BorgRepoConfig> {
        return repoConfigs
    }
    fun setWorkingDir(workingDir: File?): Configuration {
        this.workingDir = workingDir
        return this
    }
    fun setBorgCommand(borgCommand: String?): Configuration {
        this.borgCommand = borgCommand
        return this
    }
    fun setShowDemoRepos(showDemoRepos: Boolean): Configuration {
        isShowDemoRepos = showDemoRepos
        return this
    }
    companion object {
        /**
         * Default dir name for restoring archives.
         */
        private const val RESTORE_DIRNAME = "restore"
    }
}
borgbutler-core/src/main/kotlin/org/micromata/borgbutler/config/ConfigurationHandler.kt
New file
@@ -0,0 +1,158 @@
package org.micromata.borgbutler.config
import de.micromata.borgbutler.config.Definitions
import de.micromata.borgbutler.json.JsonUtils
import org.apache.commons.io.FileUtils
import org.slf4j.LoggerFactory
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
/**
 * Reads and writes config file borgbutler-config.json/borgbutler-config.yaml
 */
class ConfigurationHandler private constructor(butlerHomeDir: String? = null) {
    val configFile: File
    private val configBackupDir: File
    var workingDir: File
        private set
    private val butlerHomeDir: File? = null
    private var configuration: Configuration? = null
    private fun read() {
        if (configFile.canRead()) {
            log.info("Reading config file '" + configFile.absolutePath + "'")
        } else {
            readOldJson()
        }
        try {
            if (configuration == null) {
                try {
                    configuration = configClazz.getDeclaredConstructor().newInstance()
                } catch (ex: Exception) {
                    log.error(
                        "Internal error: Can't instantiate object of type '" + configClazz + "': " + ex.message,
                        ex
                    )
                    return
                }
            }
            configuration?.getRepoConfigs()?.filter { it.displayName.isNullOrBlank() }?.forEach { repoConfig ->
                repoConfig.displayName = repoConfig.repo
            }
            configuration?.setWorkingDir(workingDir)
        } catch (ex: IOException) {
            log.error("Error while trying to read from config file: " + configFile.absolutePath + ": " + ex.message, ex)
            return
        }
    }
    /**
     * Backward compability
     */
    private fun readOldJson() {
        val jsonConfigFile = File(workingDir, OLD_JSON_CONFIG_FILENAME)
        if (!jsonConfigFile.canRead()) {
            // Nothing to do
            return
        }
        var json: String? = null
        if (jsonConfigFile.exists()) {
            json = FileUtils.readFileToString(jsonConfigFile, Definitions.STD_CHARSET)
            // Migrate from first version:
            if (json.contains("repo-configs")) {
                json = json.replace("repo-configs", "repoConfigs")
                json = json.replace("display_name", "displayName")
            }
            val formatter = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss'-'")
            val backupFilename = "${formatter.format(Date())}-old-${jsonConfigFile.name}"
            log.info("Migrating old json config file to yaml file. Renaming old json file '${jsonConfigFile.absolutePath}' to '$backupFilename'.")
            FileUtils.moveFile(jsonConfigFile, File(jsonConfigFile.parent, backupFilename))
        }
        val newConfig = JsonUtils.fromJson(configClazz, json)
            ?: // Nothing to do
            return
        configuration = newConfig
        save()
    }
    fun save() {
        configuration?.getRepoConfigs()?.filter { !it.passphrase.isNullOrBlank() }?.forEach { repoConfig ->
            log.info("Removing password command from config because password command is given: " + repoConfig.passwordCommand)
            repoConfig.passphrase = null // Don't use password (anymore) if password command is available.
        }
        val yaml = YamlUtils.toYaml(configuration)
        try {
            if (configFile.exists()) {
                // Create backup-file first:
                makeBackup(configFile)
            }
            log.info("Writing config file '" + configFile.absolutePath + "'")
            FileUtils.write(configFile, yaml, Definitions.STD_CHARSET)
        } catch (ex: IOException) {
            log.error("Error while trying to write config file: " + configFile.absolutePath + ": " + ex.message, ex)
        }
    }
    private fun makeBackup(file: File) {
        val formatter = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss'-'")
        val backupFile = File(configBackupDir, formatter.format(Date()) + file.name)
        log.info("Creating backup file first: '" + backupFile.absolutePath + "'")
        FileUtils.copyFile(file, backupFile)
    }
    companion object {
        private val log = LoggerFactory.getLogger(ConfigurationHandler::class.java)
        private var instance: ConfigurationHandler? = null
        private const val BUTLER_HOME_DIR = ".borgbutler"
        private const val OLD_JSON_CONFIG_FILENAME = "borgbutler-config.json"
        private const val CONFIG_FILENAME = "borgbutler.config"
        private const val CONFIG_BACKUP_DIR = "backup"
        private var configClazz: Class<out Configuration> = Configuration::class.java
        @kotlin.jvm.JvmStatic
        fun init(butlerHomeDir: String?) {
            if (instance != null) {
                throw RuntimeException("ConfigurationHandler already initialized")
            }
            instance = ConfigurationHandler(butlerHomeDir)
        }
        @kotlin.jvm.JvmStatic
        fun getInstance(): ConfigurationHandler? {
            if (instance == null) instance = ConfigurationHandler()
            return instance
        }
        @kotlin.jvm.JvmStatic
        fun getConfiguration(): Configuration? {
            return getInstance()!!.configuration
        }
        @kotlin.jvm.JvmStatic
        fun setConfigClazz(configClazz: Class<out Configuration>) {
            Companion.configClazz = configClazz
        }
    }
    init {
        workingDir = if (butlerHomeDir != null) {
            File(butlerHomeDir)
        } else {
            File(System.getProperty("user.home"), BUTLER_HOME_DIR)
        }
        log.info("Using directory '" + workingDir.getAbsolutePath() + "' as BorgButler's home directory.")
        if (!workingDir.exists()) {
            log.info("Creating borg-butlers working directory: " + workingDir.getAbsolutePath())
            workingDir.mkdirs()
        }
        configFile = File(workingDir, CONFIG_FILENAME)
        configBackupDir = File(workingDir, CONFIG_BACKUP_DIR)
        if (!configBackupDir.exists()) {
            log.info("Creating borg-butlers backup directory: " + configBackupDir.absolutePath)
            configBackupDir.mkdirs()
        }
        read()
    }
}
borgbutler-core/src/main/kotlin/org/micromata/borgbutler/config/YamlUtils.kt
New file
@@ -0,0 +1,61 @@
package org.micromata.borgbutler.config
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator
import com.fasterxml.jackson.dataformat.yaml.YAMLParser
import mu.KotlinLogging
import java.io.IOException
import java.io.StringWriter
private val log = KotlinLogging.logger {}
object YamlUtils {
    /**
     * @param obj
     * @return
     */
    fun toYaml(obj: Any?): String {
        if (obj == null) {
            return ""
        }
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
        return try {
            val writer = StringWriter()
            objectMapper.writeValue(writer, obj)
            writer.toString()
        } catch (ex: IOException) {
            log.error(ex.message, ex)
            ""
        }
    }
    fun <T> fromYaml(clazz: Class<T>?, json: String?): T? {
        return try {
            objectMapper.readValue(json, clazz)
        } catch (ex: IOException) {
            log.error(ex.message, ex)
            null
        }
    }
    fun <T> fromYaml(type: TypeReference<T>?, json: String): T? {
        try {
            return objectMapper.readValue(json, type)
        } catch (ex: Exception) {
            log.error("Json: '" + json + "': " + ex.message, ex)
        }
        return null
    }
    private val objectMapper: ObjectMapper = ObjectMapper(YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER))
    init {
        objectMapper.findAndRegisterModules()
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
    }
}
borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java
@@ -1,8 +1,8 @@
package de.micromata.borgbutler.cache;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.Configuration;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.Configuration;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.data.Archive;
import de.micromata.borgbutler.data.Repository;
import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java
@@ -2,6 +2,7 @@
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
import org.micromata.borgbutler.config.ConfigurationHandler;
import java.io.File;
import java.io.IOException;
borgbutler-server/build.gradle
@@ -1,7 +1,11 @@
buildscript {
    ext.kotlin_version = '1.4.32'
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
plugins {
@@ -13,25 +17,29 @@
dependencies {
    compile project(':borgbutler-core')
    // https://mvnrepository.com/artifact/org.apache.commons/commons-text
    compile group: 'org.apache.commons', name: 'commons-text', version: '1.6'
    compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.4.12.v20180830'
    compile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.4.12.v20180830'
    compile group: 'org.eclipse.jetty', name: 'jetty-servlets', version: '9.4.12.v20180830'
    compile group: 'org.glassfish.jaxb', name: 'jaxb-core', version: '2.3.0.1'
    compile group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '2.3.1'
    compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: '2.27'
    compile group: 'org.glassfish.jersey.media', name: 'jersey-media-multipart', version: '2.27'
    compile group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: '2.27'
    compile group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.27'
    compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
    compile group: 'javax.xml.ws', name: 'jaxws-api', version: '2.3.1'
    compile group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.25'
    implementation group: 'org.apache.commons', name: 'commons-text', version: '1.6'
    implementation group: 'org.apache.commons', name: 'commons-collections4', version: '4.2'
    implementation group: 'org.apache.commons', name: 'commons-compress', version: '1.18'
    implementation group: 'commons-io', name: 'commons-io', version: '2.8.0'
    implementation group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.4.12.v20180830'
    implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.4.12.v20180830'
    implementation group: 'org.eclipse.jetty', name: 'jetty-servlets', version: '9.4.12.v20180830'
    implementation group: 'org.glassfish.jaxb', name: 'jaxb-core', version: '2.3.0.1'
    implementation group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '2.3.1'
    implementation group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: '2.27'
    implementation group: 'org.glassfish.jersey.media', name: 'jersey-media-multipart', version: '2.27'
    implementation group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: '2.27'
    implementation group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.27'
    implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
    implementation group: 'javax.xml.ws', name: 'jaxws-api', version: '2.3.1'
    implementation group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.25'
    // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.6'
    implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.6'
    // https://mvnrepository.com/artifact/commons-cli/commons-cli
    compile group: 'commons-cli', name: 'commons-cli', version: '1.4'
    implementation group: 'commons-cli', name: 'commons-cli', version: '1.4'
    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.21.0'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}
repositories {
@@ -40,6 +48,7 @@
}
apply plugin: 'application'
apply plugin: 'kotlin'
mainClassName = "de.micromata.borgbutler.server.Main"
run() {
@@ -100,3 +109,13 @@
distZip.dependsOn ':borgbutler-webapp:npmBuild'
//distZip.dependsOn ':borgbutler-docs:buildWebDoc'
task(dist).dependsOn distZip
compileKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}
compileTestKotlin {
    kotlinOptions {
        jvmTarget = "1.9"
    }
}
borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java
@@ -1,8 +1,8 @@
package de.micromata.borgbutler.server;
import de.micromata.borgbutler.BorgCommands;
import de.micromata.borgbutler.config.Configuration;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.Configuration;
import org.micromata.borgbutler.config.ConfigurationHandler;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java
@@ -1,7 +1,7 @@
package de.micromata.borgbutler.server;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
import de.micromata.borgbutler.server.jetty.JettyServer;
import de.micromata.borgbutler.server.user.SingleUserManager;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java
@@ -2,8 +2,8 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.config.Configuration;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.Configuration;
import org.micromata.borgbutler.config.ConfigurationHandler;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ArchivesRest.java
@@ -3,7 +3,7 @@
import de.micromata.borgbutler.BorgCommands;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.data.Archive;
import de.micromata.borgbutler.data.DiffFileSystemFilter;
import de.micromata.borgbutler.data.FileSystemFilter;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/BorgRepoConfigsRest.java
@@ -4,7 +4,7 @@
import de.micromata.borgbutler.BorgCommands;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.data.Repository;
import de.micromata.borgbutler.jobs.JobResult;
import de.micromata.borgbutler.json.JsonUtils;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java
@@ -1,7 +1,7 @@
package de.micromata.borgbutler.server.rest;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.json.JsonUtils;
import de.micromata.borgbutler.server.BorgInstallation;
import de.micromata.borgbutler.server.ServerConfiguration;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/JobsRest.java
@@ -3,7 +3,7 @@
import de.micromata.borgbutler.BorgJob;
import de.micromata.borgbutler.BorgQueueExecutor;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.jobs.AbstractJob;
import de.micromata.borgbutler.json.JsonUtils;
import de.micromata.borgbutler.json.borg.ProgressInfo;
borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgInstallationTest.java
@@ -1,6 +1,6 @@
package de.micromata.borgbutler.server;
import de.micromata.borgbutler.config.ConfigurationHandler;
import org.micromata.borgbutler.config.ConfigurationHandler;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
build.gradle
@@ -42,11 +42,41 @@
        )
    }
    subprojects {
        ext.depVersions = ['commonsio': '2.8.0', dep2: '2.0']
    }
    test {
        useJUnitPlatform()
    }
}
wrapper {
    gradleVersion = '4.10.2'
    gradleVersion = '6.8.3'
}
//buildscript {
//    ext.kotlin_version = '1.4.32-release-371'
//    repositories {
//        mavenCentral()
//    }
//    dependencies {
//        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
//    }
//}
//apply plugin: 'kotlin'
//repositories {
//    mavenCentral()
//}
//dependencies {
//    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
//}
//compileKotlin {
//    kotlinOptions {
//        jvmTarget = "1.8"
//    }
//}
//compileTestKotlin {
//    kotlinOptions {
//        jvmTarget = "1.8"
//    }
//}
gradle/wrapper/gradle-wrapper.jar
Binary files differ
gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
#Fri Dec 07 23:41:31 CET 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip
gradlew
@@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
##  Gradle start up script for UN*X
@@ -28,7 +44,7 @@
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -66,6 +82,7 @@
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -109,10 +126,11 @@
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`
    # We build the pattern for arguments to be converted via cygpath
@@ -138,19 +156,19 @@
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
        i=`expr $i + 1`
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
        0) set -- ;;
        1) set -- "$args0" ;;
        2) set -- "$args0" "$args1" ;;
        3) set -- "$args0" "$args1" "$args2" ;;
        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi
@@ -159,14 +177,9 @@
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
    echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
  cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
gradlew.bat
@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem      https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell