diff src/clojure/contrib/jmx/data.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/clojure/contrib/jmx/data.clj	Sat Aug 21 06:25:44 2010 -0400
     1.3 @@ -0,0 +1,104 @@
     1.4 +;; Conversions between JMX data structures and idiomatic Clojure
     1.5 +;; docs in clojure/contrib/jmx.clj!!
     1.6 +
     1.7 +;; by Stuart Halloway
     1.8 +
     1.9 +;; Copyright (c) Stuart Halloway, 2009. All rights reserved.  The use
    1.10 +;; and distribution terms for this software are covered by the Eclipse
    1.11 +;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
    1.12 +;; which can be found in the file epl-v10.html at the root of this
    1.13 +;; distribution.  By using this software in any fashion, you are
    1.14 +;; agreeing to be bound by the terms of this license.  You must not
    1.15 +;; remove this notice, or any other, from this software.
    1.16 +
    1.17 +
    1.18 +(in-ns 'clojure.contrib.jmx)
    1.19 +
    1.20 +(declare jmx->clj)
    1.21 +
    1.22 +(defn jmx-url
    1.23 +  "Build a JMX URL from options."
    1.24 +  ([] (jmx-url {}))
    1.25 +  ([overrides]
    1.26 +     (let [opts (merge {:host "localhost", :port "3000", :jndi-path "jmxrmi"} overrides)]
    1.27 +       (format "service:jmx:rmi:///jndi/rmi://%s:%s/%s" (opts :host) (opts :port) (opts :jndi-path)))))
    1.28 +
    1.29 +(defmulti as-object-name
    1.30 +  "Interpret an object as a JMX ObjectName."
    1.31 +  { :arglists '([string-or-name]) }
    1.32 +  class)
    1.33 +(defmethod as-object-name String [n] (ObjectName. n))
    1.34 +(defmethod as-object-name ObjectName [n] n)
    1.35 +
    1.36 +(defn composite-data->map [cd]
    1.37 +  (into {}
    1.38 +        (map (fn [attr] [(keyword attr) (jmx->clj (.get cd attr))])
    1.39 +             (.. cd getCompositeType keySet))))
    1.40 +
    1.41 +(defn maybe-keywordize
    1.42 +  "Convert a string key to a keyword, leaving other types alone. Used to
    1.43 +   simplify keys in the tabular data API."
    1.44 +  [s]
    1.45 +  (if (string? s) (keyword s) s))
    1.46 +
    1.47 +(defn maybe-atomize
    1.48 +  "Convert a list of length 1 into its contents, leaving other things alone.
    1.49 +  Used to simplify keys in the tabular data API."
    1.50 +  [k]
    1.51 +  (if (and (instance? java.util.List k)
    1.52 +           (= 1 (count k)))
    1.53 +    (first k)
    1.54 +    k))
    1.55 +
    1.56 +(defvar simplify-tabular-data-key
    1.57 +  (comp maybe-keywordize maybe-atomize))
    1.58 +
    1.59 +(defn tabular-data->map [td]
    1.60 +  (into {}
    1.61 +        ; the need for into-array here was a surprise, and may not
    1.62 +        ; work for all examples. Are keys always arrays?
    1.63 +        (map (fn [k]
    1.64 +               [(simplify-tabular-data-key k) (jmx->clj (.get td (into-array k)))])
    1.65 +             (.keySet td))))
    1.66 +
    1.67 +(defmulti jmx->clj
    1.68 +  "Coerce JMX data structures into Clojure data.
    1.69 +  Handles CompositeData, TabularData, maps, and atoms."
    1.70 +  { :argslists '([jmx-data-structure]) }
    1.71 +  (fn [x]
    1.72 +    (cond
    1.73 +     (instance? javax.management.openmbean.CompositeData x) :composite
    1.74 +     (instance? javax.management.openmbean.TabularData x) :tabular
    1.75 +     (instance? clojure.lang.Associative x) :map
    1.76 +     :default :default)))
    1.77 +(defmethod jmx->clj :composite [c] (composite-data->map c))
    1.78 +(defmethod jmx->clj :tabular [t] (tabular-data->map t))
    1.79 +(defmethod jmx->clj :map [m]  (into {} (zipmap (keys m) (map jmx->clj (vals m)))))
    1.80 +(defmethod jmx->clj :default [obj] obj)
    1.81 +
    1.82 +(def guess-attribute-map
    1.83 +     {"java.lang.Integer" "int"
    1.84 +      "java.lang.Boolean" "boolean"
    1.85 +      "java.lang.Long" "long"
    1.86 +      })
    1.87 +
    1.88 +(defn guess-attribute-typename
    1.89 +  "Guess the attribute typename for MBeanAttributeInfo based on the attribute value."
    1.90 +  [value]
    1.91 +  (let [classname (.getName (class value))]
    1.92 +    (get guess-attribute-map classname classname)))
    1.93 +
    1.94 +(defn build-attribute-info
    1.95 +  "Construct an MBeanAttributeInfo. Normally called with a key/value pair from a Clojure map."
    1.96 +  ([attr-name attr-value]
    1.97 +     (build-attribute-info
    1.98 +      (as-str attr-name)
    1.99 +      (guess-attribute-typename attr-value)
   1.100 +      (as-str attr-name) true false false))
   1.101 +  ([name type desc readable? writable? is?] (MBeanAttributeInfo. name type desc readable? writable? is? )))
   1.102 +
   1.103 +(defn map->attribute-infos
   1.104 +  "Construct an MBeanAttributeInfo[] from a Clojure associative."
   1.105 +  [attr-map]
   1.106 +  (into-array (map (fn [[attr-name value]] (build-attribute-info attr-name value))
   1.107 +                   attr-map)))