Mercurial > lasercutter
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/contrib/java_utils.clj Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,219 @@ 1.4 +; Copyright (c) Stuart Halloway & Contributors, April 2009. All rights reserved. 1.5 +; The use and distribution terms for this software are covered by the 1.6 +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 1.7 +; which can be found in the file epl-v10.html at the root of this distribution. 1.8 +; By using this software in any fashion, you are agreeing to be bound by 1.9 +; the terms of this license. 1.10 +; You must not remove this notice, or any other, from this software. 1.11 + 1.12 +;; 1.13 +;; CHANGELOG 1.14 +;; 1.15 +;; Most functions deprecated in 1.2. Some already exist in c.c.io, and 1.16 +;; some replaced by c.c.reflections 1.17 + 1.18 +(ns 1.19 + ^{:author "Stuart Halloway, Stephen C. Gilardi, Shawn Hoover, Perry Trolard, Stuart Sierra", 1.20 + :doc "A set of utilties for dealing with Java stuff like files and properties. 1.21 + 1.22 + Design goals: 1.23 + 1.24 + (1) Ease-of-use. These APIs should be convenient. Performance is secondary. 1.25 + 1.26 + (2) Duck typing. I hate having to think about the difference between 1.27 + a string that names a file, and a File. Ditto for a ton of other 1.28 + wrapper classes in the Java world (URL, InternetAddress). With these 1.29 + APIs you should be able to think about domain equivalence, not type 1.30 + equivalence. 1.31 + 1.32 + (3) No bossiness. I am not marking any of these functions as private 1.33 + the docstrings will tell you the intended usage but do what works for you. 1.34 + 1.35 + Feedback welcome! 1.36 + 1.37 + If something in this module violates the principle of least surprise, please 1.38 + let me (Stu) and the Clojure community know via the mailing list. 1.39 + Contributors: 1.40 + 1.41 + Stuart Halloway 1.42 + Stephen C. Gilardi 1.43 + Shawn Hoover 1.44 + Perry Trolard 1.45 + Stuart Sierra 1.46 +"} 1.47 + clojure.contrib.java-utils 1.48 + (:import [java.io File FileOutputStream] 1.49 + [java.util Properties] 1.50 + [java.net URI URL])) 1.51 + 1.52 +(defmulti relative-path-string 1.53 + "Interpret a String or java.io.File as a relative path string. 1.54 + Building block for clojure.contrib.java-utils/file." 1.55 + {:deprecated "1.2"} 1.56 + class) 1.57 + 1.58 +(defmethod relative-path-string String [^String s] 1.59 + (relative-path-string (File. s))) 1.60 + 1.61 +(defmethod relative-path-string File [^File f] 1.62 + (if (.isAbsolute f) 1.63 + (throw (IllegalArgumentException. (str f " is not a relative path"))) 1.64 + (.getPath f))) 1.65 + 1.66 +(defmulti ^File as-file 1.67 + "Interpret a String or a java.io.File as a File. Building block 1.68 + for clojure.contrib.java-utils/file, which you should prefer 1.69 + in most cases." 1.70 + {:deprecated "1.2"} 1.71 + class) 1.72 +(defmethod as-file String [^String s] (File. s)) 1.73 +(defmethod as-file File [f] f) 1.74 + 1.75 +(defn ^File file 1.76 + "Returns a java.io.File from string or file args." 1.77 + {:deprecated "1.2"} 1.78 + ([arg] 1.79 + (as-file arg)) 1.80 + ([parent child] 1.81 + (File. ^File (as-file parent) ^String (relative-path-string child))) 1.82 + ([parent child & more] 1.83 + (reduce file (file parent child) more))) 1.84 + 1.85 +(defn as-str 1.86 + "Like clojure.core/str, but if an argument is a keyword or symbol, 1.87 + its name will be used instead of its literal representation. 1.88 + 1.89 + Example: 1.90 + (str :foo :bar) ;;=> \":foo:bar\" 1.91 + (as-str :foo :bar) ;;=> \"foobar\" 1.92 + 1.93 + Note that this does not apply to keywords or symbols nested within 1.94 + data structures; they will be rendered as with str. 1.95 + 1.96 + Example: 1.97 + (str {:foo :bar}) ;;=> \"{:foo :bar}\" 1.98 + (as-str {:foo :bar}) ;;=> \"{:foo :bar}\" " 1.99 + {:deprecated "1.2"} 1.100 + ([] "") 1.101 + ([x] (if (instance? clojure.lang.Named x) 1.102 + (name x) 1.103 + (str x))) 1.104 + ([x & ys] 1.105 + ((fn [^StringBuilder sb more] 1.106 + (if more 1.107 + (recur (. sb (append (as-str (first more)))) (next more)) 1.108 + (str sb))) 1.109 + (new StringBuilder ^String (as-str x)) ys))) 1.110 + 1.111 +(defn get-system-property 1.112 + "Get a system property." 1.113 + ([stringable] 1.114 + (System/getProperty (as-str stringable))) 1.115 + ([stringable default] 1.116 + (System/getProperty (as-str stringable) default))) 1.117 + 1.118 +(defn set-system-properties 1.119 + "Set some system properties. Nil clears a property." 1.120 + [settings] 1.121 + (doseq [[name val] settings] 1.122 + (if val 1.123 + (System/setProperty (as-str name) (as-str val)) 1.124 + (System/clearProperty (as-str name))))) 1.125 + 1.126 +(defmacro with-system-properties 1.127 + "setting => property-name value 1.128 + 1.129 + Sets the system properties to the supplied values, executes the body, and 1.130 + sets the properties back to their original values. Values of nil are 1.131 + translated to a clearing of the property." 1.132 + [settings & body] 1.133 + `(let [settings# ~settings 1.134 + current# (reduce (fn [coll# k#] 1.135 + (assoc coll# k# (get-system-property k#))) 1.136 + {} 1.137 + (keys settings#))] 1.138 + (set-system-properties settings#) 1.139 + (try 1.140 + ~@body 1.141 + (finally 1.142 + (set-system-properties current#))))) 1.143 + 1.144 + 1.145 +; Not there is no corresponding props->map. Just destructure! 1.146 +(defn ^Properties as-properties 1.147 + "Convert any seq of pairs to a java.utils.Properties instance. 1.148 + Uses as-str to convert both keys and values into strings." 1.149 + {:tag Properties} 1.150 + [m] 1.151 + (let [p (Properties.)] 1.152 + (doseq [[k v] m] 1.153 + (.setProperty p (as-str k) (as-str v))) 1.154 + p)) 1.155 + 1.156 +(defn read-properties 1.157 + "Read properties from file-able." 1.158 + [file-able] 1.159 + (with-open [f (java.io.FileInputStream. (file file-able))] 1.160 + (doto (Properties.) 1.161 + (.load f)))) 1.162 + 1.163 +(defn write-properties 1.164 + "Write properties to file-able." 1.165 + {:tag Properties} 1.166 + ([m file-able] (write-properties m file-able nil)) 1.167 + ([m file-able comments] 1.168 + (with-open [^FileOutputStream f (FileOutputStream. (file file-able))] 1.169 + (doto (as-properties m) 1.170 + (.store f ^String comments))))) 1.171 + 1.172 +(defn delete-file 1.173 + "Delete file f. Raise an exception if it fails unless silently is true." 1.174 + {:deprecated "1.2"} 1.175 + [f & [silently]] 1.176 + (or (.delete (file f)) 1.177 + silently 1.178 + (throw (java.io.IOException. (str "Couldn't delete " f))))) 1.179 + 1.180 +(defn delete-file-recursively 1.181 + "Delete file f. If it's a directory, recursively delete all its contents. 1.182 +Raise an exception if any deletion fails unless silently is true." 1.183 + {:deprecated "1.2"} 1.184 + [f & [silently]] 1.185 + (let [f (file f)] 1.186 + (if (.isDirectory f) 1.187 + (doseq [child (.listFiles f)] 1.188 + (delete-file-recursively child silently))) 1.189 + (delete-file f silently))) 1.190 + 1.191 +(defmulti 1.192 + ^{:deprecated "1.2" 1.193 + :doc "Coerces argument (URL, URI, or String) to a java.net.URL." 1.194 + :arglists '([arg])} 1.195 + as-url type) 1.196 + 1.197 +(defmethod as-url URL [x] x) 1.198 + 1.199 +(defmethod as-url URI [^URI x] (.toURL x)) 1.200 + 1.201 +(defmethod as-url String [^String x] (URL. x)) 1.202 + 1.203 +(defmethod as-url File [^File x] (.toURL x)) 1.204 + 1.205 +(defn wall-hack-method 1.206 + "Calls a private or protected method. 1.207 + params is a vector of class which correspond to the arguments to the method 1.208 + obj is nil for static methods, the instance object otherwise 1.209 + the method name is given as a symbol or a keyword (something Named)" 1.210 + {:deprecated "1.2"} 1.211 + [class-name method-name params obj & args] 1.212 + (-> class-name (.getDeclaredMethod (name method-name) (into-array Class params)) 1.213 + (doto (.setAccessible true)) 1.214 + (.invoke obj (into-array Object args)))) 1.215 + 1.216 +(defn wall-hack-field 1.217 + "Access to private or protected field." 1.218 + {:deprecated "1.2"} 1.219 + [class-name field-name obj] 1.220 + (-> class-name (.getDeclaredField (name field-name)) 1.221 + (doto (.setAccessible true)) 1.222 + (.get obj)))