jmx 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Thomas E Enebo <enebo@acm.org>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,13 @@
1
+ Manifest.txt
2
+ Rakefile
3
+ README.txt
4
+ LICENSE.txt
5
+ lib/jmx
6
+ lib/jmx/dynamic_mbean.rb
7
+ lib/jmx/server.rb
8
+ lib/jmx/version.rb
9
+ lib/jmx.rb
10
+ lib/rmi.rb
11
+ samples/memory.rb
12
+ test/jmx_client_test.rb
13
+ test/jmx_server_test.rb
data/README.txt ADDED
@@ -0,0 +1,29 @@
1
+ = JMX
2
+
3
+ == DESCRIPTION:
4
+
5
+ JMX is a library which allows you to access JMX MBeans as a client or create
6
+ your own MBeans as a Ruby class.
7
+
8
+ http://jruby-extras.rubyforge.org/jmx/
9
+
10
+ == FEATURES/PROBLEMS:
11
+
12
+ * Use '-J-Dcom.sun.management.jmxremote' to make jruby process accessible from a jruby command-line
13
+
14
+ == SYNOPSIS:
15
+
16
+ require 'jmx'
17
+
18
+ client = JMX.simple_connect(:port => 9999)
19
+
20
+ memory = client["java.lang:type=Memory"]
21
+ puts memory.attributes
22
+
23
+ == REQUIREMENTS:
24
+
25
+ * JRuby
26
+
27
+ == INSTALL:
28
+
29
+ * jruby -S gem install jmx
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ MANIFEST = FileList["Manifest.txt", "Rakefile", "README.txt", "LICENSE.txt", "lib/**/*", "samples/*","test/**/*"]
2
+
3
+ file "Manifest.txt" => :manifest
4
+ task :manifest do
5
+ File.open("Manifest.txt", "w") {|f| MANIFEST.each {|n| f << "#{n}\n"} }
6
+ end
7
+ Rake::Task['manifest'].invoke # Always regen manifest, so Hoe has up-to-date list of files
8
+
9
+ $LOAD_PATH << 'lib'
10
+ require 'jmx/version'
11
+ begin
12
+ require 'hoe'
13
+ Hoe.new("jmx", JMX::VERSION) do |p|
14
+ p.rubyforge_name = "jruby-extras"
15
+ p.url = "http://jruby-extras.rubyforge.org/jmx"
16
+ p.author = "Thomas Enebo"
17
+ p.email = "enebo@acm.org"
18
+ p.summary = "Package for interacting/creating Java Management Extensions"
19
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
20
+ p.description = "Install this gem and require 'jmx' to load the library."
21
+ end.spec.dependencies.delete_if { |dep| dep.name == "hoe" }
22
+ rescue LoadError
23
+ puts "You need Hoe installed to be able to package this gem"
24
+ rescue => e
25
+ p e.backtrace
26
+ puts "ignoring error while loading hoe: #{e.to_s}"
27
+ end
data/lib/jmx.rb ADDED
@@ -0,0 +1,210 @@
1
+ include Java
2
+
3
+ require 'rmi'
4
+ require 'jmx/dynamic_mbean'
5
+ require 'jmx/server'
6
+
7
+ import java.util.ArrayList
8
+ import javax.management.Attribute
9
+ import javax.management.DynamicMBean
10
+ import javax.management.MBeanInfo
11
+ import javax.management.ObjectName
12
+
13
+ class ObjectName
14
+ def [](key)
15
+ get_key_property(key.to_s)
16
+ end
17
+
18
+ def info(server)
19
+ server.getMBeanInfo(self)
20
+ end
21
+ end
22
+
23
+ module javax::management::openmbean::CompositeData
24
+ include Enumerable
25
+
26
+ def [](key)
27
+ get(key.to_s)
28
+ end
29
+
30
+ def method_missing(name, *args)
31
+ self[name]
32
+ end
33
+
34
+ def each
35
+ get_composite_type.key_set.each { |key| yield key }
36
+ end
37
+
38
+ def each_pair
39
+ get_composite_type.key_set.each { |key| yield key, get(key) }
40
+ end
41
+ end
42
+
43
+ module JMX
44
+ ##
45
+ # Connect to a MBeanServer
46
+ # opts can contain several values
47
+ # :host - The hostname where the server resides (def: localhost)
48
+ # :port - Which port the server resides at (def: 8686)
49
+ # :url_path - path part of JMXServerURL (def: /jmxrmi)
50
+ # :user - User to connect as (optional)
51
+ # :password - Password for user (optional)
52
+ def self.connect(opts = {})
53
+ host = opts[:host] || 'localhost'
54
+ port = opts[:port] || 8686
55
+ url_path = opts[:url_path] || "/jmxrmi"
56
+ url = "service:jmx:rmi:///jndi/rmi://#{host}:#{port}#{url_path}"
57
+
58
+ if opts[:user]
59
+ JMX::MBeanServer.new url, opts[:user], opts[:password]
60
+ else
61
+ JMX::MBeanServer.new url
62
+ end
63
+ end
64
+
65
+ ##
66
+ # sad little simple server setup so you can connect up to it.
67
+ #
68
+ def self.simple_server(opts = {})
69
+ port = opts[:port] || 8686
70
+ url_path = opts[:url_path] || "/jmxrmi"
71
+ url = "service:jmx:rmi:///jndi/rmi://localhost:#{port}#{url_path}"
72
+ $registry = RMIRegistry.new port
73
+ @connector = JMX::MBeanServerConnector.new(url, JMX::MBeanServer.new).start
74
+ end
75
+
76
+ # Holder for beans created from retrieval (namespace protection [tm]).
77
+ # This also gives MBeans nicer names when inspected
78
+ module MBeans
79
+ ##
80
+ # Create modules in this namespace for each package in the Java fully
81
+ # qualified name and return the deepest module along with the Java class
82
+ # name back to the caller.
83
+ def self.parent_for(java_class_fqn)
84
+ java_class_fqn.split(".").inject(MBeans) do |parent, segment|
85
+ # Note: We are boned if java class name is lower cased
86
+ return [parent, segment] if segment =~ /^[A-Z]/
87
+
88
+ segment.capitalize!
89
+ unless parent.const_defined? segment
90
+ parent.const_set segment, Module.new
91
+ else
92
+ parent.const_get segment
93
+ end
94
+ end
95
+
96
+ end
97
+ end
98
+
99
+ # Create a Ruby proxy based on the MBean represented by the object_name
100
+ class MBeanProxy
101
+ # Generate a friendly Ruby proxy for the MBean represented by object_name
102
+ def self.generate(server, object_name)
103
+ parent, class_name = MBeans.parent_for object_name.info(server).class_name
104
+
105
+ if parent.const_defined? class_name
106
+ proxy = parent.const_get(class_name)
107
+ else
108
+ proxy = Class.new MBeanProxy
109
+ parent.const_set class_name, proxy
110
+ end
111
+
112
+ proxy.new(server, object_name)
113
+ end
114
+
115
+ def initialize(server, object_name)
116
+ @server, @object_name = server, object_name
117
+ @info = @server.getMBeanInfo(@object_name)
118
+
119
+ define_attributes
120
+ define_operations
121
+ end
122
+
123
+ def attributes
124
+ @attributes ||= @info.attributes.inject([]) { |s,attr| s << attr.name }
125
+ end
126
+
127
+ def operations
128
+ @operations ||= @info.operations.inject([]) { |s,op| s << op.name }
129
+ end
130
+
131
+ # Get MBean attribute specified by name
132
+ def [](name)
133
+ @server.getAttribute @object_name, name.to_s
134
+ end
135
+
136
+ # Set MBean attribute specified by name to value
137
+ def []=(name, value)
138
+ @server.setAttribute @object_name, Attribute.new(name.to_s, value)
139
+ end
140
+
141
+ def add_notification_listener(filter=nil, handback=nil, &listener)
142
+ @server.addNotificationListener @object_name, listener, filter, handback
143
+ end
144
+
145
+ def remove_notification_listener(listener)
146
+ @server.removeNotificationListener @object_name, listener
147
+ end
148
+
149
+ def method_missing(name, *args)
150
+ puts "Invoking: #{name}, #{args}"
151
+ java_args = java_args(args)
152
+ @server.invoke @object_name, name.to_s, java_args, java_types(java_args)
153
+ end
154
+
155
+ private
156
+
157
+ # Define ruby friendly methods for attributes. For odd attribute names or names
158
+ # that you want to call with the actual attribute name you can call aref/aset
159
+ def define_attributes
160
+ @info.attributes.each do |attr|
161
+ rname = underscore(attr.name)
162
+ self.class.__send__(:define_method, rname) { self[attr.name] } if attr.readable?
163
+ self.class.__send__(:define_method, rname + "=") {|v| self[attr.name] = v } if attr.writable?
164
+ end
165
+ end
166
+
167
+ def define_operations
168
+ @info.operations.each do |op|
169
+ self.class.__send__(:define_method, op.name) do |*args|
170
+ jargs = java_args(op.signature, args)
171
+ @server.invoke @object_name, op.name, jargs, java_types(jargs)
172
+ end
173
+ end
174
+ end
175
+
176
+ # Given the signature and the parameters supplied do these signatures match.
177
+ # Repackage these parameters as Java objects in a primitive object array.
178
+ def java_args(signature, params)
179
+ return nil if params.nil?
180
+
181
+ i = 0
182
+ params.map do |param|
183
+ required_type = JavaClass.for_name(signature[i].get_type)
184
+ java_arg = Java.ruby_to_java(param)
185
+
186
+ if (param.kind_of? Array)
187
+ java_arg = param.inject(ArrayList.new) {|l, element| l << element }
188
+ end
189
+
190
+ arg_type = java_arg.java_class
191
+
192
+ raise TypeError.new("parameter #{signature[i].name} expected to be #{required_type}, but was #{arg_type}") if !required_type.assignable_from? arg_type
193
+ i = i + 1
194
+
195
+ java_arg
196
+ end.to_java(:object)
197
+ end
198
+
199
+ # Convert a collection of java objects to their Java class name equivalents
200
+ def java_types(params)
201
+ return nil if params.nil?
202
+
203
+ params.map {|e| params.java_class.name }.to_java(:string)
204
+ end
205
+
206
+ def underscore(string)
207
+ string.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,101 @@
1
+ module JMX
2
+ import javax.management.MBeanParameterInfo
3
+ import javax.management.MBeanOperationInfo
4
+ import javax.management.MBeanInfo
5
+
6
+ module JavaTypeAware
7
+ SIMPLE_TYPES = {
8
+ :int => 'java.lang.Integer',
9
+ :list => 'java.util.List',
10
+ :long => 'java.lang.Long',
11
+ :map => 'java.util.Map',
12
+ :set => 'java.util.Set',
13
+ :string => 'java.lang.String',
14
+ :void => 'java.lang.Void'
15
+ }
16
+
17
+ def to_java_type(type_name)
18
+ SIMPLE_TYPES[type_name] || type_name
19
+ end
20
+ end
21
+
22
+ class Parameter
23
+ include JavaTypeAware
24
+
25
+ def initialize(type, name, description)
26
+ @type, @name, @description = type, name, description
27
+ end
28
+
29
+ def to_jmx
30
+ MBeanParameterInfo.new @name.to_s, to_java_type(@type), @description
31
+ end
32
+ end
33
+
34
+ class Operation < Struct.new(:description, :parameters, :return_type, :name, :impact)
35
+ include JavaTypeAware
36
+
37
+ def initialize(description)
38
+ super
39
+ self.parameters, self.impact, self.description = [], MBeanOperationInfo::UNKNOWN, description
40
+ end
41
+
42
+ def to_jmx
43
+ java_parameters = parameters.map { |parameter| parameter.to_jmx }
44
+ MBeanOperationInfo.new name.to_s, description, java_parameters.to_java(javax.management.MBeanParameterInfo), to_java_type(return_type), impact
45
+ end
46
+ end
47
+ end
48
+
49
+ class RubyDynamicMBean
50
+ import javax.management.MBeanOperationInfo
51
+
52
+ # TODO: preserve any original method_added?
53
+ # TODO: Error handling here when it all goes wrong?
54
+ def self.method_added(name)
55
+ return if Thread.current[:op].nil?
56
+ Thread.current[:op].name = name
57
+ operations << Thread.current[:op].to_jmx
58
+ Thread.current[:op] = nil
59
+ end
60
+
61
+ def self.attributes
62
+ Thread.current[:attrs] ||= []
63
+ end
64
+
65
+ def self.operations
66
+ Thread.current[:ops] ||= []
67
+ end
68
+
69
+ # Last operation wins if more than one
70
+ def self.operation(description)
71
+ include DynamicMBean
72
+
73
+ # Wait to error check until method_added so we can know method name
74
+ Thread.current[:op] = JMX::Operation.new description
75
+ end
76
+
77
+ def self.parameter(type, name=nil, description=nil)
78
+ Thread.current[:op].parameters << JMX::Parameter.new(type, name, description)
79
+ end
80
+
81
+ def self.returns(type)
82
+ Thread.current[:op].return_type = type
83
+ end
84
+
85
+ def initialize(name, description)
86
+ operations = self.class.operations.to_java(MBeanOperationInfo)
87
+ @info = MBeanInfo.new name, description, nil, nil, operations, nil
88
+ end
89
+
90
+ def getAttribute(attribute); $stderr.puts "getAttribute"; end
91
+ def getAttributes(attributes); $stderr.puts "getAttributes"; end
92
+ def getMBeanInfo; @info; end
93
+ def invoke(actionName, params=nil, signature=nil)
94
+ send(actionName, *params)
95
+ end
96
+ def setAttribute(attribute); $stderr.puts "setAttribute"; end
97
+ def setAttributes(attributes); $stderr.puts "setAttributes"; end
98
+ def to_s; toString; end
99
+ def inspect; toString; end
100
+ def toString; "#@info.class_name: #@info.description"; end
101
+ end
data/lib/jmx/server.rb ADDED
@@ -0,0 +1,117 @@
1
+ module JMX
2
+ # Represents both MBeanServer and MBeanServerConnection
3
+ class MBeanServer
4
+ import javax.management.Attribute
5
+ import javax.management.MBeanServerFactory
6
+ import javax.management.remote.JMXConnectorFactory
7
+ import javax.management.remote.JMXServiceURL
8
+
9
+ attr_accessor :server
10
+ @@classes = {}
11
+
12
+ def initialize(location=nil, username=nil, password=nil)
13
+ if (location)
14
+ env = username ?
15
+ {"jmx.remote.credentials" => [username, password].to_java(:string)} :
16
+ nil
17
+ url = JMXServiceURL.new location
18
+ @server = JMXConnectorFactory.connect(url, env).getMBeanServerConnection
19
+ else
20
+ @server = java.lang.management.ManagementFactory.getPlatformMBeanServer
21
+ #@server = MBeanServerFactory.createMBeanServer
22
+ end
23
+ end
24
+
25
+ def [](object_name)
26
+ name = make_object_name object_name
27
+
28
+ unless @server.isRegistered(name)
29
+ raise NoSuchBeanError.new("No name: #{object_name}")
30
+ end
31
+
32
+ #### TODO: Why?
33
+ @server.getObjectInstance name
34
+ MBeanProxy.generate(@server, name)
35
+ end
36
+
37
+ def []=(class_name, object_name)
38
+ name = make_object_name object_name
39
+
40
+ @server.createMBean class_name, name, nil, nil
41
+
42
+ MBeanProxy.generate(@server, name)
43
+ end
44
+
45
+ def default_domain
46
+ @server.getDefaultDomain
47
+ end
48
+
49
+ def domains
50
+ @server.domains
51
+ end
52
+
53
+ def mbean_count
54
+ @server.getMBeanCount
55
+ end
56
+
57
+ def query_names(name=nil, query=nil)
58
+ object_name = name.nil? ? nil : make_object_name(name)
59
+
60
+ @server.query_names(object_name, query)
61
+ end
62
+
63
+ def register_mbean(object, object_name)
64
+ name = make_object_name object_name
65
+
66
+ @server.registerMBean(object, name)
67
+
68
+ MBeanProxy.generate(@server, name)
69
+ end
70
+
71
+ def self.find(agent_id=nil)
72
+ MBeanServerFactory.findMBeanServer(agent_id)
73
+ end
74
+
75
+ private
76
+
77
+ def make_object_name(object_name)
78
+ return object_name if object_name.kind_of? ObjectName
79
+
80
+ ObjectName.new object_name
81
+ rescue
82
+ raise ArgumentError.new("Invalid ObjectName #{$!.message}")
83
+ end
84
+ end
85
+
86
+ class NoSuchBeanError < RuntimeError
87
+ end
88
+
89
+ class MBeanServerConnector
90
+ import javax.management.remote.JMXServiceURL
91
+ import javax.management.remote.JMXConnectorServerFactory
92
+
93
+ def initialize(location, server)
94
+ @url = JMXServiceURL.new location
95
+ @server = JMXConnectorServerFactory.newJMXConnectorServer @url, nil, server.server
96
+
97
+ if block_given?
98
+ start
99
+ yield
100
+ stop
101
+ end
102
+ end
103
+
104
+ def active?
105
+ @server.isActive
106
+ end
107
+
108
+ def start
109
+ @server.start
110
+ self
111
+ end
112
+
113
+ def stop
114
+ @server.stop if active?
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,3 @@
1
+ module JMX
2
+ VERSION = "0.1"
3
+ end
data/lib/rmi.rb ADDED
@@ -0,0 +1,21 @@
1
+ include Java
2
+
3
+ import java.rmi.registry.LocateRegistry
4
+ import java.rmi.registry.Registry
5
+ import java.rmi.server.UnicastRemoteObject
6
+
7
+ class RMIRegistry
8
+ def initialize(port = Registry::REGISTRY_PORT)
9
+ start(port)
10
+ end
11
+
12
+ def start(port)
13
+ @registry = LocateRegistry.createRegistry port
14
+
15
+ end
16
+
17
+ def stop
18
+ UnicastRemoteObject.unexportObject @registry, true
19
+ end
20
+ end
21
+
data/samples/memory.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'jmx'
2
+
3
+ def in_mb(value)
4
+ format "%0.2f Mb" % (value.to_f / (1024 * 1024))
5
+ end
6
+
7
+ server = JMX.simple_server
8
+ client = JMX.connect
9
+ memory = client["java.lang:type=Memory"]
10
+
11
+ Thread.new do
12
+ puts "Enter 'gc' to garbage collect or anything else to quit"
13
+ while (command = gets.chomp)
14
+ break if command != "gc"
15
+ memory.gc
16
+ end
17
+
18
+ server.stop
19
+ exit 0
20
+ end
21
+
22
+ while (true)
23
+ heap = in_mb(memory.heap_memory_usage.used)
24
+ non_heap = in_mb(memory.non_heap_memory_usage.used)
25
+
26
+ puts "Heap: #{heap}, Non-Heap: #{non_heap}"
27
+ sleep(2)
28
+ end
29
+
@@ -0,0 +1,88 @@
1
+ # In order to run these tests you must be running GFv2
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
4
+
5
+ require 'test/unit'
6
+ require 'rmi'
7
+ require 'jmx'
8
+
9
+ PORT = 9999
10
+ $registry = RMIRegistry.new PORT
11
+
12
+ class JMXConnectorClientTest < Test::Unit::TestCase
13
+ URL = "service:jmx:rmi:///jndi/rmi://localhost:#{PORT}/jmxrmi"
14
+
15
+ def setup
16
+ @connector = JMX::MBeanServerConnector.new(URL, JMX::MBeanServer.new)
17
+ @connector.start
18
+ @client = JMX::connect(:port => PORT)
19
+ end
20
+
21
+ def teardown
22
+ @connector.stop
23
+ end
24
+
25
+ def test_invalid_mbean_name
26
+ assert_raises(ArgumentError) { @client["::::::"] }
27
+ end
28
+
29
+ def test_get_mbean
30
+ memory = @client["java.lang:type=Memory"]
31
+
32
+ assert_not_nil memory, "Could not acquire memory mbean"
33
+
34
+ # Attr form
35
+ heap = memory[:HeapMemoryUsage]
36
+ assert_not_nil heap
37
+ assert(heap[:used] > 0, "No heap used? Impossible!")
38
+
39
+ # underscored form
40
+ heap = memory.heap_memory_usage
41
+ assert_not_nil heap
42
+ assert(heap.used > 0, "No heap used? Impossible!")
43
+ end
44
+
45
+ def test_set_mbean
46
+ memory = @client["java.lang:type=Memory"]
47
+ original_verbose = memory.verbose
48
+ memory.verbose = !original_verbose
49
+ assert(memory.verbose != original_verbose, "Could not change verbose")
50
+
51
+ memory[:Verbose] = original_verbose
52
+ assert(memory[:Verbose] == original_verbose, "Could not change back verbose")
53
+ end
54
+
55
+ def test_attributes
56
+ memory = @client["java.lang:type=Memory"]
57
+ assert(memory.attributes.include?("HeapMemoryUsage"), "HeapMemoryUsage not found")
58
+ end
59
+
60
+ def test_operations
61
+ memory = @client["java.lang:type=Memory"]
62
+ assert(memory.operations.include?("gc"), "gc not found")
63
+ end
64
+
65
+
66
+ def test_simple_operation
67
+ memory = @client["java.lang:type=Memory"]
68
+
69
+ heap1 = memory[:HeapMemoryUsage][:used]
70
+ memory.gc
71
+ heap2 = memory[:HeapMemoryUsage][:used]
72
+
73
+ assert(heap1.to_i >= heap2.to_i, "GC did not collect")
74
+ end
75
+
76
+ def test_query_names
77
+ names = @client.query_names("java.lang:type=MemoryPool,*")
78
+ assert(names.size > 0, "No memory pools. Impossible!")
79
+
80
+ a_memory_pool_bean = @client[names.to_array[0]]
81
+ assert_not_nil a_memory_pool_bean, "Name must resolve to something"
82
+
83
+ usage = a_memory_pool_bean[:Usage]
84
+ assert_not_nil usage, "Memory pools have usage"
85
+
86
+ assert_not_nil usage[:used], "Some memory is used"
87
+ end
88
+ end
@@ -0,0 +1,71 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+
6
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
7
+
8
+ require 'test/unit'
9
+ require 'rmi'
10
+ require 'jmx'
11
+
12
+ class MyDynamicMBean < RubyDynamicMBean
13
+ operation "Doubles a value"
14
+ parameter :int, "a", "Value to double"
15
+ returns :int
16
+ def double(a)
17
+ a + a
18
+ end
19
+
20
+ operation "Doubles a string"
21
+ parameter :string, "a", "Value to double"
22
+ returns :string
23
+ def string_double(a)
24
+ a + a
25
+ end
26
+
27
+ operation "Give me foo"
28
+ returns :string
29
+ def foo
30
+ "foo"
31
+ end
32
+
33
+ operation "Concatentates a list"
34
+ parameter :list, "list", "List to concatenate"
35
+ returns :string
36
+ def concat(list)
37
+ list.inject("") { |memo, element| memo << element.to_s }
38
+ end
39
+ end
40
+
41
+ class JMXServerTest < Test::Unit::TestCase
42
+ PORT = 9999
43
+ URL = "service:jmx:rmi:///jndi/rmi://localhost:#{PORT}/jmxrmi"
44
+
45
+ def setup
46
+ @registry = RMIRegistry.new PORT
47
+ @server = JMX::MBeanServer.new
48
+ @connector = JMX::MBeanServerConnector.new(URL, @server)
49
+ @connector.start
50
+ @client = JMX::connect(:port => PORT)
51
+ end
52
+
53
+ def teardown
54
+ @connector.stop
55
+ @registry.stop
56
+ end
57
+
58
+ def test_ruby_mbean
59
+ dyna = MyDynamicMBean.new("domain.MySuperBean", "Heh")
60
+ domain = @server.default_domain
61
+ @server.register_mbean dyna, "#{domain}:type=MyDynamicMBean"
62
+
63
+ # Get bean from client connector connection
64
+ bean = @client["#{domain}:type=MyDynamicMBean"]
65
+ assert_equal("foo", bean.foo)
66
+ assert_equal(6, bean.double(3))
67
+ assert_raise(TypeError) { puts bean.double("HEH") }
68
+ assert_equal("hehheh", bean.string_double("heh"))
69
+ assert_equal("123", bean.concat([1,2,3]))
70
+ end
71
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jmx
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Enebo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-06 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Install this gem and require 'jmx' to load the library.
17
+ email: enebo@acm.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - Manifest.txt
24
+ - README.txt
25
+ - LICENSE.txt
26
+ files:
27
+ - Manifest.txt
28
+ - Rakefile
29
+ - README.txt
30
+ - LICENSE.txt
31
+ - lib/jmx
32
+ - lib/jmx/dynamic_mbean.rb
33
+ - lib/jmx/server.rb
34
+ - lib/jmx/version.rb
35
+ - lib/jmx.rb
36
+ - lib/rmi.rb
37
+ - samples/memory.rb
38
+ - test/jmx_client_test.rb
39
+ - test/jmx_server_test.rb
40
+ has_rdoc: true
41
+ homepage: http://jruby-extras.rubyforge.org/jmx
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --main
45
+ - README.txt
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project: jruby-extras
63
+ rubygems_version: 1.0.1
64
+ signing_key:
65
+ specification_version: 2
66
+ summary: Package for interacting/creating Java Management Extensions
67
+ test_files: []
68
+