   ^{:author "Stuart Sierra",
      :doc "Search for ns declarations in dirs, JARs, or CLASSPATH"} 
   clojure.tools.namespace
-  (:require [clojure.java.classpath :as classpath]
+  (:require [clojure.java.io :as io]
             [clojure.set :as set])
   (import (java.io File FileReader BufferedReader PushbackReader
                    InputStreamReader)
-          (java.util.jar JarFile)))
+          (java.util.jar JarFile JarEntry)))
 
+;;; JAR-file utilities, adapted from clojure.java.classpath
+
+(defn- jar-file?
+  "Returns true if file is a normal file with a .jar or .JAR extension."
+  [f]
+  (let [file (io/file f)]
+    (and (.isFile file)
+         (or (.endsWith (.getName file) ".jar")
+             (.endsWith (.getName file) ".JAR")))))
+
+(defn- jar-files
+  "Given a sequence of File objects, filters it for JAR files, returns
+  a sequence of java.util.jar.JarFile objects."
+  [files]
+  (map #(JarFile. ^File %) (filter jar-file? files)))
+
+(defn- filenames-in-jar
+  "Returns a sequence of Strings naming the non-directory entries in
+  the JAR file."
+  [^JarFile jar-file]
+  (map #(.getName ^JarEntry %)
+       (filter #(not (.isDirectory ^JarEntry %))
+               (enumeration-seq (.entries jar-file)))))
+
+(defn- jar-file?
+  "Returns true if file is a normal file with a .jar or .JAR extension."
+  [f]
+  (let [file (io/file f)]
+    (and (.isFile file)
+         (or (.endsWith (.getName file) ".jar")
+             (.endsWith (.getName file) ".JAR")))))
 
 ;;; Finding namespaces in a directory tree
 

  "Attempts to read a (ns ...) declaration from file, and returns the
  unevaluated form.  Returns nil if read fails, or if the first form
  is not a ns declaration."
  [^File file]
  (with-open [rdr (PushbackReader. (BufferedReader. (FileReader. file)))]
    (read-ns-decl rdr)))

(defn find-ns-decls-in-dir
  "Searches dir recursively for (ns ...) declarations in Clojure
  source files; returns the unevaluated ns declarations."
  [^File dir]
  (filter identity (map read-file-ns-decl (find-clojure-sources-in-dir dir))))

(defn find-namespaces-in-dir
  "Searches dir recursively for (ns ...) declarations in Clojure

    (apply set/union (map #(deps-from-libspec nil %) (rest form)))))

(defn deps-from-ns-decl
  "Given an (ns...) declaration form (unevaluated), returns a set of
  symbols naming the dependencies of that namespace.  Handles :use and
  :require clauses but not :load."
  [decl]
  (apply set/union (map deps-from-ns-form decl)))
