Class: Rubeus::ComponentLoader

Inherits:
Module
  • Object
show all
Includes:
Verboseable
Defined in:
lib/rubeus/component_loader.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Verboseable

#log_if_verbose, out, out=

Constructor Details

#initialize(java_package, &block) ⇒ ComponentLoader

Returns a new instance of ComponentLoader.



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/rubeus/component_loader.rb', line 26

def initialize(java_package, &block)
  self.verbose = Rubeus.verbose
  build_class_to_package_table(java_package)
  java_package = JavaUtilities.get_package_module_dot_format(java_package)
  class << java_package
    include Rubeus::JavaPackage
    include Verboseable
  end
  java_package.verbose = self.verbose
  super(&block)
end

Instance Attribute Details

#class_to_packageObject (readonly)

Returns the value of attribute class_to_package.



24
25
26
# File 'lib/rubeus/component_loader.rb', line 24

def class_to_package
  @class_to_package
end

#java_packageObject (readonly)

Returns the value of attribute java_package.



23
24
25
# File 'lib/rubeus/component_loader.rb', line 23

def java_package
  @java_package
end

#verboseObject

Returns the value of attribute verbose.



22
23
24
# File 'lib/rubeus/component_loader.rb', line 22

def verbose
  @verbose
end

Class Method Details

.class_names(*package_names) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/rubeus/component_loader.rb', line 6

def self.class_names(*package_names)
  patterns = Regexp.union(
    *package_names.map{|package_name|
      Regexp.new(package_name.gsub(/\./, "/"))})
  classlist = File.join(ENV_JAVA["java.home"], "lib", "classlist")
  classes = []
  open(classlist) do |f|
    f.each do |line|
      classes << line.gsub(/\//, '.').strip if patterns =~ line
    end
  end
  classes
end

Instance Method Details

#autoload(const_name, feature = nil) ⇒ Object



113
114
115
# File 'lib/rubeus/component_loader.rb', line 113

def autoload(const_name, feature = nil)
  autolodings[const_name.to_s] = feature ||"#{self.name}::#{java_class_name.to_s}".underscore
end

#autoload?(const_name) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/rubeus/component_loader.rb', line 117

def autoload?(const_name)
  autolodings[const_name.to_s]
end

#autolodingsObject



109
110
111
# File 'lib/rubeus/component_loader.rb', line 109

def autolodings
  @autolodings ||= {}
end

#build_class_to_package_table(java_package) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rubeus/component_loader.rb', line 38

def build_class_to_package_table(java_package)
  class_names = ::Rubeus::ComponentLoader.class_names(java_package)
  @class_to_package = {}
  class_names.each do |fqn|
    parts = fqn.split('.')
    class_name = parts.pop
    # インナークラスの拡張はその持ち主のクラスの責任とします。
    # JVM上でも同じタイミングでロードされるし。
    next if class_name.include?('$')
    package = parts.join('.')
    @class_to_package[class_name] = @class_to_package.key?(class_name) ?
    [@class_to_package[class_name], package] : package
  end
end

#const_missing(java_class_name) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/rubeus/component_loader.rb', line 83

def const_missing(java_class_name)
  if autoload?(java_class_name)
    log_if_verbose("autoloading... #{java_class_name.to_s}")
    feature = autolodings.delete(java_class_name.to_s)
    log_if_verbose("require(#{feature})") do
      require(feature)
    end
    return const_get(java_class_name)
  end
  package = @class_to_package[java_class_name.to_s]
  raise NameError, java_class_name unless package
  if package.is_a?(Array)
    raise NameError, "cannot specified package name for #{java_class_name}: #{package.join(', ')}"
  end
  java_fqn = package.empty? ? java_class_name.to_s : "#{package}.#{java_class_name.to_s}"
  extension = Rubeus::Extensions.apply_for(java_fqn)
  result = log_if_verbose("instance_eval(#{java_fqn})") do
    instance_eval(java_fqn)
  end
  self.const_set(java_class_name, result)
  result
rescue
  log_if_verbose($!)
  super
end

#depend_on(*java_class_names) ⇒ Object



121
122
123
# File 'lib/rubeus/component_loader.rb', line 121

def depend_on(*java_class_names)
  java_class_names.each{|java_class_name| self.const_get(java_class_name)}
end

#extend_with(mod = Object) ⇒ Object



79
80
81
# File 'lib/rubeus/component_loader.rb', line 79

def extend_with(mod = Object)
  mod.send(:extend, self)
end

#extended(object) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rubeus/component_loader.rb', line 57

def extended(object)
  class_name_for_method = self.name.underscore.gsub('/', '_')
  const_missing_with = "const_missing_with_#{class_name_for_method}"
  const_missing_without = "const_missing_without_#{class_name_for_method}"
  return if object.singleton_methods.include?(const_missing_with)
  loader_name = "@loader_#{class_name_for_method}".to_sym
  mod = Module.new
  mod.send(:define_method, const_missing_with) do |const_name|
    begin
      instance_variable_get(loader_name).const_get(const_name)
    rescue
      send(const_missing_without, const_name)
    end
  end
  object.extend(mod)
  object.instance_variable_set(loader_name, self)
  object.instance_eval(<<-"EOS")
    alias :#{const_missing_without} :const_missing
    alias :const_missing :#{const_missing_with}
  EOS
end

#included(mod) ⇒ Object



53
54
55
# File 'lib/rubeus/component_loader.rb', line 53

def included(mod)
  mod.extend(self)
end