Skip to content

Commit

Permalink
DynamicMBean support for attributes now uses reflective calls instead…
Browse files Browse the repository at this point in the history
… of evals
  • Loading branch information
enebo committed Nov 24, 2009
1 parent 172c12b commit 732aca7
Showing 1 changed file with 57 additions and 70 deletions.
127 changes: 57 additions & 70 deletions lib/jmx/dynamic_mbean.rb
Expand Up @@ -15,18 +15,21 @@ module JavaTypeAware
:float => ['java.lang.Float', lambda {|param| param.to_f}],
:map => ['java.util.Map', lambda {|param| param}],
:set => ['java.util.Set', lambda {|param| param}],
:string => ['java.lang.String', lambda {|param| "'#{param.to_s}'"}],
:string => ['java.lang.String', lambda {|param| param.to_s}],
:void => ['java.lang.Void', lambda {|param| nil}]
}

def to_java_type(type_name)
SIMPLE_TYPES[type_name][0] || type_name
end

#TODO: I'm not sure this is strictly needed, but funky things can happen if you
# are expecting your attributes (from the ruby side) to be ruby types and they are java types.
def to_ruby(type_name)
SIMPLE_TYPES[type_name][1] || lambda {|param| param}
end

module_function :to_java_type, :to_ruby
end

class Parameter
Expand Down Expand Up @@ -93,17 +96,16 @@ def to_jmx
# like: user_name= and username. So in your ruby code you can treat the attributes
# as "regular" ruby accessors
class RubyDynamicMBean
java_import javax.management.AttributeList
java_import javax.management.MBeanOperationInfo
java_import javax.management.MBeanAttributeInfo
java_import javax.management.DynamicMBean
java_import javax.management.MBeanInfo
include JMX::JavaTypeAware

#NOTE this will not be needed when JRuby-3164 is fixed.
def self.inherited(cls)
cls.send(:include, DynamicMBean)
cls.send(:include, javax.management.DynamicMBean)
end

# TODO: preserve any original method_added?
# TODO: Error handling here when it all goes wrong?
def self.method_added(name) #:nodoc:
Expand All @@ -121,67 +123,53 @@ def self.operations #:nodoc:
Thread.current[:ops] ||= []
end

# the <tt>rw_attribute</tt> method is used to declare a JMX read write attribute.
# see the +JavaSimpleTypes+ module for more information about acceptable types
# usage:
# rw_attribute :attribute_name, :string, "Description displayed in a JMX console"
#--methods used to create an attribute. They are modeled on the attrib_accessor
# patterns of creating getters and setters in ruby
#++
def self.rw_attribute(name, type, description)
attributes << JMX::Attribute.new(name, type, description, true, true).to_jmx
attr_accessor name
#create a "java" oriented accessor method
define_method("jmx_get_#{name.to_s.downcase}") do
begin
#attempt conversion
java_type = to_java_type(type)
value = eval "#{java_type}.new(@#{name.to_s})"
rescue
#otherwise turn it into a java Object type for now.
value = eval "Java.ruby_to_java(@#{name.to_s})"
end
attribute = javax.management.Attribute.new(name.to_s, value)
def self.define_getter(name, type)
# FIXME: Our to_java_type needs to do something saner
java_type = begin; to_java_type(type); rescue; nil; end
value_proc = java_type ? proc { |value| java_type.new value } : proc { |value| Java.ruby_to_java value }

define_method("jmx_get_#{name.downcase}") do
javax.management.Attribute.new name, value_proc.call(instance_variable_get('@' + name))
end
end

def self.define_setter(name, type)
value_converter = JMX::JavaTypeAware.to_ruby(type)

define_method("jmx_set_#{name.to_s.downcase}") do |value|
blck = to_ruby(type)
eval "@#{name.to_s} = #{blck.call(value)}"
define_method("jmx_set_#{name.downcase}") do |value|
instance_variable_set '@' + name, value_converter.call(value)
end
end

