From 8c6e8dd5abd1ee61e5f4105c480b79f6c1d2939b Mon Sep 17 00:00:00 2001
From: Tassilo Horn <tassilo@member.fsf.org>
Date: Fri, 13 Apr 2012 18:22:11 +0200
Subject: [PATCH] Added ClosableResource protocol for with-open.

---
 src/clj/clojure/core.clj           |   12 ++++++++----
 src/clj/clojure/core/protocols.clj |   12 ++++++++++++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 7bb28aa..c0aaac1 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -3376,9 +3376,13 @@
 (defmacro with-open
   "bindings => [name init ...]
 
-  Evaluates body in a try expression with names bound to the values
-  of the inits, and a finally clause that calls (.close name) on each
-  name in reverse order."
+  Evaluates body in a try expression with names bound to the values of the
+  inits, and a finally clause that closes each resource in reverse order.
+
+  You can extend this functionality by extending the CloseableResource
+  protocol.  The default implementation works for all java.io.Closeables,
+  including Readers, Writers, InputStreams, OutputStreams, Sockets, and
+  Channels."
   {:added "1.0"}
   [bindings & body]
   (assert-args
@@ -3390,7 +3394,7 @@
                               (try
                                 (with-open ~(subvec bindings 2) ~@body)
                                 (finally
-                                  (. ~(bindings 0) close))))
+                                 (clojure.core.protocols/close ~(bindings 0)))))
     :else (throw (IllegalArgumentException.
                    "with-open only allows Symbols in bindings"))))
 
diff --git a/src/clj/clojure/core/protocols.clj b/src/clj/clojure/core/protocols.clj
index 199ce64..6f90a69 100644
--- a/src/clj/clojure/core/protocols.clj
+++ b/src/clj/clojure/core/protocols.clj
@@ -162,3 +162,15 @@
    entries. Called by clojure.core/reduce-kv, and has same
    semantics (just different arg order)."
   (kv-reduce [amap f init]))
+
+(defprotocol CloseableResource
+  "Protocol for resources that can be closed (for use in with-open)."
+  (close [this]))
+
+(extend-protocol CloseableResource
+  ;; Note: in Java 1.7, there's a new Closeable super-interface
+  ;; java.lang.AutoCloseable, so at some point in time, we might want to switch
+  ;; to that.
+  java.io.Closeable
+  (close [this] (.close this)))
+
-- 
1.7.8.5

