-
-
Notifications
You must be signed in to change notification settings - Fork 54
/
io.clj
95 lines (81 loc) · 3.02 KB
/
io.clj
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
(ns orchard.util.io
"Utility functions for dealing with file system objects, and in/out streams."
(:require
[clojure.java.io :as io])
(:import
(java.io File)
(java.net URL JarURLConnection)))
(defn wrap-silently
"Middleware that executes `(f)` without printing to `System/out` or `System/err`.
(Note that `System/out` is different from `*out*`)"
[f]
(fn []
(let [old-out System/out
old-err System/err
ps (java.io.PrintStream. (proxy [java.io.OutputStream] []
(write
([a])
([a b c])
([a b c d e]))))]
(try
(System/setOut ps)
(System/setErr ps)
(f)
(finally
(when (= ps System/out) ;; `System/out` may have changed in the meantime (in face of concurrency)
(System/setOut old-out))
(when (= ps System/err) ;; `System/err` may have changed in the meantime (in face of concurrency)
(System/setErr old-err)))))))
(defn url-protocol
"Get the URL protocol as a string, e.g. http, file, jar."
^String
[^java.net.URL url]
(.getProtocol url))
(def jar? #{"jar"})
(def file? #{"file"})
(defn url-to-file-within-archive?
"Does this URL point to a file inside a jar (or zip) archive?
i.e., does it use the jar: protocol."
[^java.net.URL url]
(jar? (url-protocol url)))
(defn direct-url-to-file?
"Does this URL point to a file directly?
i.e., does it use the file: protocol."
[^java.net.URL url]
(file? (url-protocol url)))
(defn resource-jarfile
"Given a jar:file:...!/... URL, return the location of the jar file on the
filesystem. Returns nil on any other URL."
^File [^URL jar-resource]
(assert (jar? (url-protocol jar-resource)))
(let [^JarURLConnection conn (.openConnection jar-resource)
inner-url (.getJarFileURL conn)]
(when (file? (url-protocol inner-url))
(io/as-file inner-url))))
(defn resource-artifact
"Return the File from which the given resource URL would be loaded.
For `file:` URLs returns the location of the resource itself, for
`jar:..!/...` URLs returns the location of the archive containing the
resource. Returns a fully qualified File, even when the URL is relative.
Throws when the URL is not a `file:` or `jar:` URL."
^File [^java.net.URL resource]
(let [protocol (url-protocol resource)]
(cond
(file? protocol)
(io/as-file resource)
(jar? protocol)
(resource-jarfile resource)
:else
(throw (ex-info (str "URLs with a " protocol
" protocol can't be situated on the filesystem.")
{:resource resource})))))
(defprotocol LastModifiedTime
(last-modified-time [this]
"Return the last modified time of a File or resource URL."))
(extend-protocol LastModifiedTime
java.net.URL
(last-modified-time [this]
(last-modified-time (resource-artifact this)))
java.io.File
(last-modified-time [this]
(.lastModified this)))