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

Kai Reinhard
19.29.2022 9926a79503c9bd6454c076f2b60cd577f6061e4d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package de.micromata.borgbutler.server.rest
 
import de.micromata.borgbutler.json.JsonUtils
import de.micromata.borgbutler.server.RunningMode
import mu.KotlinLogging
import org.apache.commons.lang3.StringUtils
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.awt.Color
import java.awt.FileDialog
import java.io.File
import javax.servlet.http.HttpServletRequest
import javax.swing.JFileChooser
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.SwingConstants
 
private val log = KotlinLogging.logger {}
 
@RestController
@RequestMapping("/rest/files")
class FilesystemBrowserRest {
 
    /**
     * Opens a directory browser or file browser on the desktop app and returns the chosen dir/file. Works only if Browser and Desktop app are running
     * on the same host.
     *
     * @param current The current path of file. If not given the directory/file browser starts with the last used directory or user.home.
     * @return The chosen directory path (absolute path).
     */
    @GetMapping("/browse-local-filesystem")
    fun browseLocalFilesystem(
        request: HttpServletRequest,
        @RequestParam("current", required = false) current: String?
    ): String {
        val msg = RestUtils.checkLocalDesktopAvailable(request)
        if (msg != null) {
            log.info(msg)
            return msg
        }
        if (fileDialog != null || fileChooser != null) {
            log.warn("Cannot call already opened file choose twice. Close file chooser first.")
            return "{\"directory\": \"\"}"
        }
        var file: File? = null
        synchronized(FilesystemBrowserRest::class.java) {
            if (frame == null) {
                val fr = JFrame("BorgButler")
                frame = fr
                fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
                fr.setSize(300, 100)
                fr.setResizable(false)
                fr.setLocationRelativeTo(null)
                fr.setBackground(Color.WHITE)
                fr.getContentPane().setBackground(Color.WHITE)
                val label = JLabel("Click for choosing directory...", SwingConstants.CENTER)
                fr.add(label)
            }
            if (RunningMode.oSType == RunningMode.OSType.MAC_OS) {
                // The JFileChooser will hang after several calls, use AWT file dialog instead for Mac OS:
                System.setProperty("apple.awt.fileDialogForDirectories", "true")
                frame?.let {
                    it.setAlwaysOnTop(true)
                    it.setVisible(true)
                }
                try {
                    val dialog =
                        FileDialog(frame, "Choose a directory", FileDialog.LOAD)
                    fileDialog = dialog
                    if (StringUtils.isNotBlank(current)) {
                        dialog.setDirectory(current)
                    }
                    dialog.toFront()
                    dialog.setVisible(true)
                    val filename: String? = dialog.getFile()
                    val directory: String? = dialog.getDirectory()
                    dialog.setVisible(false)
                    if (filename == null) {
                        return ""
                    }
                    file = File(directory, filename)
                    if (file?.isDirectory != true) {
                        file = File(directory)
                    }
                } finally {
                    fileDialog = null
                }
            } else {
                try {
                    val chooser = if (StringUtils.isNotBlank(current)) {
                        JFileChooser(current)
                    } else {
                        JFileChooser()
                    }
                    fileChooser = chooser
                    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
                    frame?.let {
                        it.setVisible(true)
                        it.setAlwaysOnTop(true)
                    }
                    val returnCode: Int = chooser.showDialog(
                        frame,
                        "Choose"
                    )
                    frame?.let {
                        it.setVisible(false)
                        it.setAlwaysOnTop(false)
                    }
                    if (returnCode == JFileChooser.APPROVE_OPTION) {
                        file = chooser.getSelectedFile()
                    }
                } finally {
                    fileChooser = null
                }
            }
        }
        val filename = if (file != null) JsonUtils.toJson(file!!.absolutePath) else ""
        return "{\"directory\":\"$filename\"}"
    }
 
    /**
     * @return OK, if the local desktop services such as open file browser etc. are available.
     */
    @GetMapping("/local-fileservices-available")
    fun browseLocalFilesystem(request: HttpServletRequest): String {
        val msg = RestUtils.checkLocalDesktopAvailable(request)
        if (msg != null) {
            log.info(msg)
            return msg
        }
        return "OK"
    }
 
    companion object {
        private var frame: JFrame? = null
        private var fileDialog: FileDialog? = null
        private var fileChooser: JFileChooser? = null
    }
}