public
Description: a JMX library for JRuby
Homepage: http://github.com/jmesnil/jmx4r/
Clone URL: git://github.com/jmesnil/jmx4r.git
jmx4r / lib / jmx4r.rb
b466dce4 » jmesnil 2008-04-10 initial commit 1 # Copyright 2007 Jeff Mesnil (http://jmesnil.net)
2 require 'java'
3
4 class String
5 # Transform a CamelCase String to a snake_case String.
6 #--
7 # Code has been taken from ActiveRecord
8 def snake_case
9 self.to_s.gsub(/::/, '/').
10 gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
11 gsub(/([a-z\d])([A-Z])/,'\1_\2').
12 tr("-", "_").
13 downcase
14 end
15 end
16
17 module JMX
515f1a9f » jmesnil 2008-12-03 added DynamicMBean to creat... 18 require 'dynamic_mbean'
b466dce4 » jmesnil 2008-04-10 initial commit 19 require 'open_data_helper'
c33c2f05 » jmesnil 2008-08-01 added helper method on Obje... 20 require 'objectname_helper'
383d9b45 » sat13f 2009-08-03 refactored 21 require 'jdk_helper'
b466dce4 » jmesnil 2008-04-10 initial commit 22 require 'jruby'
23
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 24 class MBeanServerConnectionProxy
25 attr_reader :connector
26
27 # Adds a connector attribute to Java's native MBeanServerConnection class.
28 #
29 # The connector attribute can be used to manage the connection (e.g, to close it).
30 # Why this isn't included in the native MBeanServerConnection class is beyond me.
31 #
32 # connector:: JMXConnector instance as returned by JMXConnectorFactory.connect.
33 def initialize(connector)
34 @connector = connector
35 @connection = connector.getMBeanServerConnection
36 end
37
38 # Close the connection (an unfortunate omission from the MBeanServerConnection class, imho)
39 def close
40 @connector.close
41 end
42
43 # Forward all other method messages to the underlying MBeanServerConnection instance.
44 def method_missing(method, *args, &block)
45 @connection.send method, *args, &block
46 end
47 end
48
b466dce4 » jmesnil 2008-04-10 initial commit 49 class MBean
50 include_class 'java.util.HashMap'
d5b89227 » mnadel 2009-02-12 weblogic support 51 include_class 'javax.naming.Context'
b466dce4 » jmesnil 2008-04-10 initial commit 52 include_class 'javax.management.Attribute'
53 include_class 'javax.management.ObjectName'
54 include_class 'javax.management.remote.JMXConnector'
55 include_class 'javax.management.remote.JMXConnectorFactory'
56 include_class 'javax.management.remote.JMXServiceURL'
57 JThread = java.lang.Thread
58
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 59 attr_reader :object_name, :operations, :attributes, :connection
b466dce4 » jmesnil 2008-04-10 initial commit 60
826d0ccf » jmesnil 2009-07-19 refactored attribute get/se... 61 def metaclass; class << self; self; end; end
62 def meta_def name, &blk
63 metaclass.instance_eval do
64 define_method name, &blk
65 end
66 end
67
b466dce4 » jmesnil 2008-04-10 initial commit 68 # Creates a new MBean.
69 #
70 # object_name:: a string corresponding to a valid ObjectName
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 71 # connection:: a connection to a MBean server. If none is passed,
b466dce4 » jmesnil 2008-04-10 initial commit 72 # use the global connection created by
73 # MBean.establish_connection
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 74 def initialize(object_name, connection=nil)
75 @connection = connection || @@connection
b466dce4 » jmesnil 2008-04-10 initial commit 76 @object_name = object_name
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 77 info = @connection.getMBeanInfo @object_name
b466dce4 » jmesnil 2008-04-10 initial commit 78 @attributes = Hash.new
79 info.attributes.each do | mbean_attr |
80 @attributes[mbean_attr.name.snake_case] = mbean_attr.name
81 end
82 @operations = Hash.new
83 info.operations.each do |mbean_op|
84 param_types = mbean_op.signature.map {|param| param.type}
85 @operations[mbean_op.name.snake_case] = [mbean_op.name, param_types]
86 end
87 end
88
89 def method_missing(method, *args, &block) #:nodoc:
8f777e13 » danger 2009-10-20 CamelCase and snake_case co... 90 method_in_snake_case = method.to_s.snake_case # this way Java/JRuby styles are compatible
91
92 if @operations.keys.include?(method_in_snake_case)
93 op_name, param_types = @operations[method_in_snake_case]
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 94 @connection.invoke @object_name,
8f777e13 » danger 2009-10-20 CamelCase and snake_case co... 95 op_name,
826d0ccf » jmesnil 2009-07-19 refactored attribute get/se... 96 args.to_java(:Object),
97 param_types.to_java(:String)
b466dce4 » jmesnil 2008-04-10 initial commit 98 else
99 super
100 end
101 end
102
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 103 @@connection = nil
b466dce4 » jmesnil 2008-04-10 initial commit 104
105 # establish a connection to a remote MBean server which will
106 # be used by all subsequent MBeans.
107 #
108 # See MBean.create_connection for a list of the keys that are
109 # accepted in arguments.
110 #
111 # Examples
112 #
113 # JMX::MBean.establish_connection :port => "node23", :port => 1090
114 # JMX::MBean.establish_connection :port => "node23", :username => "jeff", :password => "secret"
478de5bc » sat13f 2009-08-02 added local JVM connection ... 115 # JMX::MBean.establish_connection :command => /jconsole/i
b466dce4 » jmesnil 2008-04-10 initial commit 116 def self.establish_connection(args={})
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 117 @@connection ||= create_connection args
b466dce4 » jmesnil 2008-04-10 initial commit 118 end
119
120 def self.remove_connection(args={})
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 121 if @@connection
122 @@connection.close rescue nil
123 end
124 @@connection = nil
b466dce4 » jmesnil 2008-04-10 initial commit 125 end
126
127 def self.connection(args={})
128 if args.has_key? :host or args.has_key? :port
129 return create_connection(args)
130 else
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 131 @@connection ||= MBean.establish_connection(args)
b466dce4 » jmesnil 2008-04-10 initial commit 132 end
133 end
134
135 # Create a connection to a remote MBean server.
136 #
7a48555e » jmesnil 2009-02-12 reformatted JMX::create_con... 137 # The args accepts the following keys:
b466dce4 » jmesnil 2008-04-10 initial commit 138 #
7a48555e » jmesnil 2009-02-12 reformatted JMX::create_con... 139 # [:host] the host of the MBean server (defaults to "localhost")
140 #
141 # [:port] the port of the MBean server (defaults to 3000)
142 #
143 # [:url] the url of the MBean server.
144 # No default.
145 # if the url is specified, the host & port parameters are
146 # not taken into account
147 #
478de5bc » sat13f 2009-08-02 added local JVM connection ... 148 # [:command] the pattern matches the command line of the local
383d9b45 » sat13f 2009-08-03 refactored 149 # JVM process including the MBean server.
150 # (command lines are listed on the connection dialog
092aed8e » jmesnil 2009-10-22 fixed rdoc format 151 # in JConsole).
478de5bc » sat13f 2009-08-02 added local JVM connection ... 152 # No default.
153 # this feature needs a JDK (>=5) installed on the local
154 # system.
155 # if the command is specified, the host & port or the url
156 # parameters are not taken into account
157 #
7a48555e » jmesnil 2009-02-12 reformatted JMX::create_con... 158 # [:username] the name of the user (if the MBean server requires authentication).
159 # No default
160 #
161 # [:password] the password of the user (if the MBean server requires authentication).
162 # No default
163 #
164 # [:credentials] custom credentials (if the MBean server requires authentication).
165 # No default. It has precedence over :username and :password (i.e. if
166 # :credentials is specified, :username & :password are ignored)
167 #
168 # [:provider_package] use to fill the JMXConnectorFactory::PROTOCOL_PROVIDER_PACKAGES.
169 # No default
b466dce4 » jmesnil 2008-04-10 initial commit 170 #
171 def self.create_connection(args={})
172 host= args[:host] || "localhost"
173 port = args[:port] || 3000
174 username = args[:username]
175 password = args[:password]
176 credentials = args[:credentials]
d5b89227 » mnadel 2009-02-12 weblogic support 177 provider_package = args[:provider_package]
b466dce4 » jmesnil 2008-04-10 initial commit 178
478de5bc » sat13f 2009-08-02 added local JVM connection ... 179 if args[:command]
180 url = JDKHelper.find_local_url(args[:command]) or
181 raise "no locally attacheable VMs"
182 else
183 # host & port are not taken into account if url is set (see issue #7)
184 standard_url = "service:jmx:rmi:///jndi/rmi://#{host}:#{port}/jmxrmi"
185 url = args[:url] || standard_url
186 end
b466dce4 » jmesnil 2008-04-10 initial commit 187
188 unless credentials
189 if !username.nil? and username.length > 0
190 user_password_credentials = [username, password]
191 credentials = user_password_credentials.to_java(:String)
192 end
193 end
194
195 env = HashMap.new
196 env.put(JMXConnector::CREDENTIALS, credentials) if credentials
d5b89227 » mnadel 2009-02-12 weblogic support 197 # only fill the Context and JMXConnectorFactory properties if provider_package is set
198 if provider_package
199 env.put(Context::SECURITY_PRINCIPAL, username) if username
200 env.put(Context::SECURITY_CREDENTIALS, password) if password
201 env.put(JMXConnectorFactory::PROTOCOL_PROVIDER_PACKAGES, provider_package)
202 end
b466dce4 » jmesnil 2008-04-10 initial commit 203
204 # the context class loader is set to JRuby's classloader when
205 # creating the JMX Connection so that classes loaded using
206 # JRuby "require" (and not from its classpath) can also be
207 # accessed (see issue #6)
208 begin
209 context_class_loader = JThread.current_thread.context_class_loader
210 JThread.current_thread.context_class_loader = JRuby.runtime.getJRubyClassLoader
211
212 connector = JMXConnectorFactory::connect JMXServiceURL.new(url), env
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 213 MBeanServerConnectionProxy.new connector
b466dce4 » jmesnil 2008-04-10 initial commit 214 ensure
215 # ... and we reset the previous context class loader
216 JThread.current_thread.context_class_loader = context_class_loader
217 end
218 end
219
220 # Returns an array of MBeans corresponding to all the MBeans
221 # registered for the ObjectName passed in parameter (which may be
222 # a pattern).
223 #
224 # The args accepts the same keys than #create_connection and an
225 # additional one:
226 #
227 # [:connection] a MBean server connection (as returned by #create_connection)
228 # No default. It has precedence over :host and :port (i.e if
229 # :connection is specified, :host and :port are ignored)
230 #
231 def self.find_all_by_name(name, args={})
232 object_name = ObjectName.new(name)
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 233 connection = args[:connection] || MBean.connection(args)
234 object_names = connection.queryNames(object_name, nil)
826d0ccf » jmesnil 2009-07-19 refactored attribute get/se... 235 object_names.map { |on| create_mbean on, connection }
b466dce4 » jmesnil 2008-04-10 initial commit 236 end
237
238 # Same as #find_all_by_name but the ObjectName passed in parameter
239 # can not be a pattern.
240 # Only one single MBean is returned.
241 def self.find_by_name(name, args={})
0afd64f4 » claymation 2008-08-29 Add support for explicitly ... 242 connection = args[:connection] || MBean.connection(args)
826d0ccf » jmesnil 2009-07-19 refactored attribute get/se... 243 create_mbean ObjectName.new(name), connection
244 end
245
246 def self.create_mbean(object_name, connection)
247 info = connection.getMBeanInfo object_name
248 mbean = MBean.new object_name, connection
249 # define attribute accessor methods for the mbean
250 info.attributes.each do |mbean_attr|
251 mbean.meta_def mbean_attr.name.snake_case do
252 connection.getAttribute object_name, mbean_attr.name
253 end
254 if mbean_attr.isWritable
255 mbean.meta_def "#{mbean_attr.name.snake_case}=" do |value|
256 attribute = Attribute.new mbean_attr.name, value
257 connection.setAttribute object_name, attribute
258 end
259 end
260 end
261 mbean
b466dce4 » jmesnil 2008-04-10 initial commit 262 end
f209b8ee » jmesnil 2008-12-03 added JMX::MBean.pretty_pri... 263
264 def self.pretty_print (object_name, args={})
265 connection = args[:connection] || MBean.connection(args)
266 info = connection.getMBeanInfo ObjectName.new(object_name)
267 puts "object_name: #{object_name}"
268 puts "class: #{info.class_name}"
269 puts "description: #{info.description}"
270 puts "operations:"
271 info.operations.each do | op |
272 puts " #{op.name}"
273 op.signature.each do | param |
274 puts " #{param.name} (#{param.type} #{param.description})"
275 end
276 puts " ----"
277 puts " description: #{op.description}"
278 puts " return_type: #{op.return_type}"
279 puts " impact: #{op.impact}"
280 end
281 puts "attributes:"
282 info.attributes.each do | attr |
283 puts " #{attr.name}"
284 puts " description: #{attr.description}"
285 puts " type: #{attr.type}"
286 puts " readable: #{attr.readable}"
287 puts " writable: #{attr.writable}"
288 puts " is: #{attr.is}"
289 end
290 end
b466dce4 » jmesnil 2008-04-10 initial commit 291 end
292 end