Last active
April 10, 2022 16:47
-
-
Save borkdude/d02dc3ff1d03d09351e768964983a46b to your computer and use it in GitHub Desktop.
Retrieve the package string from a .class file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(require '[clojure.java.io :as io] | |
'[clojure.string :as str]) | |
(defn class->package | |
"Implementation by Marco Marini." | |
[class-file] | |
(with-open [dis (java.io.DataInputStream. (io/input-stream class-file))] | |
;; skip first 8 bytes | |
(.skipBytes dis 8) | |
(let [constant-pool-count (.readUnsignedShort dis) | |
[strings classes] | |
(loop [counter 1 | |
classes {} | |
strings {}] | |
(if (< counter constant-pool-count) | |
(case (.read dis) | |
1 (recur (inc counter) classes (assoc strings counter (.readUTF dis))) | |
(5 6) (do (.skipBytes dis 8) | |
(recur (+ 2 counter) classes strings)) | |
7 (recur (inc counter) (assoc classes counter (.readUnsignedShort dis)) strings) | |
(8 16 19 20) (do (.skipBytes dis 2) | |
(recur (inc counter) classes strings)) | |
15 (do (.skipBytes dis 3) (recur (inc counter) classes strings)) | |
(do (.skipBytes dis 4) | |
(recur (inc counter) classes strings))) | |
[strings classes]))] | |
;; skip access flags | |
(.skipBytes dis 2) | |
;; (prn (get @classes (.readUnsignedShort dis))) | |
(str/join | |
"." | |
(butlast | |
(str/split | |
(get strings (get classes (.readUnsignedShort dis))) | |
#"/")))))) | |
;; echo 'package foo.bar; public class Baz { }' > Baz.java | |
;; javac Baz.java | |
;; bb pkg.clj Baz.class | |
(prn (class->package (first *command-line-args*))) ;;=> "foo.bar" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment