2010-05-01 15 views
5

¿Cómo puede un programa Clojure encontrar su propio MANIFEST.MF (suponiendo que está empaquetado en un archivo JAR).programa Clojure leyendo su propio MANIFEST.MF

estoy tratando de hacerlo desde mi función "-main", pero no puedo encontrar una clase que se utiliza en el siguiente código:

(.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")) 

Gracias.

+0

Gracias, esto fue útil. Hice un poco de refactorización porque soy obsesivo con eso. Esto es lo que terminé con: (defn conseguir-función de la localización [SYM] (.. (sym clase) getProtectionDomain getCodeSource getLocation)) (defn get-manifiesto-atributos [] (let [ubicación (get-function-location get-manifest-attributes)] (when-not (nil? location) (-> (str "jar:" location "! /META-INF/MANIFEST.MF") (URL) (.openStream) (Manifiesto) (.getMainAttributes))))) –

+0

Corrección: pasar el símbolo a la función no era trabajando correctamente Terminé cambiando el nombre de get-function-location a get-location y pasando get-location a la clase. –

Respuesta

3

Esto parece funcionar de forma fiable:

(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"))) 
0

He encontrado una respuesta que funciona, sin embargo, estoy abierto a sugerencias para mejorarla, particularmente reemplazando la llamada al 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"))) 
1

encuentro mi versión un poco más fácil en los ojos:

(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") 
1

He aquí una versión legible, tan simple como podría conseguir ¡eso!

(when-let [loc (-> (.getProtectionDomain clazz) .getCodeSource .getLocation)] 
    (-> (str "jar:" loc "!/META-INF/MANIFEST.MF") 
     URL. .openStream Manifest. .getMainAttributes 
     (.getValue "Build-Number"))) 
0

Existe también clj-manifest que esencialmente proporciona esta funcionalidad, utilizando la una llamada similar a otras respuestas que se encuentran aquí.

Cuestiones relacionadas