How can a Clojure program find its own MANIFEST.MF (assuming it is packaged in a JAR file).
I am trying to do this from my "-main" function, but I can't find a class to use in the following code:
(.getValue
(..
(java.util.jar.Manifest.
(.openStream
(java.net.URL.
(str
"jar:"
(..
(class **WHAT-GOES-HERE**)
getProtectionDomain
getCodeSource
getLocation)
"!/META-INF/MANIFEST.MF"))))
getMainAttributes)
"Build-number"))
Thanks.
This seems to work reliably:
(defn set-version
"Set the version variable to the build number."
[]
(def version
(.getValue (.. (Manifest.
(.openStream
(URL.
(str "jar:"
(.getLocation
(.getCodeSource
(.getProtectionDomain org.example.myproject.thisfile)))
"!/META-INF/MANIFEST.MF"))))
getMainAttributes)
"Build-number")))
I find my version a little easier on the eyes:
(defn manifest-map
"Returns the mainAttributes of the manifest of the passed in class as a map."
[clazz]
(->> (str "jar:"
(-> clazz
.getProtectionDomain
.getCodeSource
.getLocation)
"!/META-INF/MANIFEST.MF")
clojure.java.io/input-stream
java.util.jar.Manifest.
.getMainAttributes
(map (fn [[k v]] [(str k) v]))
(into {})))
(get (manifest-map MyClass) "Build-Number")
Here's a readable version, about as simple as I could get it!
(when-let [loc (-> (.getProtectionDomain clazz) .getCodeSource .getLocation)]
(-> (str "jar:" loc "!/META-INF/MANIFEST.MF")
URL. .openStream Manifest. .getMainAttributes
(.getValue "Build-Number")))
There is also clj-manifest that essentially provides this functionality, using the a call similar to other answers found here.
I have found an answer that works, however I am open to suggestions for improving it, particularly replacing the call to Class/forName
.
(defn -main [& args]
(println "Version "
(.getValue
(..
(Manifest.
(.openStream
(URL.
(str
"jar:"
(..
(Class/forName "org.example.myproject.thisfile")
getProtectionDomain
getCodeSource
getLocation)
"!/META-INF/MANIFEST.MF"))))
getMainAttributes)
"Build-number")))