(:Verbose :ObjectPendingFinalizationCount
56 | :HeapMemoryUsage :NonHeapMemoryUsage)
57 | ```
58 |
59 | What is the value of an attribute?
60 |
61 | ```clojure
62 | (jmx/read "java.lang:type=Memory" :ObjectPendingFinalizationCount)
63 | -> 0
64 | ```
65 |
66 | Give me all the attributes:
67 |
68 | ```clojure
69 | (jmx/mbean "java.lang:type=Memory")
70 | -> {:NonHeapMemoryUsage
71 | {:used 16674024, :max 138412032, :init 24317952, :committed 24317952},
72 | :HeapMemoryUsage
73 | {:used 18619064, :max 85393408, :init 0, :committed 83230720},
74 | :ObjectPendingFinalizationCount 0,
75 | :Verbose false}
76 | ```
77 |
78 | Find an invoke an operation:
79 |
80 | ```clojure
81 | (jmx/operation-names "java.lang:type=Memory")
82 | -> (:gc)
83 | (jmx/invoke "java.lang:type=Memory" :gc)
84 | -> nil
85 | ```
86 |
87 | Conneting to another process? Just run *any* of the above code
88 | inside a with-connection:
89 |
90 | ```clojure
91 | (jmx/with-connection {:host "localhost", :port 3000}
92 | (jmx/mbean "java.lang:type=Memory"))
93 | -> {:ObjectPendingFinalizationCount 0,
94 | :HeapMemoryUsage ... etc.}
95 | ```
96 |
97 | Serve your own beans. Drop a Clojure ref into create-bean
98 | to expose read-only attributes for every key/value pair
99 | in the ref:
100 |
101 | ```clojure
102 | (jmx/register-mbean
103 | (jmx/create-bean
104 | (ref {:string-attribute "a-string"}))
105 | "my.namespace:name=Value")}
106 | ```
107 |
108 | Developer Information
109 | ========================================
110 |
111 | * [GitHub project](https://github.com/clojure/java.jmx)
112 | * [Bug Tracker](https://clojure.atlassian.net/browse/JMX)
113 | * [Continuous Integration](https://github.com/clojure/java.jmx/actions/workflows/test.yml)
114 |
115 | Building
116 | ====================
117 |
118 | 0. Clone the repo
119 | 1. Make sure you have maven installed
120 | 2. Run the maven build: `mvn install` will produce a JAR file in the
121 | target directory, and run all tests with the most recently-released build
122 | of Clojure.
123 |
124 | ## License
125 |
126 | Copyright © Stuart Halloway, Rich Hickey & contributors.
127 |
128 | Licensed under the EPL. (See the file epl.html.)
129 |
--------------------------------------------------------------------------------
/src/test/clojure/clojure/java/test_jmx.clj:
--------------------------------------------------------------------------------
1 | ;; Tests for JMX support for Clojure
2 |
3 | ;; by Stuart Halloway
4 |
5 | ;; Copyright (c) Stuart Halloway. All rights reserved. The use
6 | ;; and distribution terms for this software are covered by the Eclipse
7 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
8 | ;; which can be found in the file epl-v10.html at the root of this
9 | ;; distribution. By using this software in any fashion, you are
10 | ;; agreeing to be bound by the terms of this license. You must not
11 | ;; remove this notice, or any other, from this software.
12 |
13 | (ns clojure.java.test-jmx
14 | (:import javax.management.openmbean.CompositeDataSupport
15 | [javax.management MBeanAttributeInfo Attribute AttributeList InstanceNotFoundException]
16 | [java.util.logging LogManager Logger])
17 | (:use clojure.test)
18 | (:require [clojure.java [jmx :as jmx]]))
19 |
20 |
21 | (defn =set [a b]
22 | (= (set a) (set b)))
23 |
24 | (defn seq-contains-all?
25 | "Does container contain every item in containee?
26 | Not fast. Testing use only"
27 | [container containee]
28 | (let [container (set container)]
29 | (every? #(contains? container %) containee)))
30 |
31 | (deftest finding-mbeans
32 | (testing "as-object-name"
33 | (are [cname object-name]
34 | (= cname (.getCanonicalName object-name))
35 | "java.lang:type=Memory" (jmx/as-object-name "java.lang:type=Memory")))
36 | (testing "mbean-names"
37 | (are [cnames object-name]
38 | (= cnames (map #(.getCanonicalName %) object-name))
39 | ["java.lang:type=Memory"] (jmx/mbean-names "java.lang:type=Memory"))))
40 |
41 | ; These actual beans may differ on different JVM platforms.
42 | ; Tested April 2010 to work on Sun and IBM JDKs.
43 | (deftest testing-actual-beans
44 | (testing "reflecting on capabilities"
45 | (are [attr-list mbean-name]
46 | (seq-contains-all? (jmx/attribute-names mbean-name) attr-list)
47 | [:Verbose :ObjectPendingFinalizationCount :HeapMemoryUsage :NonHeapMemoryUsage] "java.lang:type=Memory")
48 | (are [op-list mbean-name]
49 | (seq-contains-all? (jmx/operation-names mbean-name) op-list)
50 | [:gc] "java.lang:type=Memory"))
51 | (testing "mbean-from-oname"
52 | (are [key-names oname]
53 | (seq-contains-all? (keys (jmx/mbean oname)) key-names)
54 | [:Verbose :ObjectPendingFinalizationCount :HeapMemoryUsage :NonHeapMemoryUsage] "java.lang:type=Memory")))
55 |
56 | (deftest raw-reading-attributes
57 | (let [mem "java.lang:type=Memory"
58 | log "java.util.logging:type=Logging"]
59 | (testing "simple scalar attributes"
60 | (are [a b] (= a b)
61 | false (jmx/raw-read mem :Verbose))
62 | (are [type attr] (instance? type attr)
63 | Number (jmx/raw-read mem :ObjectPendingFinalizationCount)))
64 | (testing "reading multiple attributes"
65 | (are [a b] (= a b)
66 | false ((jmx/raw-read mem [:Verbose]) :Verbose))
67 | (are [type attr] (instance? type attr)
68 | Number ((jmx/raw-read mem [:ObjectPendingFinalizationCount]) :ObjectPendingFinalizationCount)))))
69 |
70 | (deftest reading-attributes
71 | (testing "simple scalar attributes"
72 | (is (jmx/readable? "java.lang:type=Memory" :ObjectPendingFinalizationCount))
73 | (are [type attr] (instance? type attr)
74 | Number (jmx/read "java.lang:type=Memory" :ObjectPendingFinalizationCount)))
75 | (testing "composite attributes"
76 | (is (jmx/readable? "java.lang:type=Memory" :HeapMemoryUsage))
77 | (are [ks attr] (=set ks (keys attr))
78 | [:used :max :init :committed] (jmx/read "java.lang:type=Memory" :HeapMemoryUsage)))
79 | (testing "tabular attributes"
80 | (is (jmx/readable? "java.lang:type=Runtime" :SystemProperties))
81 | (is (map? (jmx/read "java.lang:type=Runtime" :SystemProperties)))))
82 |
83 | (deftest reading-multiple-attributes
84 | (testing "simple scalar attributes"
85 | (are [type attr] (instance? type attr)
86 | Number ((jmx/read "java.lang:type=Memory" [:ObjectPendingFinalizationCount]) :ObjectPendingFinalizationCount)))
87 | (testing "composite attributes"
88 | (are [ks attr] (=set ks (keys attr))
89 | [:used :max :init :committed]
90 | ((jmx/read "java.lang:type=Memory" [:HeapMemoryUsage :NonHeapMemoryUsage]) :HeapMemoryUsage)))
91 | (testing "tabular attributes"
92 | (is (map? ((jmx/read "java.lang:type=Runtime" [:SystemProperties]) :SystemProperties)))))
93 |
94 | (deftest writing-attributes
95 | (let [mem "java.lang:type=Memory"]
96 | (jmx/write! mem :Verbose true)
97 | (is (true? (jmx/read mem :Verbose)))
98 | (jmx/write! mem :Verbose false)
99 | (is (false? (jmx/read mem :Verbose)))))
100 |
101 | (deftest test-invoke-operations
102 | (testing "without arguments"
103 | (jmx/invoke "java.lang:type=Memory" :gc))
104 | (testing "with arguments"
105 | (.addLogger (LogManager/getLogManager) (Logger/getLogger "clojure.java.test_jmx"))
106 | (jmx/invoke "java.util.logging:type=Logging" :setLoggerLevel "clojure.java.test_jmx" "WARNING"))
107 | (testing "with signature"
108 | (jmx/invoke-signature "java.lang:type=Threading" :getThreadInfo ["long"] 1)
109 | (jmx/invoke-signature "java.lang:type=Threading" :getThreadInfo ["long" "int"] 1 (new java.lang.Integer 1))))
110 |
111 | (deftest test-objects->data
112 | (let [objects (jmx/raw-read "java.lang:type=Memory" :HeapMemoryUsage)
113 | prox (jmx/objects->data objects)]
114 | (testing "returns a map with keyword keys"
115 | (is (= (set [:committed :init :max :used]) (set (keys prox))))))
116 | (let [raw-props (jmx/raw-read "java.lang:type=Runtime" :SystemProperties)
117 | props (jmx/objects->data raw-props)]
118 | (are [k] (contains? props k)
119 | :java.class.path
120 | :path.separator))
121 | (testing "it works recursively on maps"
122 | (let [some-map {:foo (jmx/raw-read "java.lang:type=Memory" :HeapMemoryUsage)}]
123 | (is (map? (:foo (jmx/objects->data some-map))))))
124 | (testing "it handles null references"
125 | (is (nil? (jmx/objects->data nil))))
126 | (testing "it leaves everything else untouched"
127 | (is (= "foo" (jmx/objects->data "foo")))))
128 |
129 | (deftest test-creating-attribute-infos
130 | (let [infos (@#'jmx/map->attribute-infos [[:a 1] [:b 2]])
131 | info (first infos)]
132 | (testing "generates the right class"
133 | (is (= (class (into-array MBeanAttributeInfo [])) (class infos))))
134 | (testing "generates the right instance data"
135 | (are [result expr] (= result expr)
136 | "a" (.getName info)
137 | "a" (.getDescription info)))))
138 |
139 | (deftest various-beans-are-readable
140 | (testing "that all java.lang beans can be read without error"
141 | (doseq [mb (jmx/mbean-names "*:*")]
142 | (is (map? (jmx/mbean mb)) mb))))
143 |
144 | (deftest test-jmx-url
145 | (testing "creates default url"
146 | (is (= "service:jmx:rmi:///jndi/rmi://localhost:3000/jmxrmi"
147 | (jmx/jmx-url))))
148 | (testing "creates custom url"
149 | (is (= "service:jmx:rmi:///jndi/rmi://example.com:4000/jmxrmi"
150 | (jmx/jmx-url {:host "example.com" :port 4000}))))
151 | (testing "creates custom jndi path"
152 | (is (= "service:jmx:rmi:///jndi/rmi://example.com:4000/jmxconnector"
153 | (jmx/jmx-url {:host "example.com" :port 4000 :jndi-path "jmxconnector"})))))
154 |
155 | ;; ----------------------------------------------------------------------
156 | ;; tests for clojure.java.jmx.Bean.
157 |
158 | (deftest dynamic-mbean-from-compiled-class
159 | (let [mbean-name "clojure.java.test_jmx:name=Foo"]
160 | (jmx/register-mbean
161 | (jmx/create-bean
162 | (ref {:string-attribute "a-string"}))
163 | mbean-name)
164 | (are [result expr] (= result expr)
165 | "a-string" (jmx/read mbean-name :string-attribute)
166 | {:string-attribute "a-string"} (jmx/mbean mbean-name)
167 | )))
168 |
169 | (deftest test-getAttribute
170 | (doseq [reftype [ref atom agent]]
171 | (let [state (reftype {:a 1 :b 2})
172 | bean (jmx/create-bean state)]
173 | (testing (str "accessing values from a " (class state))
174 | (are [result expr] (= result expr)
175 | 1 (.getAttribute bean "a")
176 | 2 (.getAttribute bean "b"))))))
177 |
178 | (deftest test-setAttribute
179 | (doseq [reftype [ref atom agent]]
180 | (let [state (reftype {:a 1 :b 2})
181 | bean (jmx/create-bean state)]
182 | (testing (str "setting values on a " (class state))
183 | (.setAttribute bean (Attribute. "a" 3))
184 | (are [result expr] (= result expr)
185 | 3 (.getAttribute bean "a")
186 | 2 (.getAttribute bean "b"))))))
187 |
188 | (deftest test-setAttributes
189 | (doseq [reftype [ref atom agent]]
190 | (let [state (reftype {:r 5 :d 4})
191 | bean (jmx/create-bean state)
192 | atts (.setAttributes bean (AttributeList. [(Attribute. "r" 6)
193 | (Attribute. "d" 5)]))]
194 | (are [x y] (= x y)
195 | AttributeList (class atts)
196 | ["r" "d"] (map (memfn getName) (seq atts))
197 | [6 5] (map (memfn getValue) (seq atts))))))
198 |
199 | (deftest test-bean-info
200 | (let [state (ref {:a 1 :b 2})
201 | bean (jmx/create-bean state)
202 | info (.getMBeanInfo bean)]
203 | (testing "accessing info"
204 | (are [result expr] (= result expr)
205 | "clojure.java.jmx.Bean" (.getClassName info)))))
206 |
207 | (deftest test-getAttributes
208 | (let [bean (jmx/create-bean (ref {:r 5 :d 4}))
209 | atts (.getAttributes bean (into-array ["r" "d"]))]
210 | (are [x y] (= x y)
211 | AttributeList (class atts)
212 | ["r" "d"] (map (memfn getName) (seq atts))
213 | [5 4] (map (memfn getValue) (seq atts)))))
214 |
215 | (deftest test-guess-attribute-typename
216 | (are [x y] (= x (@#'jmx/guess-attribute-typename y))
217 | "boolean" false
218 | "java.lang.String" "foo"
219 | "long" (Long/valueOf (long 10)))
220 | (is (= "long" (@#'jmx/guess-attribute-typename 10))))
221 |
222 | (deftest test-unregister-mbean
223 | (let [mbean (jmx/create-bean (ref {:a-property 123}))
224 | mbean-name "clojure.java.test_jmx:name=UnregisterTest"]
225 | (jmx/register-mbean mbean mbean-name)
226 | (is (= 123 (jmx/read mbean-name :a-property)))
227 | (jmx/unregister-mbean mbean-name)
228 | (if (= [1 3] [(*clojure-version* :major) (*clojure-version* :minor)])
229 | ; clojure 1.3 throws RuntimeException directly for some reason so catch that and
230 | ; verify that the underlying exception is right
231 | (try
232 | (jmx/read mbean-name :a-property)
233 | (catch RuntimeException e
234 | (is (instance? InstanceNotFoundException (.getCause e)))))
235 | (is (thrown? InstanceNotFoundException (jmx/read mbean-name :a-property))))))
236 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Eclipse Public License - v 1.0
2 |
3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6 |
7 | 1. DEFINITIONS
8 |
9 | "Contribution" means:
10 |
11 | a) in the case of the initial Contributor, the initial code and documentation
12 | distributed under this Agreement, and
13 | b) in the case of each subsequent Contributor:
14 | i) changes to the Program, and
15 | ii) additions to the Program;
16 |
17 | where such changes and/or additions to the Program originate from and are
18 | distributed by that particular Contributor. A Contribution 'originates'
19 | from a Contributor if it was added to the Program by such Contributor
20 | itself or anyone acting on such Contributor's behalf. Contributions do not
21 | include additions to the Program which: (i) are separate modules of
22 | software distributed in conjunction with the Program under their own
23 | license agreement, and (ii) are not derivative works of the Program.
24 |
25 | "Contributor" means any person or entity that distributes the Program.
26 |
27 | "Licensed Patents" mean patent claims licensable by a Contributor which are
28 | necessarily infringed by the use or sale of its Contribution alone or when
29 | combined with the Program.
30 |
31 | "Program" means the Contributions distributed in accordance with this
32 | Agreement.
33 |
34 | "Recipient" means anyone who receives the Program under this Agreement,
35 | including all Contributors.
36 |
37 | 2. GRANT OF RIGHTS
38 | a) Subject to the terms of this Agreement, each Contributor hereby grants
39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
40 | reproduce, prepare derivative works of, publicly display, publicly
41 | perform, distribute and sublicense the Contribution of such Contributor,
42 | if any, and such derivative works, in source code and object code form.
43 | b) Subject to the terms of this Agreement, each Contributor hereby grants
44 | Recipient a non-exclusive, worldwide, royalty-free patent license under
45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
46 | transfer the Contribution of such Contributor, if any, in source code and
47 | object code form. This patent license shall apply to the combination of
48 | the Contribution and the Program if, at the time the Contribution is
49 | added by the Contributor, such addition of the Contribution causes such
50 | combination to be covered by the Licensed Patents. The patent license
51 | shall not apply to any other combinations which include the Contribution.
52 | No hardware per se is licensed hereunder.
53 | c) Recipient understands that although each Contributor grants the licenses
54 | to its Contributions set forth herein, no assurances are provided by any
55 | Contributor that the Program does not infringe the patent or other
56 | intellectual property rights of any other entity. Each Contributor
57 | disclaims any liability to Recipient for claims brought by any other
58 | entity based on infringement of intellectual property rights or
59 | otherwise. As a condition to exercising the rights and licenses granted
60 | hereunder, each Recipient hereby assumes sole responsibility to secure
61 | any other intellectual property rights needed, if any. For example, if a
62 | third party patent license is required to allow Recipient to distribute
63 | the Program, it is Recipient's responsibility to acquire that license
64 | before distributing the Program.
65 | d) Each Contributor represents that to its knowledge it has sufficient
66 | copyright rights in its Contribution, if any, to grant the copyright
67 | license set forth in this Agreement.
68 |
69 | 3. REQUIREMENTS
70 |
71 | A Contributor may choose to distribute the Program in object code form under
72 | its own license agreement, provided that:
73 |
74 | a) it complies with the terms and conditions of this Agreement; and
75 | b) its license agreement:
76 | i) effectively disclaims on behalf of all Contributors all warranties
77 | and conditions, express and implied, including warranties or
78 | conditions of title and non-infringement, and implied warranties or
79 | conditions of merchantability and fitness for a particular purpose;
80 | ii) effectively excludes on behalf of all Contributors all liability for
81 | damages, including direct, indirect, special, incidental and
82 | consequential damages, such as lost profits;
83 | iii) states that any provisions which differ from this Agreement are
84 | offered by that Contributor alone and not by any other party; and
85 | iv) states that source code for the Program is available from such
86 | Contributor, and informs licensees how to obtain it in a reasonable
87 | manner on or through a medium customarily used for software exchange.
88 |
89 | When the Program is made available in source code form:
90 |
91 | a) it must be made available under this Agreement; and
92 | b) a copy of this Agreement must be included with each copy of the Program.
93 | Contributors may not remove or alter any copyright notices contained
94 | within the Program.
95 |
96 | Each Contributor must identify itself as the originator of its Contribution,
97 | if
98 | any, in a manner that reasonably allows subsequent Recipients to identify the
99 | originator of the Contribution.
100 |
101 | 4. COMMERCIAL DISTRIBUTION
102 |
103 | Commercial distributors of software may accept certain responsibilities with
104 | respect to end users, business partners and the like. While this license is
105 | intended to facilitate the commercial use of the Program, the Contributor who
106 | includes the Program in a commercial product offering should do so in a manner
107 | which does not create potential liability for other Contributors. Therefore,
108 | if a Contributor includes the Program in a commercial product offering, such
109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
110 | every other Contributor ("Indemnified Contributor") against any losses,
111 | damages and costs (collectively "Losses") arising from claims, lawsuits and
112 | other legal actions brought by a third party against the Indemnified
113 | Contributor to the extent caused by the acts or omissions of such Commercial
114 | Contributor in connection with its distribution of the Program in a commercial
115 | product offering. The obligations in this section do not apply to any claims
116 | or Losses relating to any actual or alleged intellectual property
117 | infringement. In order to qualify, an Indemnified Contributor must:
118 | a) promptly notify the Commercial Contributor in writing of such claim, and
119 | b) allow the Commercial Contributor to control, and cooperate with the
120 | Commercial Contributor in, the defense and any related settlement
121 | negotiations. The Indemnified Contributor may participate in any such claim at
122 | its own expense.
123 |
124 | For example, a Contributor might include the Program in a commercial product
125 | offering, Product X. That Contributor is then a Commercial Contributor. If
126 | that Commercial Contributor then makes performance claims, or offers
127 | warranties related to Product X, those performance claims and warranties are
128 | such Commercial Contributor's responsibility alone. Under this section, the
129 | Commercial Contributor would have to defend claims against the other
130 | Contributors related to those performance claims and warranties, and if a
131 | court requires any other Contributor to pay any damages as a result, the
132 | Commercial Contributor must pay those damages.
133 |
134 | 5. NO WARRANTY
135 |
136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
140 | Recipient is solely responsible for determining the appropriateness of using
141 | and distributing the Program and assumes all risks associated with its
142 | exercise of rights under this Agreement , including but not limited to the
143 | risks and costs of program errors, compliance with applicable laws, damage to
144 | or loss of data, programs or equipment, and unavailability or interruption of
145 | operations.
146 |
147 | 6. DISCLAIMER OF LIABILITY
148 |
149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
156 | OF SUCH DAMAGES.
157 |
158 | 7. GENERAL
159 |
160 | If any provision of this Agreement is invalid or unenforceable under
161 | applicable law, it shall not affect the validity or enforceability of the
162 | remainder of the terms of this Agreement, and without further action by the
163 | parties hereto, such provision shall be reformed to the minimum extent
164 | necessary to make such provision valid and enforceable.
165 |
166 | If Recipient institutes patent litigation against any entity (including a
167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
168 | (excluding combinations of the Program with other software or hardware)
169 | infringes such Recipient's patent(s), then such Recipient's rights granted
170 | under Section 2(b) shall terminate as of the date such litigation is filed.
171 |
172 | All Recipient's rights under this Agreement shall terminate if it fails to
173 | comply with any of the material terms or conditions of this Agreement and does
174 | not cure such failure in a reasonable period of time after becoming aware of
175 | such noncompliance. If all Recipient's rights under this Agreement terminate,
176 | Recipient agrees to cease use and distribution of the Program as soon as
177 | reasonably practicable. However, Recipient's obligations under this Agreement
178 | and any licenses granted by Recipient relating to the Program shall continue
179 | and survive.
180 |
181 | Everyone is permitted to copy and distribute copies of this Agreement, but in
182 | order to avoid inconsistency the Agreement is copyrighted and may only be
183 | modified in the following manner. The Agreement Steward reserves the right to
184 | publish new versions (including revisions) of this Agreement from time to
185 | time. No one other than the Agreement Steward has the right to modify this
186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The
187 | Eclipse Foundation may assign the responsibility to serve as the Agreement
188 | Steward to a suitable separate entity. Each new version of the Agreement will
189 | be given a distinguishing version number. The Program (including
190 | Contributions) may always be distributed subject to the version of the
191 | Agreement under which it was received. In addition, after a new version of the
192 | Agreement is published, Contributor may elect to distribute the Program
193 | (including its Contributions) under the new version. Except as expressly
194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
195 | licenses to the intellectual property of any Contributor under this Agreement,
196 | whether expressly, by implication, estoppel or otherwise. All rights in the
197 | Program not expressly granted under this Agreement are reserved.
198 |
199 | This Agreement is governed by the laws of the State of New York and the
200 | intellectual property laws of the United States of America. No party to this
201 | Agreement will bring a legal action under this Agreement more than one year
202 | after the cause of action arose. Each party waives its rights to a jury trial in
203 | any resulting litigation.
204 |
205 |
206 |
--------------------------------------------------------------------------------
/epl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Eclipse Public License - Version 1.0
8 |
25 |
26 |
27 |
28 |
29 |
30 | Eclipse Public License - v 1.0
31 |
32 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
33 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
34 | DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
35 | AGREEMENT.
36 |
37 | 1. DEFINITIONS
38 |
39 | "Contribution" means:
40 |
41 | a) in the case of the initial Contributor, the initial
42 | code and documentation distributed under this Agreement, and
43 | b) in the case of each subsequent Contributor:
44 | i) changes to the Program, and
45 | ii) additions to the Program;
46 | where such changes and/or additions to the Program
47 | originate from and are distributed by that particular Contributor. A
48 | Contribution 'originates' from a Contributor if it was added to the
49 | Program by such Contributor itself or anyone acting on such
50 | Contributor's behalf. Contributions do not include additions to the
51 | Program which: (i) are separate modules of software distributed in
52 | conjunction with the Program under their own license agreement, and (ii)
53 | are not derivative works of the Program.
54 |
55 | "Contributor" means any person or entity that distributes
56 | the Program.
57 |
58 | "Licensed Patents" mean patent claims licensable by a
59 | Contributor which are necessarily infringed by the use or sale of its
60 | Contribution alone or when combined with the Program.
61 |
62 | "Program" means the Contributions distributed in accordance
63 | with this Agreement.
64 |
65 | "Recipient" means anyone who receives the Program under
66 | this Agreement, including all Contributors.
67 |
68 | 2. GRANT OF RIGHTS
69 |
70 | a) Subject to the terms of this Agreement, each
71 | Contributor hereby grants Recipient a non-exclusive, worldwide,
72 | royalty-free copyright license to reproduce, prepare derivative works
73 | of, publicly display, publicly perform, distribute and sublicense the
74 | Contribution of such Contributor, if any, and such derivative works, in
75 | source code and object code form.
76 |
77 | b) Subject to the terms of this Agreement, each
78 | Contributor hereby grants Recipient a non-exclusive, worldwide,
79 | royalty-free patent license under Licensed Patents to make, use, sell,
80 | offer to sell, import and otherwise transfer the Contribution of such
81 | Contributor, if any, in source code and object code form. This patent
82 | license shall apply to the combination of the Contribution and the
83 | Program if, at the time the Contribution is added by the Contributor,
84 | such addition of the Contribution causes such combination to be covered
85 | by the Licensed Patents. The patent license shall not apply to any other
86 | combinations which include the Contribution. No hardware per se is
87 | licensed hereunder.
88 |
89 | c) Recipient understands that although each Contributor
90 | grants the licenses to its Contributions set forth herein, no assurances
91 | are provided by any Contributor that the Program does not infringe the
92 | patent or other intellectual property rights of any other entity. Each
93 | Contributor disclaims any liability to Recipient for claims brought by
94 | any other entity based on infringement of intellectual property rights
95 | or otherwise. As a condition to exercising the rights and licenses
96 | granted hereunder, each Recipient hereby assumes sole responsibility to
97 | secure any other intellectual property rights needed, if any. For
98 | example, if a third party patent license is required to allow Recipient
99 | to distribute the Program, it is Recipient's responsibility to acquire
100 | that license before distributing the Program.
101 |
102 | d) Each Contributor represents that to its knowledge it
103 | has sufficient copyright rights in its Contribution, if any, to grant
104 | the copyright license set forth in this Agreement.
105 |
106 | 3. REQUIREMENTS
107 |
108 | A Contributor may choose to distribute the Program in object code
109 | form under its own license agreement, provided that:
110 |
111 | a) it complies with the terms and conditions of this
112 | Agreement; and
113 |
114 | b) its license agreement:
115 |
116 | i) effectively disclaims on behalf of all Contributors
117 | all warranties and conditions, express and implied, including warranties
118 | or conditions of title and non-infringement, and implied warranties or
119 | conditions of merchantability and fitness for a particular purpose;
120 |
121 | ii) effectively excludes on behalf of all Contributors
122 | all liability for damages, including direct, indirect, special,
123 | incidental and consequential damages, such as lost profits;
124 |
125 | iii) states that any provisions which differ from this
126 | Agreement are offered by that Contributor alone and not by any other
127 | party; and
128 |
129 | iv) states that source code for the Program is available
130 | from such Contributor, and informs licensees how to obtain it in a
131 | reasonable manner on or through a medium customarily used for software
132 | exchange.
133 |
134 | When the Program is made available in source code form:
135 |
136 | a) it must be made available under this Agreement; and
137 |
138 | b) a copy of this Agreement must be included with each
139 | copy of the Program.
140 |
141 | Contributors may not remove or alter any copyright notices contained
142 | within the Program.
143 |
144 | Each Contributor must identify itself as the originator of its
145 | Contribution, if any, in a manner that reasonably allows subsequent
146 | Recipients to identify the originator of the Contribution.
147 |
148 | 4. COMMERCIAL DISTRIBUTION
149 |
150 | Commercial distributors of software may accept certain
151 | responsibilities with respect to end users, business partners and the
152 | like. While this license is intended to facilitate the commercial use of
153 | the Program, the Contributor who includes the Program in a commercial
154 | product offering should do so in a manner which does not create
155 | potential liability for other Contributors. Therefore, if a Contributor
156 | includes the Program in a commercial product offering, such Contributor
157 | ("Commercial Contributor") hereby agrees to defend and
158 | indemnify every other Contributor ("Indemnified Contributor")
159 | against any losses, damages and costs (collectively "Losses")
160 | arising from claims, lawsuits and other legal actions brought by a third
161 | party against the Indemnified Contributor to the extent caused by the
162 | acts or omissions of such Commercial Contributor in connection with its
163 | distribution of the Program in a commercial product offering. The
164 | obligations in this section do not apply to any claims or Losses
165 | relating to any actual or alleged intellectual property infringement. In
166 | order to qualify, an Indemnified Contributor must: a) promptly notify
167 | the Commercial Contributor in writing of such claim, and b) allow the
168 | Commercial Contributor to control, and cooperate with the Commercial
169 | Contributor in, the defense and any related settlement negotiations. The
170 | Indemnified Contributor may participate in any such claim at its own
171 | expense.
172 |
173 | For example, a Contributor might include the Program in a commercial
174 | product offering, Product X. That Contributor is then a Commercial
175 | Contributor. If that Commercial Contributor then makes performance
176 | claims, or offers warranties related to Product X, those performance
177 | claims and warranties are such Commercial Contributor's responsibility
178 | alone. Under this section, the Commercial Contributor would have to
179 | defend claims against the other Contributors related to those
180 | performance claims and warranties, and if a court requires any other
181 | Contributor to pay any damages as a result, the Commercial Contributor
182 | must pay those damages.
183 |
184 | 5. NO WARRANTY
185 |
186 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
187 | PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
188 | OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
189 | ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
190 | OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
191 | responsible for determining the appropriateness of using and
192 | distributing the Program and assumes all risks associated with its
193 | exercise of rights under this Agreement , including but not limited to
194 | the risks and costs of program errors, compliance with applicable laws,
195 | damage to or loss of data, programs or equipment, and unavailability or
196 | interruption of operations.
197 |
198 | 6. DISCLAIMER OF LIABILITY
199 |
200 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
201 | NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
202 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
203 | WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
204 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
205 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
206 | DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
207 | HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
208 |
209 | 7. GENERAL
210 |
211 | If any provision of this Agreement is invalid or unenforceable under
212 | applicable law, it shall not affect the validity or enforceability of
213 | the remainder of the terms of this Agreement, and without further action
214 | by the parties hereto, such provision shall be reformed to the minimum
215 | extent necessary to make such provision valid and enforceable.
216 |
217 | If Recipient institutes patent litigation against any entity
218 | (including a cross-claim or counterclaim in a lawsuit) alleging that the
219 | Program itself (excluding combinations of the Program with other
220 | software or hardware) infringes such Recipient's patent(s), then such
221 | Recipient's rights granted under Section 2(b) shall terminate as of the
222 | date such litigation is filed.
223 |
224 | All Recipient's rights under this Agreement shall terminate if it
225 | fails to comply with any of the material terms or conditions of this
226 | Agreement and does not cure such failure in a reasonable period of time
227 | after becoming aware of such noncompliance. If all Recipient's rights
228 | under this Agreement terminate, Recipient agrees to cease use and
229 | distribution of the Program as soon as reasonably practicable. However,
230 | Recipient's obligations under this Agreement and any licenses granted by
231 | Recipient relating to the Program shall continue and survive.
232 |
233 | Everyone is permitted to copy and distribute copies of this
234 | Agreement, but in order to avoid inconsistency the Agreement is
235 | copyrighted and may only be modified in the following manner. The
236 | Agreement Steward reserves the right to publish new versions (including
237 | revisions) of this Agreement from time to time. No one other than the
238 | Agreement Steward has the right to modify this Agreement. The Eclipse
239 | Foundation is the initial Agreement Steward. The Eclipse Foundation may
240 | assign the responsibility to serve as the Agreement Steward to a
241 | suitable separate entity. Each new version of the Agreement will be
242 | given a distinguishing version number. The Program (including
243 | Contributions) may always be distributed subject to the version of the
244 | Agreement under which it was received. In addition, after a new version
245 | of the Agreement is published, Contributor may elect to distribute the
246 | Program (including its Contributions) under the new version. Except as
247 | expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
248 | rights or licenses to the intellectual property of any Contributor under
249 | this Agreement, whether expressly, by implication, estoppel or
250 | otherwise. All rights in the Program not expressly granted under this
251 | Agreement are reserved.
252 |
253 | This Agreement is governed by the laws of the State of New York and
254 | the intellectual property laws of the United States of America. No party
255 | to this Agreement will bring a legal action under this Agreement more
256 | than one year after the cause of action arose. Each party waives its
257 | rights to a jury trial in any resulting litigation.
258 |
259 |
260 |
261 |
262 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/java/jmx.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Stuart Halloway. All rights reserved. The use
2 | ;; and distribution terms for this software are covered by the Eclipse
3 | ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this
5 | ;; distribution. By using this software in any fashion, you are
6 | ;; agreeing to be bound by the terms of this license. You must not
7 | ;; remove this notice, or any other, from this software.
8 |
9 |
10 | (ns ^{:author "Stuart Halloway"
11 | :doc "JMX support for Clojure
12 |
13 | Usage
14 | (require '[clojure.java.jmx :as jmx])
15 |
16 | What beans do I have?
17 |
18 | (jmx/mbean-names \"*:*\")
19 | -> # (:Verbose :ObjectPendingFinalizationCount
26 | :HeapMemoryUsage :NonHeapMemoryUsage)
27 |
28 | What is the value of an attribute?
29 |
30 | (jmx/read \"java.lang:type=Memory\" :ObjectPendingFinalizationCount)
31 | -> 0
32 | (jmx/read \"java.lang:type=Memory\" [:HeapMemoryUsage :NonHeapMemoryUsage])
33 | ->
34 | {:NonHeapMemoryUsage
35 | {:used 16674024, :max 138412032, :init 24317952, :committed 24317952},
36 | :HeapMemoryUsage
37 | {:used 18619064, :max 85393408, :init 0, :committed 83230720}}
38 |
39 | Can't I just have *all* the attributes in a Clojure map?
40 |
41 | (jmx/mbean \"java.lang:type=Memory\")
42 | -> {:NonHeapMemoryUsage
43 | {:used 16674024, :max 138412032, :init 24317952, :committed 24317952},
44 | :HeapMemoryUsage
45 | {:used 18619064, :max 85393408, :init 0, :committed 83230720},
46 | :ObjectPendingFinalizationCount 0,
47 | :Verbose false}
48 |
49 | Can I find and invoke an operation?
50 |
51 | (jmx/operation-names \"java.lang:type=Memory\")
52 | -> (:gc)
53 | (jmx/invoke \"java.lang:type=Memory\" :gc)
54 | -> nil
55 |
56 | What about some other process? Just run *any* of the above code
57 | inside a with-connection:
58 |
59 | (jmx/with-connection {:host \"localhost\", :port 3000}
60 | (jmx/mbean \"java.lang:type=Memory\"))
61 | -> {:ObjectPendingFinalizationCount 0,
62 | :HeapMemoryUsage ... etc.}
63 |
64 | Can I serve my own beans? Sure, just drop a Clojure ref
65 | into an instance of clojure.java.jmx.Bean, and the bean
66 | will expose read-only attributes for every key/value pair
67 | in the ref:
68 |
69 | (jmx/register-mbean
70 | (create-bean
71 | (ref {:string-attribute \"a-string\"}))
72 | \"my.namespace:name=Value\")"}
73 | clojure.java.jmx
74 | (:refer-clojure :exclude [read])
75 | (:use [clojure.walk :only [postwalk]])
76 | (:import [clojure.lang Associative]
77 | java.lang.management.ManagementFactory
78 | [javax.management Attribute AttributeList DynamicMBean MBeanInfo MBeanServer
79 | ObjectName RuntimeMBeanException MBeanAttributeInfo MBeanOperationInfo
80 | MBeanParameterInfo MBeanServerConnection]
81 | [javax.management.remote JMXConnectorFactory JMXServiceURL]))
82 |
83 | (set! *warn-on-reflection* true)
84 |
85 | (def ^{:dynamic true
86 | :doc "The connection to be used for JMX ops. Defaults to the local process."
87 | :skip-wiki true
88 | :tag MBeanServerConnection}
89 | *connection*
90 | (ManagementFactory/getPlatformMBeanServer))
91 |
92 | (declare jmx->clj)
93 |
94 | (defn ^{:skip-wiki true} jmx-url
95 | "Build a JMX URL from options."
96 | ([] (jmx-url {}))
97 | ([overrides]
98 | (let [opts (merge {:protocol "rmi:///jndi/rmi", :host "localhost", :port "3000", :jndi-path "jmxrmi"} overrides)]
99 | (format "service:jmx:%s://%s:%s/%s" (opts :protocol) (opts :host) (opts :port) (opts :jndi-path)))))
100 |
101 | (defprotocol CoercionImpl
102 | (as-object-name [_]))
103 |
104 | (extend-protocol CoercionImpl
105 | String
106 | (as-object-name [_] (ObjectName. _))
107 |
108 | ObjectName
109 | (as-object-name [_] _))
110 |
111 | (defn- maybe-keywordize
112 | "Convert a string key to a keyword, leaving other types alone. Used to
113 | simplify keys in the tabular data API."
114 | [s]
115 | (if (string? s) (keyword s) s))
116 |
117 | (defn- maybe-atomize
118 | "Convert a list of length 1 into its contents, leaving other things alone.
119 | Used to simplify keys in the tabular data API."
120 | [k]
121 | (if (and (instance? java.util.List k)
122 | (= 1 (count k)))
123 | (first k)
124 | k))
125 |
126 | (def ^{:private true} simplify-tabular-data-key
127 | (comp maybe-keywordize maybe-atomize))
128 |
129 | (defprotocol ^{:skip-wiki true} Destract
130 | (objects->data [_] "Convert JMX object model into data. Handles CompositeData, TabularData, maps, and atoms."))
131 |
132 | (extend-protocol Destract
133 | javax.management.openmbean.CompositeData
134 | (objects->data
135 | [cd]
136 | (into {}
137 | (map (fn [attr] [(keyword attr) (objects->data (.get cd attr))])
138 | (.. cd getCompositeType keySet))))
139 |
140 | javax.management.openmbean.TabularData
141 | (objects->data
142 | [td]
143 | (into {}
144 | (map (fn [k]
145 | [(simplify-tabular-data-key k) (objects->data (.get td (into-array k)))])
146 | (.keySet td))))
147 | clojure.lang.Associative
148 | (objects->data
149 | [m]
150 | (into {} (zipmap (keys m) (map objects->data (vals m)))))
151 |
152 | java.lang.Boolean
153 | (objects->data [b] (boolean b))
154 | Object
155 | (objects->data [obj] obj)
156 | nil
157 | (objects->data [_] nil))
158 |
159 | (def ^{:private true} guess-attribute-map
160 | {"java.lang.Integer" "int"
161 | "java.lang.Boolean" "boolean"
162 | "java.lang.Long" "long"
163 | })
164 |
165 | (defn- guess-attribute-typename
166 | "Guess the attribute typename for MBeanAttributeInfo based on the attribute value."
167 | [value]
168 | (let [classname (.getName (class value))]
169 | (get guess-attribute-map classname classname)))
170 |
171 | (defn- build-attribute-info
172 | "Construct an MBeanAttributeInfo. Normally called with a key/value pair from a Clojure map."
173 | ([attr-name attr-value]
174 | (build-attribute-info
175 | (name attr-name)
176 | (guess-attribute-typename attr-value)
177 | (name attr-name) true false false))
178 | ([name type desc readable? writable? is?] (MBeanAttributeInfo. name type desc readable? writable? is? )))
179 |
180 | (defn- map->attribute-infos
181 | "Construct an MBeanAttributeInfo[] from a Clojure associative."
182 | [attr-map]
183 | (into-array MBeanAttributeInfo
184 | (map (fn [[attr-name value]] (build-attribute-info attr-name value))
185 | attr-map)))
186 |
187 | (defmacro with-connection
188 | "Execute body with a JMX connection created based on opts. opts can include [default]:
189 |
190 | :protocol The protocol to use [rmi:///jndi/rmi]
191 | :host The host to connect to [localhost]
192 | :port The port to connect to [3000]
193 | :jndi-path The jndi-path to use [jmxuri]
194 | :url The full url (as a String) to use instead of generating a rmi url from
195 | the above options [nil]
196 | :environment A map representing the environment used for the connection.
197 | See JMXConnectorFactory/connect for details [{}]"
198 | [opts & body]
199 | `(let [opts# ~opts
200 | env# (get opts# :environment {})
201 | opts# (dissoc opts# :environment)]
202 | (with-open [connector# (javax.management.remote.JMXConnectorFactory/connect
203 | (JMXServiceURL. (:url opts# (jmx-url opts#)))
204 | env#)]
205 | (binding [*connection* (.getMBeanServerConnection connector#)]
206 | ~@body))))
207 |
208 | (defn ^{:skip-wiki true} mbean-info
209 | ^MBeanInfo [n]
210 | (.getMBeanInfo *connection* (as-object-name n)))
211 |
212 | (defn ^{:skip-wiki true} raw-read
213 | "Read a list of mbean properties. Returns low-level Java object
214 | models for composites, tabulars, etc. Most callers should use
215 | read."
216 | [n attrs]
217 | (if (sequential? attrs)
218 | (into {}
219 | (map (fn [^Attribute attr] [(keyword (.getName attr)) (.getValue attr)])
220 | (.getAttributes *connection*
221 | (as-object-name n)
222 | (into-array (map name attrs)))))
223 | (.getAttribute *connection* (as-object-name n) (name attrs))))
224 |
225 | (def ^{:doc "Read one or more mbean properties."}
226 | read
227 | (comp objects->data raw-read))
228 |
229 | (defn- read-supported
230 | "Calls read to read an mbean property, *returning* unsupported
231 | operation exceptions instead of throwing them. Used to keep mbean
232 | from blowing up. Note: There is no good exception that aggregates
233 | unsupported operations, hence the overly-general catch block."
234 | [n attr]
235 | (try
236 | (read n attr)
237 | (catch Exception e
238 | e)))
239 |
240 | (defn write!
241 | "Write an attribute value."
242 | [n attr value]
243 | (.setAttribute
244 | ^MBeanServerConnection *connection*
245 | ^ObjectName (as-object-name n)
246 | (Attribute. ^String (name attr) ^String value)))
247 |
248 | (defn ^{:skip-wiki true} attribute-info
249 | "Get the MBeanAttributeInfo for an attribute."
250 | ^MBeanAttributeInfo [object-name attr-name]
251 | (first
252 | (filter #(= (name attr-name) (.getName ^MBeanAttributeInfo %))
253 | (.getAttributes (mbean-info object-name)))))
254 |
255 | (defn readable?
256 | "Is attribute readable?"
257 | [n attr]
258 | (.isReadable (attribute-info n attr)))
259 |
260 | (defn ^{:skip-wiki true} operations
261 | "All operations available on an MBean."
262 | [n]
263 | (.getOperations (mbean-info n)))
264 |
265 | (defn- operation
266 | "The MBeanOperationInfo for operation op on mbean n. Used by invoke."
267 | ^MBeanOperationInfo [n op]
268 | (first (filter (fn [^MBeanOperationInfo info]
269 | (= (-> info .getName keyword) op)) (operations n))))
270 |
271 | (defn- op-param-types
272 | "The parameter types (as class name strings) for operation op on n.
273 | Used for invoke."
274 | [n op]
275 | (map #(.getType ^MBeanParameterInfo %)
276 | (.getSignature (operation n op))))
277 |
278 | (defn register-mbean
279 | "Register an mbean with the current *connection*."
280 | [mbean mbean-name]
281 | (.registerMBean ^MBeanServer *connection* mbean (as-object-name mbean-name)))
282 |
283 | (defn unregister-mbean
284 | "Unregister mbean named mbean-name with the current *connection*."
285 | [mbean-name]
286 | (.unregisterMBean *connection* (as-object-name mbean-name)))
287 |
288 | (defn mbean-names
289 | "Finds all MBeans matching a name on the current *connection*."
290 | [n]
291 | (.queryNames *connection* (as-object-name n) nil))
292 |
293 | (defn attribute-names
294 | "All attribute names available on an MBean."
295 | [n]
296 | (doall (map (fn [^MBeanAttributeInfo info]
297 | (-> info .getName keyword))
298 | (.getAttributes (mbean-info n)))))
299 |
300 | (defn operation-names
301 | "All operation names available on an MBean."
302 | [n]
303 | (doall (map (fn [^MBeanOperationInfo info]
304 | (-> info .getName keyword)) (operations n))))
305 |
306 | (defn invoke-signature
307 | "Invoke an operation an an MBean. You must also supply
308 | the signature of the operation. This is useful in cases
309 | where the operation is overloaded. Otherwise you should
310 | use the 'invoke' operation which will determine the
311 | signature for you.
312 |
313 | The signature parameter is a sequence of strings that
314 | describes the method parameter types in order."
315 | [n op signature & args]
316 | (if ( seq args)
317 | (.invoke *connection* (as-object-name n) (name op)
318 | (into-array Object args)
319 | (into-array String signature))
320 | (.invoke *connection* (as-object-name n) (name op)
321 | nil nil)))
322 |
323 | (defn invoke
324 | "Invoke an operation an an MBean. See also: invoke-signature"
325 | [n op & args]
326 | (apply invoke-signature n op (op-param-types n op) args))
327 |
328 | (defn mbean
329 | "Like clojure.core/bean, but for JMX beans. Returns a read-only map of
330 | a JMX bean's attributes. If an attribute it not supported, value is
331 | set to the exception thrown."
332 | [n]
333 | (into {} (map (fn [attr-name] [(keyword attr-name) (read-supported n attr-name)])
334 | (attribute-names n))))
335 |
336 | (deftype Bean [state-ref]
337 | DynamicMBean
338 | (getMBeanInfo [_]
339 | (MBeanInfo. (.. _ getClass getName) ; class name
340 | "Clojure Dynamic MBean" ; description
341 | (map->attribute-infos @state-ref) ; attributes
342 | nil ; constructors
343 | nil ; operations
344 | nil))
345 | (getAttribute [_ attr]
346 | (@state-ref (keyword attr)))
347 | (getAttributes [_ attrs]
348 | (let [result (AttributeList.)]
349 | (doseq [attr attrs]
350 | (.add result (Attribute. attr (.getAttribute _ attr))))
351 | result))
352 | (setAttribute [_ attr]
353 | (let [attr-name (.getName attr)
354 | attr-value (.getValue attr)
355 | state-update {(keyword attr-name) attr-value}]
356 | (condp = (type state-ref)
357 | clojure.lang.Agent
358 | (await (send state-ref (fn [state state-update] (merge state state-update)) state-update))
359 |
360 | clojure.lang.Atom
361 | (swap! state-ref merge state-update)
362 |
363 | clojure.lang.Ref
364 | (dosync
365 | (ref-set state-ref
366 | (merge @state-ref state-update))))))
367 | (setAttributes [_ attrs]
368 | (let [attr-names (map (fn [^Attribute attr]
369 | (.setAttribute _ attr)
370 | (.getName attr))
371 | attrs)]
372 | (.getAttributes _ (into-array attr-names)))))
373 |
374 |
375 | (defn create-bean
376 | "Expose a reference as a JMX bean. state-ref should be a Clojure
377 | reference (ref, atom, agent) containing a map.
378 |
379 | Using an agent for the state-ref is not recommended when the bean may
380 | be modified with the setAttribute(s) methods. The setAttribute(s) methods
381 | will block on the agent to complete all submitted actions (via await)."
382 | [state-ref]
383 | (Bean. state-ref))
384 |
--------------------------------------------------------------------------------