aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/apply-macro/pom.xml16
-rw-r--r--modules/apply-macro/src/main/clojure/clojure/contrib/apply_macro.clj45
-rw-r--r--modules/http-agent/pom.xml26
-rw-r--r--modules/http-agent/src/main/clojure/clojure/contrib/http/agent.clj386
-rw-r--r--modules/http-connection/pom.xml21
-rw-r--r--modules/http-connection/src/main/clojure/clojure/contrib/http/connection.clj62
-rw-r--r--modules/javadoc/pom.xml26
-rw-r--r--modules/javadoc/src/main/clojure/clojure/contrib/javadoc.clj4
-rw-r--r--modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse.clj51
-rw-r--r--modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse_ui.clj31
-rw-r--r--modules/properties/pom.xml26
-rw-r--r--modules/properties/src/main/clojure/clojure/contrib/properties.clj77
-rw-r--r--modules/properties/src/test/clojure/clojure/contrib/test_properties.clj63
-rw-r--r--modules/test-is/pom.xml16
-rw-r--r--modules/test-is/src/main/clojure/clojure/contrib/test_is.clj119
-rw-r--r--pom.xml6
16 files changed, 975 insertions, 0 deletions
diff --git a/modules/apply-macro/pom.xml b/modules/apply-macro/pom.xml
new file mode 100644
index 00000000..23048791
--- /dev/null
+++ b/modules/apply-macro/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <artifactId>apply-macro</artifactId>
+ <dependencies>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/modules/apply-macro/src/main/clojure/clojure/contrib/apply_macro.clj b/modules/apply-macro/src/main/clojure/clojure/contrib/apply_macro.clj
new file mode 100644
index 00000000..9df85407
--- /dev/null
+++ b/modules/apply-macro/src/main/clojure/clojure/contrib/apply_macro.clj
@@ -0,0 +1,45 @@
+;;; apply_macro.clj: make macros behave like functions
+
+;; by Stuart Sierra, http://stuartsierra.com/
+;; January 28, 2009
+
+;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use
+;; and distribution terms for this software are covered by the Eclipse
+;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this
+;; distribution. By using this software in any fashion, you are
+;; agreeing to be bound by the terms of this license. You must not
+;; remove this notice, or any other, from this software.
+
+
+;; Don't use this. I mean it. It's evil. How evil? You can't
+;; handle it, that's how evil it is. That's right. I did it so you
+;; don't have to, ok? Look but don't touch. Use this lib and you'll
+;; go blind.
+
+;; DEPRECATED in 1.2 with no replacement.
+
+(ns ^{:deprecated "1.2"}
+ clojure.contrib.apply-macro)
+
+;; Copied from clojure.core/spread, which is private.
+(defn- spread
+ "Flatten final argument list as in apply."
+ [arglist]
+ (cond
+ (nil? arglist) nil
+ (nil? (rest arglist)) (seq (first arglist))
+ :else (cons (first arglist) (spread (rest arglist)))))
+
+(defmacro apply-macro
+ "This is evil. Don't ever use it. It makes a macro behave like a
+ function. Seriously, how messed up is that?
+
+ Evaluates all args, then uses them as arguments to the macro as with
+ apply.
+
+ (def things [true true false])
+ (apply-macro and things)
+ ;; Expands to: (and true true false)"
+ [macro & args]
+ (cons macro (spread (map eval args))))
diff --git a/modules/http-agent/pom.xml b/modules/http-agent/pom.xml
new file mode 100644
index 00000000..4de1a63c
--- /dev/null
+++ b/modules/http-agent/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <artifactId>http-agent</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>http-connection</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>io</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/modules/http-agent/src/main/clojure/clojure/contrib/http/agent.clj b/modules/http-agent/src/main/clojure/clojure/contrib/http/agent.clj
new file mode 100644
index 00000000..a42431f6
--- /dev/null
+++ b/modules/http-agent/src/main/clojure/clojure/contrib/http/agent.clj
@@ -0,0 +1,386 @@
+;;; http/agent.clj: agent-based asynchronous HTTP client
+
+;; by Stuart Sierra, http://stuartsierra.com/
+;; August 17, 2009
+
+;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use
+;; and distribution terms for this software are covered by the Eclipse
+;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this
+;; distribution. By using this software in any fashion, you are
+;; agreeing to be bound by the terms of this license. You must not
+;; remove this notice, or any other, from this software.
+
+;; DEPRECATED IN 1.2. Use direct Java bits, or take a look at
+;; http://github.com/technomancy/clojure-http-client
+
+(ns ^{:deprecated "1.2"
+ :doc "Agent-based asynchronous HTTP client.
+
+ This is a HTTP client library based on Java's HttpURLConnection
+ class and Clojure's Agent system. It allows you to make multiple
+ HTTP requests in parallel.
+
+ Start an HTTP request with the 'http-agent' function, which
+ immediately returns a Clojure Agent. You will never deref this
+ agent; that is handled by the accessor functions. The agent will
+ execute the HTTP request on a separate thread.
+
+ If you pass a :handler function to http-agent, that function will be
+ called as soon as the HTTP response body is ready. The handler
+ function is called with one argument, the HTTP agent itself. The
+ handler can read the response body by calling the 'stream' function
+ on the agent.
+
+ The value returned by the handler function becomes part of the state
+ of the agent, and you can retrieve it with the 'result' function.
+ If you call 'result' before the HTTP request has finished, it will
+ block until the handler function returns.
+
+ If you don't provide a handler function, the default handler will
+ buffer the entire response body in memory, which you can retrieve
+ with the 'bytes', 'string', or 'stream' functions. Like 'result',
+ these functions will block until the HTTP request is completed.
+
+ If you want to check if an HTTP request is finished without
+ blocking, use the 'done?' function.
+
+ A single GET request could be as simple as:
+
+ (string (http-agent \"http://www.stuartsierra.com/\"))
+
+ A simple POST might look like:
+
+ (http-agent \"http...\" :method \"POST\" :body \"foo=1\")
+
+ And you could write the response directly to a file like this:
+
+ (require '[clojure.contrib.io :as d])
+
+ (http-agent \"http...\"
+ :handler (fn [agnt]
+ (with-open [w (d/writer \"/tmp/out\")]
+ (d/copy (stream agnt) w))))
+"
+ :author "Stuart Sierra"
+ }
+
+ clojure.contrib.http.agent
+ (:refer-clojure :exclude [bytes])
+ (:require [clojure.contrib.http.connection :as c]
+ [clojure.contrib.io :as duck])
+ (:import (java.io InputStream ByteArrayOutputStream
+ ByteArrayInputStream)
+ (java.net HttpURLConnection)))
+
+
+;;; PRIVATE
+
+(declare result stream)
+
+(defn- setup-http-connection
+ "Sets the instance method, redirect behavior, and request headers of
+ the HttpURLConnection."
+ [^HttpURLConnection conn options]
+ (when-let [t (:connect-timeout options)]
+ (.setConnectTimeout conn t))
+ (when-let [t (:read-timeout options)]
+ (.setReadTimeout conn t))
+ (.setRequestMethod conn (:method options))
+ (.setInstanceFollowRedirects conn (:follow-redirects options))
+ (doseq [[name value] (:headers options)]
+ (.setRequestProperty conn name value)))
+
+(defn- start-request
+ "Agent action that starts sending the HTTP request."
+ [state options]
+ (let [conn (::connection state)]
+ (setup-http-connection conn options)
+ (c/start-http-connection conn (:body options))
+ (assoc state ::state ::started)))
+
+(defn- connection-success? [^HttpURLConnection conn]
+ "Returns true if the HttpURLConnection response code is in the 2xx
+ range."
+ (= 2 (quot (.getResponseCode conn) 100)))
+
+(defn- open-response
+ "Agent action that opens the response body stream on the HTTP
+ request; this will block until the response stream is available." ;
+ [state options]
+ (let [^HttpURLConnection conn (::connection state)]
+ (assoc state
+ ::response-stream (if (connection-success? conn)
+ (.getInputStream conn)
+ (.getErrorStream conn))
+ ::state ::receiving)))
+
+(defn- handle-response
+ "Agent action that calls the provided handler function, with no
+ arguments, and sets the ::result key of the agent to the handler's
+ return value."
+ [state handler options]
+ (let [conn (::connection state)]
+ (assoc state
+ ::result (handler)
+ ::state ::finished)))
+
+(defn- disconnect
+ "Agent action that closes the response body stream and disconnects
+ the HttpURLConnection."
+ [state options]
+ (when (::response-stream state)
+ (.close ^InputStream (::response-stream state)))
+ (.disconnect ^HttpURLConnection (::connection state))
+ (assoc state
+ ::response-stream nil
+ ::state ::disconnected))
+
+(defn- status-in-range?
+ "Returns true if the response status of the HTTP agent begins with
+ digit, an Integer."
+ [digit http-agnt]
+ (= digit (quot (.getResponseCode
+ ^HttpURLConnection (::connection @http-agnt))
+ 100)))
+
+(defn- ^ByteArrayOutputStream get-byte-buffer [http-agnt]
+ (let [buffer (result http-agnt)]
+ (if (instance? ByteArrayOutputStream buffer)
+ buffer
+ (throw (Exception. "Handler result was not a ByteArrayOutputStream")))))
+
+
+(defn buffer-bytes
+ "The default HTTP agent result handler; it collects the response
+ body in a java.io.ByteArrayOutputStream, which can later be
+ retrieved with the 'stream', 'string', and 'bytes' functions."
+ [http-agnt]
+ (let [output (ByteArrayOutputStream.)]
+ (duck/copy (or (stream http-agnt) "") output)
+ output))
+
+
+;;; CONSTRUCTOR
+
+(def *http-agent-defaults*
+ {:method "GET"
+ :headers {}
+ :body nil
+ :connect-timeout 0
+ :read-timeout 0
+ :follow-redirects true
+ :handler buffer-bytes})
+
+(defn http-agent
+ "Creates (and immediately returns) an Agent representing an HTTP
+ request running in a new thread.
+
+ options are key/value pairs:
+
+ :method string
+
+ The HTTP method name. Default is \"GET\".
+
+ :headers h
+
+ HTTP headers, as a Map or a sequence of pairs like
+ ([key1,value1], [key2,value2]) Default is nil.
+
+ :body b
+
+ HTTP request entity body, one of nil, String, byte[], InputStream,
+ Reader, or File. Default is nil.
+
+ :connect-timeout int
+
+ Timeout value, in milliseconds, when opening a connection to the
+ URL. Default is zero, meaning no timeout.
+
+ :read-timeout int
+
+ Timeout value, in milliseconds, when reading data from the
+ connection. Default is zero, meaning no timeout.
+
+ :follow-redirects boolean
+
+ If true, HTTP 3xx redirects will be followed automatically. Default
+ is true.
+
+ :handler f
+
+ Function to be called when the HTTP response body is ready. If you
+ do not provide a handler function, the default is to buffer the
+ entire response body in memory.
+
+ The handler function will be called with the HTTP agent as its
+ argument, and can use the 'stream' function to read the response
+ body. The return value of this function will be stored in the state
+ of the agent and can be retrieved with the 'result' function. Any
+ exceptions thrown by this function will be added to the agent's
+ error queue (see agent-errors). The default function collects the
+ response stream in a memory buffer.
+ "
+ ([uri & options]
+ (let [opts (merge *http-agent-defaults* (apply array-map options))]
+ (let [a (agent {::connection (c/http-connection uri)
+ ::state ::created
+ ::uri uri
+ ::options opts})]
+ (send-off a start-request opts)
+ (send-off a open-response opts)
+ (send-off a handle-response (partial (:handler opts) a) opts)
+ (send-off a disconnect opts)))))
+
+
+;;; RESPONSE BODY ACCESSORS
+
+(defn result
+ "Returns the value returned by the :handler function of the HTTP
+ agent; blocks until the HTTP request is completed. The default
+ handler function returns a ByteArrayOutputStream."
+ [http-agnt]
+ (await http-agnt)
+ (::result @http-agnt))
+
+(defn stream
+ "Returns an InputStream of the HTTP response body. When called by
+ the handler function passed to http-agent, this is the raw
+ HttpURLConnection stream.
+
+ If the default handler function was used, this function returns a
+ ByteArrayInputStream on the buffered response body."
+ [http-agnt]
+ (let [a @http-agnt]
+ (if (= (::state a) ::receiving)
+ (::response-stream a)
+ (ByteArrayInputStream.
+ (.toByteArray (get-byte-buffer http-agnt))))))
+
+(defn bytes
+ "Returns a Java byte array of the content returned by the server;
+ nil if the content is not yet available."
+ [http-agnt]
+ (.toByteArray (get-byte-buffer http-agnt)))
+
+(defn string
+ "Returns the HTTP response body as a string, using the given
+ encoding.
+
+ If no encoding is given, uses the encoding specified in the server
+ headers, or clojure.contrib.io/*default-encoding* if it is
+ not specified."
+ ([http-agnt]
+ (await http-agnt) ;; have to wait for Content-Encoding
+ (string http-agnt (or (.getContentEncoding
+ ^HttpURLConnection (::connection @http-agnt))
+ duck/*default-encoding*)))
+ ([http-agnt ^String encoding]
+ (.toString (get-byte-buffer http-agnt) encoding)))
+
+
+;;; REQUEST ACCESSORS
+
+(defn request-uri
+ "Returns the URI/URL requested by this HTTP agent, as a String."
+ [http-agnt]
+ (::uri @http-agnt))
+
+(defn request-headers
+ "Returns the request headers specified for this HTTP agent."
+ [http-agnt]
+ (:headers (::options @http-agnt)))
+
+(defn method
+ "Returns the HTTP method name used by this HTTP agent, as a String."
+ [http-agnt]
+ (:method (::options @http-agnt)))
+
+(defn request-body
+ "Returns the HTTP request body given to this HTTP agent.
+
+ Note: if the request body was an InputStream or a Reader, it will no
+ longer be usable."
+ [http-agnt]
+ (:body (::options @http-agnt)))
+
+
+;;; RESPONSE ACCESSORS
+
+(defn done?
+ "Returns true if the HTTP request/response has completed."
+ [http-agnt]
+ (if (#{::finished ::disconnected} (::state @http-agnt))
+ true false))
+
+(defn status
+ "Returns the HTTP response status code (e.g. 200, 404) for this
+ request, as an Integer, or nil if the status has not yet been
+ received."
+ [http-agnt]
+ (when (done? http-agnt)
+ (.getResponseCode ^HttpURLConnection (::connection @http-agnt))))
+
+(defn message
+ "Returns the HTTP response message (e.g. 'Not Found'), for this
+ request, or nil if the response has not yet been received."
+ [http-agnt]
+ (when (done? http-agnt)
+ (.getResponseMessage ^HttpURLConnection (::connection @http-agnt))))
+
+(defn headers
+ "Returns a map of HTTP response headers. Header names are converted
+ to keywords in all lower-case Header values are strings. If a
+ header appears more than once, only the last value is returned."
+ [http-agnt]
+ (reduce (fn [m [^String k v]]
+ (assoc m (when k (keyword (.toLowerCase k))) (last v)))
+ {} (.getHeaderFields
+ ^HttpURLConnection (::connection @http-agnt))))
+
+(defn headers-seq
+ "Returns the HTTP response headers in order as a sequence of
+ [String,String] pairs. The first 'header' name may be null for the
+ HTTP status line."
+ [http-agnt]
+ (let [^HttpURLConnection conn (::connection @http-agnt)
+ f (fn thisfn [^Integer i]
+ ;; Get value first because first key may be nil.
+ (when-let [value (.getHeaderField conn i)]
+ (cons [(.getHeaderFieldKey conn i) value]
+ (thisfn (inc i)))))]
+ (lazy-seq (f 0))))
+
+
+;;; RESPONSE STATUS CODE ACCESSORS
+
+(defn success?
+ "Returns true if the HTTP response code was in the 200-299 range."
+ [http-agnt]
+ (status-in-range? 2 http-agnt))
+
+(defn redirect?
+ "Returns true if the HTTP response code was in the 300-399 range.
+
+ Note: if the :follow-redirects option was true (the default),
+ redirects will be followed automatically and a the agent will never
+ return a 3xx response code."
+ [http-agnt]
+ (status-in-range? 3 http-agnt))
+
+(defn client-error?
+ "Returns true if the HTTP response code was in the 400-499 range."
+ [http-agnt]
+ (status-in-range? 4 http-agnt))
+
+(defn server-error?
+ "Returns true if the HTTP response code was in the 500-599 range."
+ [http-agnt]
+ (status-in-range? 5 http-agnt))
+
+(defn error?
+ "Returns true if the HTTP response code was in the 400-499 range OR
+ the 500-599 range."
+ [http-agnt]
+ (or (client-error? http-agnt)
+ (server-error? http-agnt)))
diff --git a/modules/http-connection/pom.xml b/modules/http-connection/pom.xml
new file mode 100644
index 00000000..74aaa0b0
--- /dev/null
+++ b/modules/http-connection/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <artifactId>http-connection</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>io</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/modules/http-connection/src/main/clojure/clojure/contrib/http/connection.clj b/modules/http-connection/src/main/clojure/clojure/contrib/http/connection.clj
new file mode 100644
index 00000000..c6cf162a
--- /dev/null
+++ b/modules/http-connection/src/main/clojure/clojure/contrib/http/connection.clj
@@ -0,0 +1,62 @@
+;;; http/connection.clj: low-level HTTP client API around HttpURLConnection
+
+;; by Stuart Sierra, http://stuartsierra.com/
+;; June 8, 2009
+
+;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use
+;; and distribution terms for this software are covered by the Eclipse
+;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this
+;; distribution. By using this software in any fashion, you are
+;; agreeing to be bound by the terms of this license. You must not
+;; remove this notice, or any other, from this software.
+
+;; DEPRECATED IN 1.2. Use direct Java bits, or take a look at
+;; http://github.com/technomancy/clojure-http-client
+
+(ns ^{:deprecated "1.2"
+ :doc "Low-level HTTP client API around HttpURLConnection"}
+ clojure.contrib.http.connection
+ (:require [clojure.contrib.io :as duck])
+ (:import (java.net URI URL HttpURLConnection)
+ (java.io File InputStream Reader)))
+
+(defn http-connection
+ "Opens an HttpURLConnection at the URL, handled by as-url."
+ [url]
+ (.openConnection (duck/as-url url)))
+
+(defmulti
+ ^{:doc "Transmits a request entity body."}
+ send-request-entity (fn [conn entity] (type entity)))
+
+(defmethod send-request-entity duck/*byte-array-type* [^HttpURLConnection conn entity]
+ (.setFixedLengthStreamingMode conn (count entity))
+ (.connect conn)
+ (duck/copy entity (.getOutputStream conn)))
+
+(defmethod send-request-entity String [conn ^String entity]
+ (send-request-entity conn (.getBytes entity duck/*default-encoding*)))
+
+(defmethod send-request-entity File [^HttpURLConnection conn ^File entity]
+ (.setFixedLengthStreamingMode conn (.length entity))
+ (.connect conn)
+ (duck/copy entity (.getOutputStream conn)))
+
+(defmethod send-request-entity InputStream [^HttpURLConnection conn entity]
+ (.setChunkedStreamingMode conn -1)
+ (.connect conn)
+ (duck/copy entity (.getOutputStream conn)))
+
+(defmethod send-request-entity Reader [^HttpURLConnection conn entity]
+ (.setChunkedStreamingMode conn -1)
+ (.connect conn)
+ (duck/copy entity (.getOutputStream conn)))
+
+(defn start-http-connection
+ ([^HttpURLConnection conn] (.connect conn))
+ ([^HttpURLConnection conn request-entity-body]
+ (if request-entity-body
+ (do (.setDoOutput conn true)
+ (send-request-entity conn request-entity-body))
+ (.connect conn))))
diff --git a/modules/javadoc/pom.xml b/modules/javadoc/pom.xml
new file mode 100644
index 00000000..4479bb97
--- /dev/null
+++ b/modules/javadoc/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <artifactId>javadoc</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>shell</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>def</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/javadoc/src/main/clojure/clojure/contrib/javadoc.clj b/modules/javadoc/src/main/clojure/clojure/contrib/javadoc.clj
new file mode 100644
index 00000000..7ac30a4e
--- /dev/null
+++ b/modules/javadoc/src/main/clojure/clojure/contrib/javadoc.clj
@@ -0,0 +1,4 @@
+(ns ^{:deprecated "1.2"}
+ clojure.contrib.javadoc)
+
+(throw (Exception. "clojure.contrib.javadoc/javadoc can now be found in clojure.java.javadoc"))
diff --git a/modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse.clj b/modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse.clj
new file mode 100644
index 00000000..a47fc0cd
--- /dev/null
+++ b/modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse.clj
@@ -0,0 +1,51 @@
+;;; browse.clj -- start a web browser from Clojure
+
+; Copyright (c) Christophe Grand, December 2008. All rights reserved.
+; The use and distribution terms for this software are covered by the
+; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+; which can be found in the file epl-v10.html at the root of this
+; distribution.
+; By using this software in any fashion, you are agreeing to be bound by
+; the terms of this license.
+; You must not remove this notice, or any other, from this software.
+
+(ns
+ ^{:author "Christophe Grand",
+ :deprecated "1.2"
+ :doc "Start a web browser from Clojure"}
+ clojure.contrib.javadoc.browse
+ (:require [clojure.contrib.shell :as sh])
+ (:import (java.net URI)))
+
+(defn- macosx? []
+ (-> "os.name" System/getProperty .toLowerCase
+ (.startsWith "mac os x")))
+
+(def *open-url-script* (when (macosx?) "/usr/bin/open"))
+
+(defn open-url-in-browser
+ "Opens url (a string) in the default system web browser. May not
+ work on all platforms. Returns url on success, nil if not
+ supported."
+ [url]
+ (try
+ (when (clojure.lang.Reflector/invokeStaticMethod "java.awt.Desktop"
+ "isDesktopSupported" (to-array nil))
+ (-> (clojure.lang.Reflector/invokeStaticMethod "java.awt.Desktop"
+ "getDesktop" (to-array nil))
+ (.browse (URI. url)))
+ url)
+ (catch ClassNotFoundException e
+ nil)))
+
+(defn open-url-in-swing
+ "Opens url (a string) in a Swing window."
+ [url]
+ ; the implementation of this function resides in another namespace to be loaded "on demand"
+ ; this fixes a bug on mac os x where requiring repl-utils turns the process into a GUI app
+ ; see http://code.google.com/p/clojure-contrib/issues/detail?id=32
+ (require 'clojure.contrib.javadoc.browse-ui)
+ ((find-var 'clojure.contrib.javadoc.browse-ui/open-url-in-swing) url))
+
+(defn browse-url [url]
+ (or (open-url-in-browser url) (when *open-url-script* (sh/sh *open-url-script* (str url)) true) (open-url-in-swing url)))
diff --git a/modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse_ui.clj b/modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse_ui.clj
new file mode 100644
index 00000000..388c76d5
--- /dev/null
+++ b/modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse_ui.clj
@@ -0,0 +1,31 @@
+;;; browse_ui.clj -- starts a swing web browser :-(
+
+; Copyright (c) Christophe Grand, December 2008. All rights reserved.
+; The use and distribution terms for this software are covered by the
+; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+; which can be found in the file epl-v10.html at the root of this
+; distribution.
+; By using this software in any fashion, you are agreeing to be bound by
+; the terms of this license.
+; You must not remove this notice, or any other, from this software.
+
+(ns ^{:deprecated "1.2"}
+ clojure.contrib.javadoc.browse-ui)
+
+(defn open-url-in-swing
+ "Opens url (a string) in a Swing window."
+ [url]
+ (let [htmlpane (javax.swing.JEditorPane. url)]
+ (.setEditable htmlpane false)
+ (.addHyperlinkListener htmlpane
+ (proxy [javax.swing.event.HyperlinkListener] []
+ (hyperlinkUpdate [^javax.swing.event.HyperlinkEvent e]
+ (when (= (.getEventType e) (. javax.swing.event.HyperlinkEvent$EventType ACTIVATED))
+ (if (instance? javax.swing.text.html.HTMLFrameHyperlinkEvent e)
+ (-> htmlpane .getDocument (.processHTMLFrameHyperlinkEvent e))
+ (.setPage htmlpane (.getURL e)))))))
+ (doto (javax.swing.JFrame.)
+ (.setContentPane (javax.swing.JScrollPane. htmlpane))
+ (.setBounds 32 32 700 900)
+ (.show))))
+
diff --git a/modules/properties/pom.xml b/modules/properties/pom.xml
new file mode 100644
index 00000000..c0cbca7a
--- /dev/null
+++ b/modules/properties/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <artifactId>properties</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>io</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>string</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/modules/properties/src/main/clojure/clojure/contrib/properties.clj b/modules/properties/src/main/clojure/clojure/contrib/properties.clj
new file mode 100644
index 00000000..0e210206
--- /dev/null
+++ b/modules/properties/src/main/clojure/clojure/contrib/properties.clj
@@ -0,0 +1,77 @@
+; Copyright (c) Stuart Halloway & Contributors, April 2009. All rights reserved.
+; The use and distribution terms for this software are covered by the
+; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+; which can be found in the file epl-v10.html at the root of this distribution.
+; By using this software in any fashion, you are agreeing to be bound by
+; the terms of this license.
+; You must not remove this notice, or any other, from this software.
+
+;; DEPRECATED in 1.2. Moved to c.c.java-utils
+
+(ns ^{:deprecated "1.2"}
+ clojure.contrib.properties
+ (:use [clojure.contrib.string :only (as-str)]
+ [clojure.contrib.io :only (file)])
+ (:import (java.util Properties)
+ (java.io FileInputStream FileOutputStream)))
+
+(defn get-system-property
+ "Get a system property."
+ ([stringable]
+ (System/getProperty (as-str stringable)))
+ ([stringable default]
+ (System/getProperty (as-str stringable) default)))
+
+(defn set-system-properties
+ "Set some system properties. Nil clears a property."
+ [settings]
+ (doseq [[name val] settings]
+ (if val
+ (System/setProperty (as-str name) (as-str val))
+ (System/clearProperty (as-str name)))))
+
+(defmacro with-system-properties
+ "setting => property-name value
+
+ Sets the system properties to the supplied values, executes the body, and
+ sets the properties back to their original values. Values of nil are
+ translated to a clearing of the property."
+ [settings & body]
+ `(let [settings# ~settings
+ current# (reduce (fn [coll# k#]
+ (assoc coll# k# (get-system-property k#)))
+ {}
+ (keys settings#))]
+ (set-system-properties settings#)
+ (try
+ ~@body
+ (finally
+ (set-system-properties current#)))))
+
+
+; Not there is no corresponding props->map. Just destructure!
+(defn ^Properties as-properties
+ "Convert any seq of pairs to a java.utils.Properties instance.
+ Uses as-str to convert both keys and values into strings."
+ {:tag Properties}
+ [m]
+ (let [p (Properties.)]
+ (doseq [[k v] m]
+ (.setProperty p (as-str k) (as-str v)))
+ p))
+
+(defn read-properties
+ "Read properties from file-able."
+ [file-able]
+ (with-open [f (java.io.FileInputStream. (file file-able))]
+ (doto (Properties.)
+ (.load f))))
+
+(defn write-properties
+ "Write properties to file-able."
+ {:tag Properties}
+ ([m file-able] (write-properties m file-able nil))
+ ([m file-able comments]
+ (with-open [^FileOutputStream f (FileOutputStream. (file file-able))]
+ (doto (as-properties m)
+ (.store f ^String comments)))))
diff --git a/modules/properties/src/test/clojure/clojure/contrib/test_properties.clj b/modules/properties/src/test/clojure/clojure/contrib/test_properties.clj
new file mode 100644
index 00000000..65b1371f
--- /dev/null
+++ b/modules/properties/src/test/clojure/clojure/contrib/test_properties.clj
@@ -0,0 +1,63 @@
+(ns clojure.contrib.test-properties
+ (:refer-clojure :exclude (spit))
+ (:use clojure.test clojure.contrib.properties
+ [clojure.contrib.io :only (spit)])
+ (:import (java.util Properties)
+ (java.io File)))
+
+(deftest test-get-system-property
+ (testing "works the same with keywords, symbols, and strings"
+ (is (= (get-system-property "java.home") (get-system-property 'java.home)))
+ (is (= (get-system-property "java.home") (get-system-property :java.home))))
+ (testing "treats second arg as default"
+ (is (= "default" (get-system-property "testing.test-system-property" "default"))))
+ (testing "returns nil for missing properties"
+ (is (nil? (get-system-property "testing.test-system-property")))))
+
+(deftest test-set-system-properties
+ (testing "set and then unset a property using keywords"
+ (let [propname :clojure.contrib.java.test-set-system-properties]
+ (is (nil? (get-system-property propname)))
+ (set-system-properties {propname :foo})
+ (is (= "foo") (get-system-property propname))
+ (set-system-properties {propname nil})
+ (is (nil? (get-system-property propname))))))
+
+(deftest test-with-system-properties
+ (let [propname :clojure.contrib.java.test-with-system-properties]
+ (testing "sets a property only for the duration of a block"
+ (is (= "foo"
+ (with-system-properties {propname "foo"}
+ (get-system-property propname))))
+ (is (nil? (get-system-property propname)))))
+ (testing "leaves other properties alone"
+ ; TODO: write this test better, using a properties -> map function
+ (let [propname :clojure.contrib.java.test-with-system-properties
+ propcount (count (System/getProperties))]
+ (with-system-properties {propname "foo"}
+ (is (= (inc propcount) (count (System/getProperties)))))
+ (is (= propcount (count (System/getProperties)))))))
+
+(deftest test-as-properties
+ (let [expected (doto (Properties.)
+ (.setProperty "a" "b")
+ (.setProperty "c" "d"))]
+ (testing "with a map"
+ (is (= expected
+ (as-properties {:a "b" :c "d"}))))
+ (testing "with a sequence of pairs"
+ (is (= expected
+ (as-properties [[:a :b] [:c :d]]))))))
+
+(deftest test-read-properties
+ (let [f (File/createTempFile "test" "properties")]
+ (spit f "a=b\nc=d")
+ (is (= {"a" "b" "c" "d"}
+ (read-properties f)))))
+
+(deftest test-write-properties
+ (let [f (File/createTempFile "test" "properties")]
+ (write-properties [['a 'b] ['c 'd]] f)
+ (is (= {"a" "b" "c" "d"}
+ (read-properties f)))))
+
diff --git a/modules/test-is/pom.xml b/modules/test-is/pom.xml
new file mode 100644
index 00000000..c0fb8a47
--- /dev/null
+++ b/modules/test-is/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.clojure.contrib</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <artifactId>test-is</artifactId>
+ <dependencies>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/modules/test-is/src/main/clojure/clojure/contrib/test_is.clj b/modules/test-is/src/main/clojure/clojure/contrib/test_is.clj
new file mode 100644
index 00000000..a1b0d8f9
--- /dev/null
+++ b/modules/test-is/src/main/clojure/clojure/contrib/test_is.clj
@@ -0,0 +1,119 @@
+;;; test_is.clj: Compatibility layer for old clojure.contrib.test-is
+
+;; by Stuart Sierra, http://stuartsierra.com/
+;; August 28, 2009
+
+;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use
+;; and distribution terms for this software are covered by the Eclipse
+;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this
+;; distribution. By using this software in any fashion, you are
+;; agreeing to be bound by the terms of this license. You must not
+;; remove this notice, or any other, from this software.
+
+;; DEPRECATED in 1.2: Moved to clojure.test
+
+(ns ^{:deprecated "1.2"
+ :doc "Backwards-compatibility for clojure.contrib.test-is
+
+ The clojure.contrib.test-is library moved from Contrib into the
+ Clojure distribution as clojure.test.
+
+ This happened on or around clojure-contrib Git commit
+ 82cf0409d0fcb71be477ebfc4da18ee2128a2ad1 on June 25, 2009.
+
+ This file makes the clojure.test interface available under the old
+ namespace clojure.contrib.test-is.
+
+ This includes support for the old syntax of the 'are' macro.
+
+ This was suggested by Howard Lewis Ship in ticket #26,
+ http://www.assembla.com/spaces/clojure-contrib/tickets/26"
+ :author "Stuart Sierra"}
+ clojure.contrib.test-is
+ (:require clojure.test
+ [clojure.walk :as walk]))
+
+
+;;; COPY INTERNED VARS (EXCEPT are) FROM clojure.test
+
+(doseq [v (disj (set (vals (ns-interns 'clojure.test)))
+ #'clojure.test/are)]
+ (intern *ns* (with-meta (:name (meta v)) (meta v)) (var-get v)))
+
+
+;;; REDEFINE OLD clojure.contrib.template
+
+(defn find-symbols
+ "Recursively finds all symbols in form."
+ [form]
+ (distinct (filter symbol? (tree-seq coll? seq form))))
+
+(defn find-holes
+ "Recursively finds all symbols starting with _ in form."
+ [form]
+ (sort (distinct (filter #(.startsWith (name %) "_")
+ (find-symbols form)))))
+
+(defn find-pure-exprs
+ "Recursively finds all sub-expressions in form that do not contain
+ any symbols starting with _"
+ [form]
+ (filter #(and (list? %)
+ (empty? (find-holes %)))
+ (tree-seq seq? seq form)))
+
+(defn flatten-map
+ "Transforms a map into a vector like [key value key value]."
+ [m]
+ (reduce (fn [coll [k v]] (conj coll k v))
+ [] m))
+
+(defn template?
+ "Returns true if form is a valid template expression."
+ [form]
+ (if (seq (find-holes form)) true false))
+
+(defn apply-template
+ "Replaces _1, _2, _3, etc. in expr with corresponding elements of
+ values. Returns the modified expression. For use in macros."
+ [expr values]
+ (when-not (template? expr)
+ (throw (IllegalArgumentException. (str (pr-str expr) " is not a valid template."))))
+ (let [expr (walk/postwalk-replace {'_ '_1} expr)
+ holes (find-holes expr)
+ smap (zipmap holes values)]
+ (walk/prewalk-replace smap expr)))
+
+(defmacro do-template
+ "Repeatedly evaluates template expr (in a do block) using values in
+ args. args are grouped by the number of holes in the template.
+ Example: (do-template (check _1 _2) :a :b :c :d)
+ expands to (do (check :a :b) (check :c :d))"
+ [expr & args]
+ (when-not (template? expr)
+ (throw (IllegalArgumentException. (str (pr-str expr) " is not a valid template."))))
+ (let [expr (walk/postwalk-replace {'_ '_1} expr)
+ argcount (count (find-holes expr))]
+ `(do ~@(map (fn [a] (apply-template expr a))
+ (partition argcount args)))))
+
+
+
+;;; REDEFINE are MACRO TO MATCH OLD TEMPLATE BEHAVIOR
+
+(defmacro are
+ "Checks multiple assertions with a template expression.
+ See clojure.contrib.template/do-template for an explanation of
+ templates.
+
+ Example: (are (= _1 _2)
+ 2 (+ 1 1)
+ 4 (* 2 2))
+ Expands to:
+ (do (is (= 2 (+ 1 1)))
+ (is (= 4 (* 2 2))))
+
+ Note: This breaks some reporting features, such as line numbers."
+ [expr & args]
+ `(do-template (is ~expr) ~@args))
diff --git a/pom.xml b/pom.xml
index b8f3ff3f..ad38a1fa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,6 +24,7 @@
<module>modules/accumulators</module>
<module>modules/agent-utils</module>
+ <module>modules/apply-macro</module>
<module>modules/base64</module>
<module>modules/classpath</module>
<module>modules/combinatorics</module>
@@ -45,10 +46,13 @@
<module>modules/generic</module>
<module>modules/graph</module>
<module>modules/greatest-least</module>
+ <module>modules/http-agent</module>
+ <module>modules/http-connection</module>
<module>modules/import-static</module>
<module>modules/io</module>
<module>modules/jar</module>
<module>modules/java-utils</module>
+ <module>modules/javadoc</module>
<module>modules/jmx</module>
<module>modules/json</module>
<module>modules/lazy-seqs</module>
@@ -68,6 +72,7 @@
<module>modules/priority-map</module>
<module>modules/probabilities</module>
<module>modules/profile</module>
+ <module>modules/properties</module>
<module>modules/prxml</module>
<module>modules/reflect</module>
<module>modules/repl-ln</module>
@@ -86,6 +91,7 @@
<module>modules/string</module>
<module>modules/strint</module>
<module>modules/swing-utils</module>
+ <module>modules/test-is</module>
<module>modules/trace</module>
<module>modules/types</module>
<module>modules/with-ns</module>