diff options
author | Stuart Sierra <mail@stuartsierra.com> | 2010-08-20 13:27:46 -0400 |
---|---|---|
committer | Stuart Sierra <mail@stuartsierra.com> | 2010-08-20 13:27:46 -0400 |
commit | 055b69c39b0d1ea61d486be11caa98f74c0493fc (patch) | |
tree | d936c24dd46c84f7dff58b95285801a6396f7a99 | |
parent | 4e5d98a8840fdeabbb304ca084cb02509dc14393 (diff) |
Revert "Remove modules that were deprecated in 1.2"
This reverts commit 4e5d98a8840fdeabbb304ca084cb02509dc14393.
Too many build dependencies were broken by this change;
deprecated modules should be removed one-at-a-time.
-rw-r--r-- | modules/apply-macro/pom.xml | 16 | ||||
-rw-r--r-- | modules/apply-macro/src/main/clojure/clojure/contrib/apply_macro.clj | 45 | ||||
-rw-r--r-- | modules/http-agent/pom.xml | 26 | ||||
-rw-r--r-- | modules/http-agent/src/main/clojure/clojure/contrib/http/agent.clj | 386 | ||||
-rw-r--r-- | modules/http-connection/pom.xml | 21 | ||||
-rw-r--r-- | modules/http-connection/src/main/clojure/clojure/contrib/http/connection.clj | 62 | ||||
-rw-r--r-- | modules/javadoc/pom.xml | 26 | ||||
-rw-r--r-- | modules/javadoc/src/main/clojure/clojure/contrib/javadoc.clj | 4 | ||||
-rw-r--r-- | modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse.clj | 51 | ||||
-rw-r--r-- | modules/javadoc/src/main/clojure/clojure/contrib/javadoc/browse_ui.clj | 31 | ||||
-rw-r--r-- | modules/properties/pom.xml | 26 | ||||
-rw-r--r-- | modules/properties/src/main/clojure/clojure/contrib/properties.clj | 77 | ||||
-rw-r--r-- | modules/properties/src/test/clojure/clojure/contrib/test_properties.clj | 63 | ||||
-rw-r--r-- | modules/test-is/pom.xml | 16 | ||||
-rw-r--r-- | modules/test-is/src/main/clojure/clojure/contrib/test_is.clj | 119 | ||||
-rw-r--r-- | pom.xml | 6 |
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-p |