# the <tt>r_attribute</tt> method is used to declare a JMX read only attribute.
# see the +JavaSimpleTypes+ module for more information about acceptable types
# usage:
# r_attribute :attribute_name, :string, "Description displayed in a JMX console"
# the <tt>rw_attribute</tt> method is used to declare a JMX read write attribute. See the +JavaSimpleTypes+
# module for more information about acceptable types usage:
# rw_attribute :attribute_name, :string, "Description displayed in a JMX console"
def self.rw_attribute(name, type, description)
name = name.to_s
attributes << JMX::Attribute.new(name, type, description, true, true).to_jmx
attr_accessor name
define_getter name, type
define_setter name, type
end

# the <tt>r_attribute</tt> method is used to declare a JMX read only attribute. See the +JavaSimpleTypes+
# module for more information about acceptable types usage:
# r_attribute :attribute_name, :string, "Description displayed in a JMX console"
def self.r_attribute(name, type, description)
name = name.to_s
attributes << JMX::Attribute.new(name, type, description, true, false).to_jmx
attr_reader name
#create a "java" oriented accessor method
define_method("jmx_get_#{name.to_s.downcase}") do
begin
#attempt conversion
java_type = to_java_type(type)
value = eval "#{java_type}.new(@#{name.to_s})"
rescue
#otherwise turn it into a java Object type for now.
value = eval "Java.ruby_to_java(@#{name.to_s})"
end
attribute = javax.management.Attribute.new(name.to_s, value)
end
define_getter name, type
end

# the <tt>w_attribute</tt> method is used to declare a JMX write only attribute.
# see the +JavaSimpleTypes+ module for more information about acceptable types
# usage:
# w_attribute :attribute_name, :string, "Description displayed in a JMX console"
# the <tt>w_attribute</tt> method is used to declare a JMX write only attribute. See the +JavaSimpleTypes+
# module for more information about acceptable types usage:
# w_attribute :attribute_name, :string, "Description displayed in a JMX console"
def self.w_attribute(name, type, description)
name = name.to_s
attributes << JMX::Attribute.new(name, type, description, false, true).to_jmx
attr_writer name
define_method("jmx_set_#{name.to_s.downcase}") do |value|
blck = to_ruby(type)
eval "@#{name.to_s} = #{blck.call(value)}"
end
define_setter name, type
end

# Use the operation method to declare the start of an operation
Expand All @@ -193,7 +181,6 @@ def self.w_attribute(name, type, description)
# Last operation wins if more than one
#++
def self.operation(description)

# Wait to error check until method_added so we can know method name
Thread.current[:op] = JMX::Operation.new description
end
Expand All @@ -218,41 +205,41 @@ def self.returns(type)
Thread.current[:op].return_type = type
end

# when creating a dynamic MBean we need to provide it with a
# name and a description.
# when creating a dynamic MBean we need to provide it with a name and a description.
def initialize(name, description)
operations = self.class.operations.to_java(MBeanOperationInfo)
attributes = self.class.attributes.to_java(MBeanAttributeInfo)
operations = self.class.operations.to_java MBeanOperationInfo
attributes = self.class.attributes.to_java MBeanAttributeInfo
@info = MBeanInfo.new name, description, attributes, nil, operations, nil
end

# Retrieve the value of the requested attribute (where attribute is a
# javax.management.Attribute class)
# Retrieve the value of the requested attribute (where attribute is a javax.management.Attribute class)
def getAttribute(attribute)
send("jmx_get_"+attribute.downcase)
__send__("jmx_get_" + attribute.downcase)
end

def getAttributes(attributes)
attrs = javax.management.AttributeList.new
attributes.each { |attribute| attrs.add(getAttribute(attribute)) }
attrs
attributes.inject(AttributeList.new) { |attrs, attribute| attrs.add(getAttribute(attribute)); attrs }
end

def getMBeanInfo; @info; end
def getMBeanInfo
@info
end

def invoke(actionName, params=nil, signature=nil)
send(actionName, *params)
__send__(actionName, *params)
end

def setAttribute(attribute)
send("jmx_set_#{attribute.name.downcase}", attribute.value)
__send__("jmx_set_#{attribute.name.downcase}", attribute.value)
end

def setAttributes(attributes)
attributes.each { |attribute| setAttribute attribute}
end

def to_s; toString; end
def inspect; toString; end
def toString; "#@info.class_name: #@info.description"; end
def toString
"#@info.class_name: #@info.description"
end
alias_method :to_s, :toString
alias_method :inspect, :toString
end

0 comments on commit 732aca7

Please sign in to comment.