            (java.net URL)
            (java.util Enumeration
                       Map$Entry)
+           (java.util.regex Pattern)
            (javax.servlet ServletContext)
            (javax.servlet.http Cookie
                                HttpServlet

(defstruct url-route
  :regex
  :keywords)
 
(defn compile-route
  "Turn a route string into a regex and seq of symbols."
  [route-str]
  (let [splat #"\*"
        word  #":(\w+)"
        path  #"[^:*]+"]
    (struct url-route
      (re-pattern
        (apply str
          (parse route-str
            splat "(.*?)"
            word  "([^/.,;?]+)"
            path  #(re-escape (.group %)))))
      (filter (complement nil?)
        (parse route-str
          splat :*
          word  #(keyword (.group % 1))
          path  nil)))))
 
(defn match-route
  "Match a path against a parsed route. Returns a map of keywords and their
  matching path values."
  [route path]
  (let [matcher (re-matcher (route :regex) path)]
    (if (.matches matcher)
      (reduce
        (partial merge-with
          #(conj (ifn vector? vector %1) %2))
        {}
        (map hash-map
          (route :keywords)
          (rest (re-groups matcher)))))))

;;;; Handler functions ;;;;
 

  (apply hash-map
    (mapcat #(list (keyword (.getName %)) (.getValue %))
             (.getCookies request))))

(defmacro handler-fn
  "Macro that wraps the body of a handler up in a standalone function."
