annotate src/clojure/contrib/java_utils.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
rlm@10 1 ; Copyright (c) Stuart Halloway & Contributors, April 2009. All rights reserved.
rlm@10 2 ; The use and distribution terms for this software are covered by the
rlm@10 3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
rlm@10 4 ; which can be found in the file epl-v10.html at the root of this distribution.
rlm@10 5 ; By using this software in any fashion, you are agreeing to be bound by
rlm@10 6 ; the terms of this license.
rlm@10 7 ; You must not remove this notice, or any other, from this software.
rlm@10 8
rlm@10 9 ;;
rlm@10 10 ;; CHANGELOG
rlm@10 11 ;;
rlm@10 12 ;; Most functions deprecated in 1.2. Some already exist in c.c.io, and
rlm@10 13 ;; some replaced by c.c.reflections
rlm@10 14
rlm@10 15 (ns
rlm@10 16 ^{:author "Stuart Halloway, Stephen C. Gilardi, Shawn Hoover, Perry Trolard, Stuart Sierra",
rlm@10 17 :doc "A set of utilties for dealing with Java stuff like files and properties.
rlm@10 18
rlm@10 19 Design goals:
rlm@10 20
rlm@10 21 (1) Ease-of-use. These APIs should be convenient. Performance is secondary.
rlm@10 22
rlm@10 23 (2) Duck typing. I hate having to think about the difference between
rlm@10 24 a string that names a file, and a File. Ditto for a ton of other
rlm@10 25 wrapper classes in the Java world (URL, InternetAddress). With these
rlm@10 26 APIs you should be able to think about domain equivalence, not type
rlm@10 27 equivalence.
rlm@10 28
rlm@10 29 (3) No bossiness. I am not marking any of these functions as private
rlm@10 30 the docstrings will tell you the intended usage but do what works for you.
rlm@10 31
rlm@10 32 Feedback welcome!
rlm@10 33
rlm@10 34 If something in this module violates the principle of least surprise, please
rlm@10 35 let me (Stu) and the Clojure community know via the mailing list.
rlm@10 36 Contributors:
rlm@10 37
rlm@10 38 Stuart Halloway
rlm@10 39 Stephen C. Gilardi
rlm@10 40 Shawn Hoover
rlm@10 41 Perry Trolard
rlm@10 42 Stuart Sierra
rlm@10 43 "}
rlm@10 44 clojure.contrib.java-utils
rlm@10 45 (:import [java.io File FileOutputStream]
rlm@10 46 [java.util Properties]
rlm@10 47 [java.net URI URL]))
rlm@10 48
rlm@10 49 (defmulti relative-path-string
rlm@10 50 "Interpret a String or java.io.File as a relative path string.
rlm@10 51 Building block for clojure.contrib.java-utils/file."
rlm@10 52 {:deprecated "1.2"}
rlm@10 53 class)
rlm@10 54
rlm@10 55 (defmethod relative-path-string String [^String s]
rlm@10 56 (relative-path-string (File. s)))
rlm@10 57
rlm@10 58 (defmethod relative-path-string File [^File f]
rlm@10 59 (if (.isAbsolute f)
rlm@10 60 (throw (IllegalArgumentException. (str f " is not a relative path")))
rlm@10 61 (.getPath f)))
rlm@10 62
rlm@10 63 (defmulti ^File as-file
rlm@10 64 "Interpret a String or a java.io.File as a File. Building block
rlm@10 65 for clojure.contrib.java-utils/file, which you should prefer
rlm@10 66 in most cases."
rlm@10 67 {:deprecated "1.2"}
rlm@10 68 class)
rlm@10 69 (defmethod as-file String [^String s] (File. s))
rlm@10 70 (defmethod as-file File [f] f)
rlm@10 71
rlm@10 72 (defn ^File file
rlm@10 73 "Returns a java.io.File from string or file args."
rlm@10 74 {:deprecated "1.2"}
rlm@10 75 ([arg]
rlm@10 76 (as-file arg))
rlm@10 77 ([parent child]
rlm@10 78 (File. ^File (as-file parent) ^String (relative-path-string child)))
rlm@10 79 ([parent child & more]
rlm@10 80 (reduce file (file parent child) more)))
rlm@10 81
rlm@10 82 (defn as-str
rlm@10 83 "Like clojure.core/str, but if an argument is a keyword or symbol,
rlm@10 84 its name will be used instead of its literal representation.
rlm@10 85
rlm@10 86 Example:
rlm@10 87 (str :foo :bar) ;;=> \":foo:bar\"
rlm@10 88 (as-str :foo :bar) ;;=> \"foobar\"
rlm@10 89
rlm@10 90 Note that this does not apply to keywords or symbols nested within
rlm@10 91 data structures; they will be rendered as with str.
rlm@10 92
rlm@10 93 Example:
rlm@10 94 (str {:foo :bar}) ;;=> \"{:foo :bar}\"
rlm@10 95 (as-str {:foo :bar}) ;;=> \"{:foo :bar}\" "
rlm@10 96 {:deprecated "1.2"}
rlm@10 97 ([] "")
rlm@10 98 ([x] (if (instance? clojure.lang.Named x)
rlm@10 99 (name x)
rlm@10 100 (str x)))
rlm@10 101 ([x & ys]
rlm@10 102 ((fn [^StringBuilder sb more]
rlm@10 103 (if more
rlm@10 104 (recur (. sb (append (as-str (first more)))) (next more))
rlm@10 105 (str sb)))
rlm@10 106 (new StringBuilder ^String (as-str x)) ys)))
rlm@10 107
rlm@10 108 (defn get-system-property
rlm@10 109 "Get a system property."
rlm@10 110 ([stringable]
rlm@10 111 (System/getProperty (as-str stringable)))
rlm@10 112 ([stringable default]
rlm@10 113 (System/getProperty (as-str stringable) default)))
rlm@10 114
rlm@10 115 (defn set-system-properties
rlm@10 116 "Set some system properties. Nil clears a property."
rlm@10 117 [settings]
rlm@10 118 (doseq [[name val] settings]
rlm@10 119 (if val
rlm@10 120 (System/setProperty (as-str name) (as-str val))
rlm@10 121 (System/clearProperty (as-str name)))))
rlm@10 122
rlm@10 123 (defmacro with-system-properties
rlm@10 124 "setting => property-name value
rlm@10 125
rlm@10 126 Sets the system properties to the supplied values, executes the body, and
rlm@10 127 sets the properties back to their original values. Values of nil are
rlm@10 128 translated to a clearing of the property."
rlm@10 129 [settings & body]
rlm@10 130 `(let [settings# ~settings
rlm@10 131 current# (reduce (fn [coll# k#]
rlm@10 132 (assoc coll# k# (get-system-property k#)))
rlm@10 133 {}
rlm@10 134 (keys settings#))]
rlm@10 135 (set-system-properties settings#)
rlm@10 136 (try
rlm@10 137 ~@body
rlm@10 138 (finally
rlm@10 139 (set-system-properties current#)))))
rlm@10 140
rlm@10 141
rlm@10 142 ; Not there is no corresponding props->map. Just destructure!
rlm@10 143 (defn ^Properties as-properties
rlm@10 144 "Convert any seq of pairs to a java.utils.Properties instance.
rlm@10 145 Uses as-str to convert both keys and values into strings."
rlm@10 146 {:tag Properties}
rlm@10 147 [m]
rlm@10 148 (let [p (Properties.)]
rlm@10 149 (doseq [[k v] m]
rlm@10 150 (.setProperty p (as-str k) (as-str v)))
rlm@10 151 p))
rlm@10 152
rlm@10 153 (defn read-properties
rlm@10 154 "Read properties from file-able."
rlm@10 155 [file-able]
rlm@10 156 (with-open [f (java.io.FileInputStream. (file file-able))]
rlm@10 157 (doto (Properties.)
rlm@10 158 (.load f))))
rlm@10 159
rlm@10 160 (defn write-properties
rlm@10 161 "Write properties to file-able."
rlm@10 162 {:tag Properties}
rlm@10 163 ([m file-able] (write-properties m file-able nil))
rlm@10 164 ([m file-able comments]
rlm@10 165 (with-open [^FileOutputStream f (FileOutputStream. (file file-able))]
rlm@10 166 (doto (as-properties m)
rlm@10 167 (.store f ^String comments)))))
rlm@10 168
rlm@10 169 (defn delete-file
rlm@10 170 "Delete file f. Raise an exception if it fails unless silently is true."
rlm@10 171 {:deprecated "1.2"}
rlm@10 172 [f & [silently]]
rlm@10 173 (or (.delete (file f))
rlm@10 174 silently
rlm@10 175 (throw (java.io.IOException. (str "Couldn't delete " f)))))
rlm@10 176
rlm@10 177 (defn delete-file-recursively
rlm@10 178 "Delete file f. If it's a directory, recursively delete all its contents.
rlm@10 179 Raise an exception if any deletion fails unless silently is true."
rlm@10 180 {:deprecated "1.2"}
rlm@10 181 [f & [silently]]
rlm@10 182 (let [f (file f)]
rlm@10 183 (if (.isDirectory f)
rlm@10 184 (doseq [child (.listFiles f)]
rlm@10 185 (delete-file-recursively child silently)))
rlm@10 186 (delete-file f silently)))
rlm@10 187
rlm@10 188 (defmulti
rlm@10 189 ^{:deprecated "1.2"
rlm@10 190 :doc "Coerces argument (URL, URI, or String) to a java.net.URL."
rlm@10 191 :arglists '([arg])}
rlm@10 192 as-url type)
rlm@10 193
rlm@10 194 (defmethod as-url URL [x] x)
rlm@10 195
rlm@10 196 (defmethod as-url URI [^URI x] (.toURL x))
rlm@10 197
rlm@10 198 (defmethod as-url String [^String x] (URL. x))
rlm@10 199
rlm@10 200 (defmethod as-url File [^File x] (.toURL x))
rlm@10 201
rlm@10 202 (defn wall-hack-method
rlm@10 203 "Calls a private or protected method.
rlm@10 204 params is a vector of class which correspond to the arguments to the method
rlm@10 205 obj is nil for static methods, the instance object otherwise
rlm@10 206 the method name is given as a symbol or a keyword (something Named)"
rlm@10 207 {:deprecated "1.2"}
rlm@10 208 [class-name method-name params obj & args]
rlm@10 209 (-> class-name (.getDeclaredMethod (name method-name) (into-array Class params))
rlm@10 210 (doto (.setAccessible true))
rlm@10 211 (.invoke obj (into-array Object args))))
rlm@10 212
rlm@10 213 (defn wall-hack-field
rlm@10 214 "Access to private or protected field."
rlm@10 215 {:deprecated "1.2"}
rlm@10 216 [class-name field-name obj]
rlm@10 217 (-> class-name (.getDeclaredField (name field-name))
rlm@10 218 (doto (.setAccessible true))
rlm@10 219 (.get obj)))