RubyExt 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +846 -0
- data/lib/RubyExt/Cache.rb +101 -0
- data/lib/RubyExt/Cache.res/multiple_version_with_args.txt +12 -0
- data/lib/RubyExt/Cache.res/multiple_version_without_args.txt +11 -0
- data/lib/RubyExt/Cache.res/single_version_with_args.txt +11 -0
- data/lib/RubyExt/Cache.res/single_version_without_args.txt +10 -0
- data/lib/RubyExt/ClassLoader.rb +142 -0
- data/lib/RubyExt/Debug.rb +24 -0
- data/lib/RubyExt/ExtraBlankSlate.rb +14 -0
- data/lib/RubyExt/ImportAll.rb +9 -0
- data/lib/RubyExt/Localization/Module.rb +12 -0
- data/lib/RubyExt/Localization/Object.rb +19 -0
- data/lib/RubyExt/Localization/require.rb +3 -0
- data/lib/RubyExt/Localization.rb +28 -0
- data/lib/RubyExt/Log.config.sample +57 -0
- data/lib/RubyExt/Log.rb +59 -0
- data/lib/RubyExt/OpenConstructor.rb +51 -0
- data/lib/RubyExt/Path.rb +91 -0
- data/lib/RubyExt/Resource/file_system_provider.rb +244 -0
- data/lib/RubyExt/StateMashine.rb +176 -0
- data/lib/RubyExt/Synchronizer.rb +29 -0
- data/lib/RubyExt/array.rb +24 -0
- data/lib/RubyExt/assert.rb +111 -0
- data/lib/RubyExt/class.rb +0 -0
- data/lib/RubyExt/debug.rb +71 -0
- data/lib/RubyExt/false_class.rb +5 -0
- data/lib/RubyExt/file.rb +23 -0
- data/lib/RubyExt/ideas.txt +17 -0
- data/lib/RubyExt/kernel.rb +61 -0
- data/lib/RubyExt/module.rb +102 -0
- data/lib/RubyExt/nil_class.rb +5 -0
- data/lib/RubyExt/object.rb +7 -0
- data/lib/RubyExt/observable.rb +25 -0
- data/lib/RubyExt/require.rb +56 -0
- data/lib/RubyExt/require_base.rb +35 -0
- data/lib/RubyExt/resource.rb +198 -0
- data/lib/RubyExt/string.rb +21 -0
- data/lib/RubyExt/symbol.rb +21 -0
- data/lib/RubyExt/true_class +0 -0
- data/lib/RubyExt/true_class.rb +5 -0
- data/rakefile +49 -0
- data/spec/RubyExt/ForClassLoader/ClassA.rb +4 -0
- data/spec/RubyExt/ForClassLoader/LoadCount.rb +1 -0
- data/spec/RubyExt/ForClassLoader/ModuleA/ClassB.rb +3 -0
- data/spec/RubyExt/ForClassLoader/ModuleA/ClassInsideAnonymousClass.rb +3 -0
- data/spec/RubyExt/ForClassLoader/ModuleA/InfinityLoop.rb +3 -0
- data/spec/RubyExt/ForClassLoader/ModuleA/ModuleB/ClassC.rb +3 -0
- data/spec/RubyExt/ForClassLoader/ModuleA/SameName/SomeClass.rb +2 -0
- data/spec/RubyExt/ForClassLoader/ModuleA/SameName.rb +2 -0
- data/spec/RubyExt/ForClassLoader/Scope/ScopeA1.rb +3 -0
- data/spec/RubyExt/ForClassLoader/Scope/ScopeB1.rb +5 -0
- data/spec/RubyExt/ForKernel/Raise2.rb +5 -0
- data/spec/RubyExt/ForKernel/RaiseWithoutSelf.rb +9 -0
- data/spec/RubyExt/ForLocalization/NS/A.rb +3 -0
- data/spec/RubyExt/ForLocalization/NS/A.ru.localization.yaml +2 -0
- data/spec/RubyExt/ForLocalization/NS/B.rb +22 -0
- data/spec/RubyExt/ForLocalization/NS/B.ru.localization.yaml +3 -0
- data/spec/RubyExt/ForLocalization/NS.ru.localization.yaml +2 -0
- data/spec/RubyExt/ForModule/NS1/A.data +1 -0
- data/spec/RubyExt/ForModule/NS1/A.rb +1 -0
- data/spec/RubyExt/ForModule/NS1/A2.rb +1 -0
- data/spec/RubyExt/ForModule/NS1/B.rb +2 -0
- data/spec/RubyExt/ForModule/NS1/B2.rb +1 -0
- data/spec/RubyExt/ForModule/NS1.data +1 -0
- data/spec/RubyExt/ForModule/NS2/A.data +1 -0
- data/spec/RubyExt/ForModule/NS2/A.rb +3 -0
- data/spec/RubyExt/ForModule/NS2/B.rb +3 -0
- data/spec/RubyExt/ForModule/NS2/M.data +1 -0
- data/spec/RubyExt/ForModule/NS2/M.rb +3 -0
- data/spec/RubyExt/ForResource/ChangedClass.rb +1 -0
- data/spec/RubyExt/ForResource/ChangedClass.res/Text.txt +0 -0
- data/spec/RubyExt/ForResource/ChangedClass.txt +0 -0
- data/spec/RubyExt/ForResource/ProviderChaining/ProviderABaseDir/ChainTest.rb +3 -0
- data/spec/RubyExt/ForResource/ProviderChaining/ProviderABaseDir/ChainTest.resource +1 -0
- data/spec/RubyExt/ForResource/ProviderChaining/ProviderABaseDir/ClassExistOnlyInProviderA.rb +3 -0
- data/spec/RubyExt/ForResource/ProviderChaining/ProviderBBaseDir/ChainTest.rb +3 -0
- data/spec/RubyExt/ForResource/ProviderChaining/ProviderBBaseDir/ChainTest.resource +1 -0
- data/spec/RubyExt/ForResource/ResourceExtension.rb +1 -0
- data/spec/RubyExt/ForResource/ResourceExtension.res/Data.yaml +2 -0
- data/spec/RubyExt/ForResource/ResourceTest/Test.rb +1 -0
- data/spec/RubyExt/ForResource/ResourceTest/Test.res/Data.txt +1 -0
- data/spec/RubyExt/ForResource/ResourceTest/Test.res/txt +1 -0
- data/spec/array_spec.rb +27 -0
- data/spec/assert_spec.rb +18 -0
- data/spec/cache_spec.rb +95 -0
- data/spec/class_loader_spec.rb +94 -0
- data/spec/import_all_spec.rb +21 -0
- data/spec/kernel_spec.rb +38 -0
- data/spec/localization_spec.rb +49 -0
- data/spec/module_spec.rb +135 -0
- data/spec/object_spec.rb +8 -0
- data/spec/observable_spec.rb +44 -0
- data/spec/open_constructor_spec.rb +38 -0
- data/spec/path_spec.rb +169 -0
- data/spec/resource_spec.rb +135 -0
- data/spec/state_machine_spec.rb +201 -0
- data/spec/synchronizer_spec.rb +66 -0
- metadata +130 -10
- data/lib/RubyExt.rb +0 -1
- data/lib/hello_gem.rb +0 -5
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Cache
|
|
2
|
+
DISABLED = false
|
|
3
|
+
|
|
4
|
+
warn "CASHE DISABLED" if DISABLED
|
|
5
|
+
|
|
6
|
+
# It's not a good idea to mix Business Logic and Performance optimization,
|
|
7
|
+
# so i think these methods should be never used.
|
|
8
|
+
# def cached *methods
|
|
9
|
+
# Cache.cached self, *methods
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# def cached_with_params *methods
|
|
13
|
+
# Cache.cached_with_params self, *methods
|
|
14
|
+
# end
|
|
15
|
+
|
|
16
|
+
@versions, @alias_counter, @monitor = Hash.new{should! :be_never_called}, 0, Monitor.new
|
|
17
|
+
class << self
|
|
18
|
+
|
|
19
|
+
def alias_counter
|
|
20
|
+
@alias_counter += 1
|
|
21
|
+
return :"m#{@alias_counter}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def cached *arg
|
|
25
|
+
vnames, klass, methods = parse_and_check_arguments *arg
|
|
26
|
+
|
|
27
|
+
return if DISABLED
|
|
28
|
+
methods.each do |m|
|
|
29
|
+
als = (m.to_s =~ /^[_a-zA-Z0-9]+$/) ? m : RubyExt::Cache.alias_counter.to_sym
|
|
30
|
+
|
|
31
|
+
klass.class_eval{alias_method :"cached_#{als}", :"#{m}"}
|
|
32
|
+
unless vnames.is_a? Array
|
|
33
|
+
script = Cache["single_version_without_args.txt"].substitute binding
|
|
34
|
+
@versions[vnames] = 0 unless @versions.include? vnames
|
|
35
|
+
else
|
|
36
|
+
vnames_str = vnames.collect{|vname| "'#{vname}' => nil"}.join(', ')
|
|
37
|
+
script = Cache["multiple_version_without_args.txt"].substitute binding
|
|
38
|
+
vnames.each{|vname| @versions[vname] = 0 unless @versions.include? vname}
|
|
39
|
+
end
|
|
40
|
+
klass.class_eval script, __FILE__, __LINE__
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def cached_with_params *arg
|
|
45
|
+
vnames, klass, methods = parse_and_check_arguments *arg
|
|
46
|
+
|
|
47
|
+
return if DISABLED
|
|
48
|
+
methods.each do |m|
|
|
49
|
+
als = (m.to_s =~ /^[_a-zA-Z0-9]+$/) ? m : RubyExt::Cache.alias_counter
|
|
50
|
+
|
|
51
|
+
klass.class_eval{alias_method :"cached_#{als}", :"#{m}"}
|
|
52
|
+
unless vnames.is_a? Array
|
|
53
|
+
script = Cache["single_version_with_args.txt"].substitute binding
|
|
54
|
+
@versions[vnames] = 0 unless @versions.include? vnames
|
|
55
|
+
else
|
|
56
|
+
vnames_str = vnames.collect{|vname| "'#{vname}' => nil"}.join(', ')
|
|
57
|
+
script = Cache["multiple_version_with_args.txt"].substitute binding
|
|
58
|
+
vnames.each{|vname| @versions[vname] = 0 unless @versions.include? vname}
|
|
59
|
+
end
|
|
60
|
+
klass.class_eval script, __FILE__, __LINE__
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def version name
|
|
65
|
+
@versions[name]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def update *names
|
|
69
|
+
names.each do |n|
|
|
70
|
+
n = n.to_s
|
|
71
|
+
@versions[n] = 0 unless @versions.include? n
|
|
72
|
+
@versions[n] += 1
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
attr_reader :monitor
|
|
77
|
+
|
|
78
|
+
protected
|
|
79
|
+
def parse_and_check_arguments *arg
|
|
80
|
+
arg.size.should! :>=, 3
|
|
81
|
+
|
|
82
|
+
version_names = arg[0]
|
|
83
|
+
if version_names.is_a? Array
|
|
84
|
+
version_names.size.should! :>, 0
|
|
85
|
+
version_names = version_names.collect{|n| n.to_s}
|
|
86
|
+
else
|
|
87
|
+
version_names = version_names.to_s
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
klass = arg[1]
|
|
91
|
+
klass.class.should! :be, [Class, Module]
|
|
92
|
+
|
|
93
|
+
methods = arg[2..arg.size]
|
|
94
|
+
defined = klass.instance_methods
|
|
95
|
+
methods.each do |m|
|
|
96
|
+
raise "Invalid method_name '#{m}'!" unless defined.include? m.to_s
|
|
97
|
+
end
|
|
98
|
+
return version_names, klass, methods
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
def #{m} *params
|
|
2
|
+
Cache.monitor.synchronize do
|
|
3
|
+
@cache_versions_#{als} ||= {#{vnames_str}}
|
|
4
|
+
@cache_value_#{als} ||= {}
|
|
5
|
+
if @cache_versions_#{als}.all?{|vname, v| v == RubyExt::Cache.version(vname)} and @cache_value_#{als}.include?(params)
|
|
6
|
+
return @cache_value_#{als}[params]
|
|
7
|
+
else
|
|
8
|
+
@cache_versions_#{als}.keys.each{|vname| @cache_versions_#{als}[vname] = RubyExt::Cache.version(vname)}
|
|
9
|
+
return @cache_value_#{als}[params] = cached_#{als}(*params)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
def #{m}
|
|
2
|
+
Cache.monitor.synchronize do
|
|
3
|
+
@cache_versions_#{als} ||= {#{vnames_str}}
|
|
4
|
+
if @cache_versions_#{als}.all?{|vname, v| v == RubyExt::Cache.version(vname)}
|
|
5
|
+
return @cache_value_#{als}
|
|
6
|
+
else
|
|
7
|
+
@cache_versions_#{als}.keys.each{|vname| @cache_versions_#{als}[vname] = RubyExt::Cache.version(vname)}
|
|
8
|
+
return @cache_value_#{als} = cached_#{als}
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
def #{m} *params
|
|
2
|
+
Cache.monitor.synchronize do
|
|
3
|
+
@cache_value_#{als} ||= {}
|
|
4
|
+
if @cache_version_#{als} == RubyExt::Cache.version("#{vnames}") and @cache_value_#{als}.include?(params)
|
|
5
|
+
return @cache_value_#{als}[params]
|
|
6
|
+
else
|
|
7
|
+
@cache_version_#{als} = RubyExt::Cache.version("#{vnames}")
|
|
8
|
+
return @cache_value_#{als}[params] = cached_#{als}(*params)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
def #{m}
|
|
2
|
+
Cache.monitor.synchronize do
|
|
3
|
+
if @cache_version_#{als} == RubyExt::Cache.version("#{vnames}")
|
|
4
|
+
return @cache_value_#{als}
|
|
5
|
+
else
|
|
6
|
+
@cache_version_#{als} = RubyExt::Cache.version("#{vnames}")
|
|
7
|
+
return @cache_value_#{als} = cached_#{als}
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
module RubyExt
|
|
2
|
+
module ClassLoader
|
|
3
|
+
@monitor = Monitor.new
|
|
4
|
+
@loaded_classes = {}
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
include Observable
|
|
8
|
+
|
|
9
|
+
attr_accessor :error_on_defined_constant
|
|
10
|
+
|
|
11
|
+
def reload_class class_name
|
|
12
|
+
@monitor.synchronize do
|
|
13
|
+
class_name = class_name.sub(/^::/, "")
|
|
14
|
+
namespace = Module.namespace_for(class_name);
|
|
15
|
+
name = class_name.sub(/^#{namespace}::/, "")
|
|
16
|
+
return load_class namespace, name, true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def load_class namespace, const, reload = false
|
|
21
|
+
@monitor.synchronize do
|
|
22
|
+
namespace = nil if namespace == Object or namespace == Module
|
|
23
|
+
target_namespace = namespace
|
|
24
|
+
|
|
25
|
+
# Name hack (for anonymous classes)
|
|
26
|
+
namespace = eval "#{name_hack(namespace)}" if namespace
|
|
27
|
+
|
|
28
|
+
class_name = namespace ? "#{namespace.name}::#{const}" : const
|
|
29
|
+
simple_also_tried = false
|
|
30
|
+
begin
|
|
31
|
+
simple_also_tried = (namespace == nil)
|
|
32
|
+
|
|
33
|
+
if try_load class_name, const
|
|
34
|
+
defined_in_home_scope = namespace ? namespace.const_defined?(const) : \
|
|
35
|
+
Object.const_defined?(const)
|
|
36
|
+
|
|
37
|
+
raise_without_self NameError, "Class Name '#{class_name}' doesn't\
|
|
38
|
+
correspond to File Name '#{Resource.class_to_virtual_file(class_name)}'!", ClassLoader \
|
|
39
|
+
unless defined_in_home_scope
|
|
40
|
+
|
|
41
|
+
unless reload
|
|
42
|
+
if @loaded_classes.include? class_name
|
|
43
|
+
if error_on_defined_constant
|
|
44
|
+
raise_without_self NameError,
|
|
45
|
+
"Class '#{class_name}' is not defined in the '#{target_namespace}' Namespace!",
|
|
46
|
+
ClassLoader
|
|
47
|
+
else
|
|
48
|
+
warn "Warn: Class '#{class_name}' is not defined in the '#{target_namespace}' Namespace!"
|
|
49
|
+
puts caller
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
result = namespace ? namespace.const_get(const) : Object.const_get(const)
|
|
55
|
+
|
|
56
|
+
@loaded_classes[class_name] = target_namespace
|
|
57
|
+
notify_observers :update_class, result
|
|
58
|
+
return result
|
|
59
|
+
elsif namespace
|
|
60
|
+
namespace = Module.namespace_for(namespace.name)
|
|
61
|
+
class_name = namespace ? "#{namespace.name}::#{const}" : const
|
|
62
|
+
end
|
|
63
|
+
end until simple_also_tried
|
|
64
|
+
|
|
65
|
+
raise_without_self NameError, "uninitialized constant '#{class_name}'!",
|
|
66
|
+
ClassLoader
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def wrap_inside_namespace namespace, script
|
|
71
|
+
nesting = []
|
|
72
|
+
if namespace
|
|
73
|
+
current_scope = ""
|
|
74
|
+
namespace.name.split("::").each do |level|
|
|
75
|
+
current_scope += "::#{level}"
|
|
76
|
+
type = eval current_scope, TOPLEVEL_BINDING, __FILE__, __LINE__
|
|
77
|
+
nesting << [level, (type.class == Module ? "module" : "class")]
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
begining = nesting.collect{|l, t| "#{t} #{l};"}.join(' ')
|
|
81
|
+
ending = nesting.collect{"end"}.join('; ')
|
|
82
|
+
return "#{begining}#{script} \n#{ending}"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
protected
|
|
86
|
+
|
|
87
|
+
def try_load class_name, const
|
|
88
|
+
if Resource.class_exist? class_name
|
|
89
|
+
script = Resource.class_get class_name
|
|
90
|
+
script = wrap_inside_namespace Module.namespace_for(class_name), script
|
|
91
|
+
eval script, TOPLEVEL_BINDING, Resource.class_to_virtual_file(class_name)
|
|
92
|
+
# elsif Resource.class_namespace_exist? class_name
|
|
93
|
+
# script = "#{begining} module #{const}; end; #{ending}"
|
|
94
|
+
# eval script, TOPLEVEL_BINDING, __FILE__, __LINE__
|
|
95
|
+
else
|
|
96
|
+
return false
|
|
97
|
+
end
|
|
98
|
+
return true
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def name_hack namespace
|
|
102
|
+
if namespace
|
|
103
|
+
namespace.to_s.gsub("#<Class:", "").gsub(">", "")
|
|
104
|
+
else
|
|
105
|
+
""
|
|
106
|
+
end
|
|
107
|
+
# Namespace Hack description
|
|
108
|
+
# Module.name doesn't works correctly for Anonymous classes.
|
|
109
|
+
# try to execute this code:
|
|
110
|
+
#
|
|
111
|
+
#class Module
|
|
112
|
+
# def const_missing const
|
|
113
|
+
# p self.to_s
|
|
114
|
+
# end
|
|
115
|
+
#end
|
|
116
|
+
#
|
|
117
|
+
#class A
|
|
118
|
+
# class << self
|
|
119
|
+
# def a
|
|
120
|
+
# p self
|
|
121
|
+
# MissingConst
|
|
122
|
+
# end
|
|
123
|
+
# end
|
|
124
|
+
#end
|
|
125
|
+
#
|
|
126
|
+
#A.a
|
|
127
|
+
#
|
|
128
|
+
# the output will be:
|
|
129
|
+
# A
|
|
130
|
+
# "#<Class:A>"
|
|
131
|
+
#
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
class Module
|
|
138
|
+
# alias_method :old_const_missing, :const_missing
|
|
139
|
+
def const_missing const
|
|
140
|
+
return RubyExt::ClassLoader.load_class self, const.to_s
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class Debug
|
|
2
|
+
class << self
|
|
3
|
+
|
|
4
|
+
def trace_methods klass
|
|
5
|
+
klass.instance_methods(false).each do |m|
|
|
6
|
+
klass.class_eval do
|
|
7
|
+
alias_method :"old_#{m}", m
|
|
8
|
+
define_method m.to_sym do |*args|
|
|
9
|
+
begin
|
|
10
|
+
time = Time.now
|
|
11
|
+
p [m.to_sym, :start]
|
|
12
|
+
result = send :"old_#{m}", *args
|
|
13
|
+
ensure
|
|
14
|
+
p [m.to_sym, :end, time - Time.now]
|
|
15
|
+
end
|
|
16
|
+
return result
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class ExtraBlankSlate < BlankSlate
|
|
2
|
+
CUSTOM_UNDEFINE = [:p, :select, :puts]
|
|
3
|
+
|
|
4
|
+
undefine = Kernel.instance_methods + Object.instance_methods + CUSTOM_UNDEFINE
|
|
5
|
+
BlankSlate.instance_methods.each{|m| undefine.delete m}
|
|
6
|
+
|
|
7
|
+
undefine.each do |m|
|
|
8
|
+
script = %{\
|
|
9
|
+
def #{m} *p, &b
|
|
10
|
+
method_missing :#{m}, *p, &b
|
|
11
|
+
end}
|
|
12
|
+
class_eval script, __FILE__, __LINE__
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class Module
|
|
2
|
+
def localization lang
|
|
3
|
+
list, resource = [], "#{lang}.#{RubyExt::Localization::RESOURCE_EXTENSION}"
|
|
4
|
+
self_ancestors_and_namespaces do |klass|
|
|
5
|
+
if RubyExt::Resource.resource_exist? klass, resource
|
|
6
|
+
list << RubyExt::Resource.resource_get(klass, resource)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
return list.reverse.inject(:merge)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
Cache.cached_with_params :class, Module, :localization
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Object
|
|
2
|
+
def to_l string, binding = nil
|
|
3
|
+
lang = RubyExt::Localization.language
|
|
4
|
+
unless lang == RubyExt::Localization::DEFAULT_LANGUAGE
|
|
5
|
+
aself = self.respond_to(:localization_self) || self
|
|
6
|
+
aclass = (aself.class == Class or aself.class == Module) ? aself : aself.class
|
|
7
|
+
|
|
8
|
+
localization = aclass.localization lang
|
|
9
|
+
if localization and localization.include? string
|
|
10
|
+
string = localization[string]
|
|
11
|
+
else
|
|
12
|
+
RubyExt::Localization.log.warn("Not localized: '#{aclass.name}' '#{string}'!")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
string = string.substitute binding if binding
|
|
17
|
+
return string
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Localization
|
|
2
|
+
extend Log
|
|
3
|
+
DEFAULT_LANGUAGE = :en
|
|
4
|
+
RESOURCE_EXTENSION = "localization.yaml"
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def default_language= lang
|
|
8
|
+
@default_language = lang
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def default_language
|
|
12
|
+
@default_language ||= DEFAULT_LANGUAGE
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def language= block
|
|
16
|
+
@language = block
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def language
|
|
20
|
+
if @language
|
|
21
|
+
lang = @language.call
|
|
22
|
+
return lang || default_language
|
|
23
|
+
else
|
|
24
|
+
return default_language
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<log4r_config>
|
|
2
|
+
<pre_config>
|
|
3
|
+
<global level="DEBUG"/>
|
|
4
|
+
|
|
5
|
+
<parameter name="serverlog" value="./logs/server.log"/>
|
|
6
|
+
</pre_config>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<outputter type="FileOutputter" name="server">
|
|
10
|
+
<filename>#{serverlog}</filename>
|
|
11
|
+
<trunc>false</trunc>
|
|
12
|
+
</outputter>
|
|
13
|
+
<outputter type="FileOutputter" name="client"
|
|
14
|
+
filename="./../logs/client.log"/>
|
|
15
|
+
<outputter type="FileOutputter" name="gui"
|
|
16
|
+
filename="./../logs/guidebug.log"/>
|
|
17
|
+
<outputter type="StderrOutputter" name="console" level="ERROR"/>
|
|
18
|
+
|
|
19
|
+
<logger name="server" level="ERROR" outputters="server, console"/>
|
|
20
|
+
<logger name="client" level="INFO" outputters="client, console"/>
|
|
21
|
+
<logger name="client::gui" trace="true">
|
|
22
|
+
<level>DEBUG</level>
|
|
23
|
+
<outputter>gui</outputter>
|
|
24
|
+
</logger>
|
|
25
|
+
|
|
26
|
+
</log4r_config>
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
<log4r_config>
|
|
32
|
+
<pre_config>
|
|
33
|
+
<global level="ALL"/>
|
|
34
|
+
</pre_config>
|
|
35
|
+
|
|
36
|
+
<outputter type="StderrOutputter" name="default" level="ALL"/>
|
|
37
|
+
<logger name="Default" level="ALL" outputters="default"/>
|
|
38
|
+
|
|
39
|
+
<outputter type="StderrOutputter" name="console" level="WARN"/>
|
|
40
|
+
<outputter type="StderrOutputter" name="console_all" level="ALL"/>
|
|
41
|
+
<outputter type="FileOutputter" name="microcontainer" filename="./../logs/microcontainer.log"/>
|
|
42
|
+
<outputter type="FileOutputter" name="rubyext" filename="./../logs/rubyext.log"/>
|
|
43
|
+
<outputter type="FileOutputter" name="wgui" filename="./../logs/wgui.log"/>
|
|
44
|
+
<outputter type="FileOutputter" name="howt" filename="./../logs/howt.log"/>
|
|
45
|
+
<outputter type="FileOutputter" name="log" filename="./../logs/log.log"/>
|
|
46
|
+
<outputter type="FileOutputter" name="localization" filename="./../logs/localization.log"/>
|
|
47
|
+
<outputter type="FileOutputter" name="object_model" filename="./../logs/object_model.log" level="ALL"/>
|
|
48
|
+
|
|
49
|
+
<logger name="MicroContainer" level="ALL" outputters="console, microcontainer"/>
|
|
50
|
+
<logger name="HOWT" level="ALL" outputters="console, howt"/>
|
|
51
|
+
<logger name="WGUI" level="ALL" outputters="console, wgui"/>
|
|
52
|
+
<logger name="RubyExt" level="ALL" outputters="console, rubyext"/>
|
|
53
|
+
<logger name="Localization" level="ALL" outputters="localization"/>
|
|
54
|
+
<logger name="Log" level="ALL" outputters="console, log"/>
|
|
55
|
+
<logger name="ClassLoader" level="ALL" outputters="console_all"/>
|
|
56
|
+
<logger name="ObjectModel" level="ALL" outputters="object_model, console_all"/>
|
|
57
|
+
</log4r_config>
|
data/lib/RubyExt/Log.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'log4r/configurator'
|
|
3
|
+
|
|
4
|
+
module Log
|
|
5
|
+
@loggers = Hash.new do |hash, klass|
|
|
6
|
+
# Such complex initialization because I don't know how it exactly work.
|
|
7
|
+
# For example: Log.new for WGUI::SomeClass will works, but Log.new for WGUI will not.
|
|
8
|
+
logger = begin
|
|
9
|
+
Log4r::Logger.get(klass.name)
|
|
10
|
+
rescue
|
|
11
|
+
Log4r::Logger.new(klass.name) rescue Log4r::Logger.get("Default")
|
|
12
|
+
end
|
|
13
|
+
hash[klass] = logger
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module ClassMethods
|
|
17
|
+
def log
|
|
18
|
+
Log.loggers[(self.class == Class or self.class == Module) ? self : self.class]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def log
|
|
23
|
+
Log.loggers[(self.class == Class or self.class == Module) ? self : self.class]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
attr_reader :loggers
|
|
28
|
+
|
|
29
|
+
def info *s
|
|
30
|
+
log.info *s
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def error *s
|
|
34
|
+
log.error *s
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def warn *s
|
|
38
|
+
log.warn *s
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def log
|
|
42
|
+
Log.loggers[Log]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
# configure %{\
|
|
46
|
+
#<log4r_config>
|
|
47
|
+
# <pre_config>
|
|
48
|
+
# <global level="ALL"/>
|
|
49
|
+
# </pre_config>
|
|
50
|
+
#
|
|
51
|
+
# <outputter type="StderrOutputter" name="default" level="ALL"/>
|
|
52
|
+
# <logger name="Default" level="ALL" outputters="default"/>
|
|
53
|
+
#</log4r_config>}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
module Log
|
|
57
|
+
config = Dir.getwd + "config/log.xml"
|
|
58
|
+
Log4r::Configurator.load_xml_string(File.read(config)) if File.exist? config
|
|
59
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module OpenConstructor
|
|
2
|
+
def set values, list = nil
|
|
3
|
+
unless list
|
|
4
|
+
if values.is_a? Hash
|
|
5
|
+
values.each do |k, v|
|
|
6
|
+
self.respond_to k.to_writer, v
|
|
7
|
+
end
|
|
8
|
+
else
|
|
9
|
+
values.instance_variables.each do |name|
|
|
10
|
+
accessor = name[1..name.size].to_writer
|
|
11
|
+
if self.respond_to? accessor
|
|
12
|
+
self.send accessor, values.instance_variable_get(name)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
else
|
|
17
|
+
if values.is_a? Hash
|
|
18
|
+
values.each do |k, v|
|
|
19
|
+
self.respond_to k.to_writer, v if list.include? k
|
|
20
|
+
end
|
|
21
|
+
else
|
|
22
|
+
values.instance_variables.each do |name|
|
|
23
|
+
accessor = name[1..name.size]
|
|
24
|
+
if list.include?(accessor.to_sym)
|
|
25
|
+
accessor = accessor.to_writer
|
|
26
|
+
if self.respond_to?(accessor)
|
|
27
|
+
self.send accessor, values.instance_variable_get(name)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
return self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def set_with_check values
|
|
37
|
+
values.each do |k, v|
|
|
38
|
+
self.send k.to_writer, v
|
|
39
|
+
end
|
|
40
|
+
return self
|
|
41
|
+
end
|
|
42
|
+
alias_method :set!, :set_with_check
|
|
43
|
+
|
|
44
|
+
def to_hash
|
|
45
|
+
hash = {}
|
|
46
|
+
instance_variables.each do |name|
|
|
47
|
+
hash[name[1..name.size].to_sym] = instance_variable_get name
|
|
48
|
+
end
|
|
49
|
+
return hash
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/RubyExt/Path.rb
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
class Path < String
|
|
2
|
+
def initialize path = ''
|
|
3
|
+
super path.chomp
|
|
4
|
+
raise "Invalid Path '#{path}' (ends with the '/' sign)" if (self =~ /\/$/ ) && !empty?
|
|
5
|
+
raise "Tnvalid Path '#{path}' (the '/' sign encounters multiple times in a row)" if self =~ /\/{2,}/
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def absolute?;
|
|
9
|
+
(self =~ /^\//) ? true : false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def relative?;
|
|
13
|
+
!absolute?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def empty?; self == '' || self == '/' end
|
|
17
|
+
|
|
18
|
+
def simple?;
|
|
19
|
+
self =~ /^\/?[^\/]*$/ ? true : false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def after part
|
|
23
|
+
raise "There is no Part '#{part}' in the Path '#{self}'" unless include? part
|
|
24
|
+
Path.new((absolute? ? '/' : '') + sub(/.*#{part}\/*/, ""))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def before part
|
|
28
|
+
raise "There is no Part '#{part}' in the Path '#{self}'" unless include? part
|
|
29
|
+
Path.new((absolute? ? '/' : '') + to_relative.sub(/\/*#{part}.*/, ""))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def previous;
|
|
33
|
+
return nil if empty?
|
|
34
|
+
p = sub(/[^\/]+?$/, "" )
|
|
35
|
+
p = p[0..p.string_size-2] if p.string_size > 1
|
|
36
|
+
return p
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def next;
|
|
40
|
+
p = sub(/[^\/]+\/?/, "")
|
|
41
|
+
return p.empty? ? nil : p
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def first;
|
|
45
|
+
Path.new(scan(/^\/?[^\/]*/)[0])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def last;
|
|
49
|
+
Path.new(sub(/[^\/].+\//, ""))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def last_name
|
|
53
|
+
list = scan(/[^\/]+$/)
|
|
54
|
+
return list.size > 0 ? list[0] : nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def first_name
|
|
58
|
+
list = scan(/[^\/]+/)
|
|
59
|
+
return list.size > 0 ? list[0] : nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def add path
|
|
63
|
+
path = Path.new(path) unless path.is_a? Path
|
|
64
|
+
return Path.new((absolute? ? "/" : "") + path.to_relative) if empty?
|
|
65
|
+
return Path.new(self) if path.empty?
|
|
66
|
+
return Path.new(self.string_plus((path.absolute? ? '' : '/')) + path)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
alias_method :string_plus, :+
|
|
70
|
+
def + o
|
|
71
|
+
add(o)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_absolute; Path.new(absolute? ? self : "/#{self}") end
|
|
75
|
+
|
|
76
|
+
def to_relative; Path.new sub(/^\//, "") end
|
|
77
|
+
|
|
78
|
+
alias_method :string_each, :each
|
|
79
|
+
def each &block
|
|
80
|
+
to_a.each(&block)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
alias_method :string_size, :size
|
|
84
|
+
def size() to_a.size end
|
|
85
|
+
|
|
86
|
+
def to_a; @elements ||= to_relative.split('/') end
|
|
87
|
+
|
|
88
|
+
def to_s
|
|
89
|
+
return String.new(self)
|
|
90
|
+
end
|
|
91
|
+
end
|