jruby-ehcache 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,128 +1,51 @@
1
- require 'erb'
2
- require 'yaml'
3
-
4
- module Ehcache
5
-
6
- class MissingConfigurationException < StandardError
7
- def initialize(search_dirs)
8
- super("Could not find Ehcache configuration file in any of: #{search_dirs.inspect}")
1
+ require 'ehcache/yaml_config'
2
+
3
+ # Enhance net.sf.ehcache.config.Configuration with a more Rubyesque API, and
4
+ # add support for using YAML for configuration.
5
+ class Java::NetSfEhcacheConfig::Configuration
6
+ Factory = Java::NetSfEhcacheConfig::ConfigurationFactory
7
+
8
+ # Searches for an Ehcache configuration file and, if found, returns a
9
+ # Configuration object created from it. The search algorithm looks for
10
+ # files named "ehcache.yml" or "ehcache.xml", first looking in the provided
11
+ # directories in order, and if not found there then looking in the Ruby
12
+ # $LOAD_PATH.
13
+ # Returns nil if no configuration file is found.
14
+ def self.find(*dirs)
15
+ file_names = %w[ehcache.yml ehcache.xml]
16
+ dirs += $LOAD_PATH
17
+ dirs.each do |dir|
18
+ file_names.each do |name|
19
+ candidate = File.join(dir, name)
20
+ return create(candidate) if File.exist?(candidate)
21
+ end
9
22
  end
23
+ nil
10
24
  end
11
25
 
12
- # default configuration and a cache named "cache"
13
- # manager = Ehcache::CacheManager.new
14
- # cache = manager.cache
15
- #
16
- # default configuration and a cache named "steve"
17
- # manager = Ehcache::CacheManager.new({"cache" => {"name" => "steve"}})
18
- # cache = manager.cache("steve")
19
- class Config
20
- CONFIG_FILE_NAME = 'ehcache.yml'
21
-
22
- RAILS_CONFIG_DIR =
23
- if defined?(::Rails)
24
- File.join(::Rails.root.to_s, 'config')
25
- elsif defined?(RAILS_ROOT)
26
- File.join(RAILS_ROOT, 'config')
27
- end
28
-
29
- SEARCH_DIRS = [RAILS_CONFIG_DIR,
30
- File.join(ENV['HOME'], 'lib', 'config'),
31
- File.join(EHCACHE_HOME, 'config')].compact
32
-
33
- class << self
34
- def generate(options={})
35
- unless config_file = find_config_file
36
- raise MissingConfigurationException.new(SEARCH_DIRS)
26
+ def self.create(*args)
27
+ result = nil
28
+ case args.size
29
+ when 0
30
+ result = Factory.parseConfiguration()
31
+ when 1
32
+ arg = args.first
33
+
34
+ if arg.is_a?(String)
35
+ raise ArgumentError, "Cannot read config file '#{arg}'" unless File.readable?(arg)
36
+ if arg =~ /\.yml$/
37
+ result = Ehcache::Config::YamlConfig.parse_yaml_config(arg)
38
+ else
39
+ result = Factory.parseConfiguration(java.io.File.new(arg))
37
40
  end
38
- config = ERB.new(File.open(config_file) {|f| f.read})
39
- config = YAML.load(config.result(binding))
40
- initialize_factory_proxies
41
- process(config, options)
42
- end
43
-
44
- private
45
-
46
- def find_config_file
47
- SEARCH_DIRS.map {|dir| File.join(dir, CONFIG_FILE_NAME)}.find { |f|
48
- File.readable?(f)
49
- }
50
- end
51
-
52
- def process(config, options)
53
- # merge in new defaults if any
54
- config["default"].deep_merge!(options["default"]) if options["default"]
55
-
56
- # primary cache should be based off of default cache
57
- config["cache"] = config["default"].merge({"name" => Ehcache::Cache::PRIMARY})
58
-
59
- # update the rest of the configuration
60
- config.deep_merge!(options) if options
61
- config.each { |key, value| setter(key, value) }
62
-
63
- # add default cache and primary cache if present
64
- create_default_cache(config["default"])
65
- create_primary_cache(config["cache"]) if config["cache"]
66
-
67
- # populate the configuration
68
- @configuration.add_disk_store(@disk)
69
- @configuration.add_cache_manager_peer_provider_factory(@peer_provider)
70
- @configuration.add_cache_manager_peer_listener_factory(@peer_listener)
71
- @configuration
72
- end
73
-
74
- # creates and installs default cache
75
- def create_default_cache(default)
76
- default_cache_config = create_cache_configuration("default", default)
77
- @configuration.add_default_cache(default_cache_config)
78
- end
79
-
80
- # creates and installs primary cache
81
- def create_primary_cache(primary)
82
- primary_cache_config = create_cache_configuration("cache", primary)
83
- @configuration.add_cache(primary_cache_config)
84
- end
85
-
86
- # creates and sets up cache configurations
87
- def create_cache_configuration(cache_name, data)
88
- config = instance_variable_get("@#{cache_name}".intern)
89
- data.each { |k,v|
90
- # included hashes will be event listener factories, exception handler
91
- # factories, loader factories, etc. TODO: clean this up, and add
92
- # support for adding other factories in a cleaner fashion.
93
- if v.is_a?(Hash)
94
- case k
95
- when "event_listener":
96
- event_factory = Ehcache::Java::CacheConfiguration::CacheEventListenerFactoryConfiguration.new(config)
97
- v.each { |k,v| event_factory.send("set_#{k.to_s}",v) }
98
- config.add_cache_event_listener_factory(event_factory)
99
- when "bootstrap_loader":
100
- bootstrap_loader = Ehcache::Java::CacheConfiguration::BootstrapCacheLoaderFactoryConfiguration.new(config)
101
- v.each { |k,v| bootstrap_loader.send("set_#{k.to_s}",v) }
102
- config.add_bootstrap_cache_loader_factory(bootstrap_loader)
103
- end
104
- else
105
- config.send("set_#{k.to_s}",v)
106
- end
107
- }
108
- config
109
- end
110
-
111
- # initialize all the java factory proxies for configuration
112
- def initialize_factory_proxies
113
- @configuration = Ehcache::Java::Configuration.new
114
- @disk = Ehcache::Java::DiskStoreConfiguration.new
115
- @cache = Ehcache::Java::CacheConfiguration.new
116
- @default = Ehcache::Java::CacheConfiguration.new
117
- @peer_provider = Ehcache::Java::FactoryConfiguration.new
118
- @peer_listener = Ehcache::Java::FactoryConfiguration.new
41
+ else
42
+ result = Factory.parseConfiguration(arg)
119
43
  end
44
+ end
120
45
 
121
- # helper for setters
122
- def setter(factory, config)
123
- factory = instance_variable_get("@#{factory}".intern)
124
- config.each { |k,v| factory.send("set_#{k.to_s}",v) unless v.is_a?(Hash) }
125
- end
46
+ unless result.is_a?(self)
47
+ raise ArgumentError, "Could not create Configuration from: #{args.inspect}"
126
48
  end
49
+ result
127
50
  end
128
51
  end
@@ -1,27 +1,17 @@
1
- module Ehcache
2
- class Element
3
- attr_accessor :key, :value
4
-
5
- def initialize(key, value, options = {})
6
- @key = key
7
- @value = value
8
- @ttl = options[:ttl] || nil
9
-
10
- element = Ehcache::Java::Element.new(key, value)
11
- element.set_time_to_live(@ttl) if @ttl
12
- @proxy = element
13
- end
14
-
15
- def ttl
16
- @ttl = @proxy.get_time_to_live
1
+ # Enhance net.sf.ehcache.Element with a more Rubyesque API.
2
+ class Java::NetSfEhcache::Element
3
+ def self.create(key, value, options = {})
4
+ result = self.new(key, value)
5
+ options.each do |key, value|
6
+ setter = "#{key}=".to_sym
7
+ result.send(setter, value) if result.respond_to?(setter)
17
8
  end
9
+ result
10
+ end
18
11
 
19
- def tti
20
- @tti = @proxy.get_time_to_idle
21
- end
12
+ alias tti getTimeToIdle
13
+ alias ttl getTimeToLive
22
14
 
23
- def proxy
24
- @proxy
25
- end
26
- end
15
+ alias tti= setTimeToIdle
16
+ alias ttl= setTimeToLive
27
17
  end
@@ -1,3 +1,6 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+ require 'active_support/core_ext/array/extract_options'
3
+
1
4
  class Hash
2
5
  # Merges self with another hash, recursively.
3
6
  # This code was lovingly stolen from some random gem:
data/lib/ehcache/java.rb CHANGED
@@ -1,8 +1,38 @@
1
+ require 'java'
2
+
3
+ EHCACHE_LIBS_DIR = "#{Ehcache::EHCACHE_HOME}/ext"
4
+
1
5
  module Ehcache
2
- module Java
3
- include ::Java
4
- Dir["#{Ehcache::EHCACHE_HOME}/ext/**/*.jar"].sort.each {|l| require l}
5
- include_package "net.sf.ehcache"
6
- include_package "net.sf.ehcache.config"
6
+ slf4j_loader = lambda { Java::OrgSlf4j::LoggerFactory.getLogger("JRubyEhcache") }
7
+ begin
8
+ LOG = slf4j_loader.call
9
+ LOG.info("Using SLF4J Logger from CLASSPATH")
10
+ rescue NameError
11
+ Dir["#{EHCACHE_LIBS_DIR}/**/*slf4j*.jar"].each do |l| require l end
12
+ LOG = slf4j_loader.call
13
+ LOG.info("Using bundled SLF4J Logger")
7
14
  end
15
+
16
+ ehcache_version_loader = lambda {
17
+ Java::NetSfEhcacheUtil::ProductInfo.new.getVersion()
18
+ }
19
+ begin
20
+ # If Ehcache is already on the classpath, use it.
21
+ VERSION = ehcache_version_loader.call
22
+ LOG.info("Using Ehcache #{VERSION} from CLASSPATH")
23
+ rescue NameError
24
+ # If not, use the Ehcache bundled with the jruby-ehcache gem.
25
+ Dir["#{EHCACHE_LIBS_DIR}/**/*.jar"].each do |l|
26
+ require l unless l =~ /slf4j/
27
+ end
28
+ VERSION = ehcache_version_loader.call
29
+ LOG.info("Using bundled Ehcache #{VERSION}")
30
+ end
31
+
32
+ include_package 'net.sf.ehcache'
33
+
34
+ module Config
35
+ include_package 'net.sf.ehcache.config'
36
+ end
37
+
8
38
  end
@@ -0,0 +1,251 @@
1
+ require 'java'
2
+ require 'ehcache'
3
+ require 'yaml'
4
+ require 'erb'
5
+
6
+ module Ehcache::Config
7
+ # Support for using YAML for Ehcache configuration.
8
+ #
9
+ # <strong>DEPRECATED:</strong> Please use ehcache.xml instead.
10
+ #
11
+ # YAML configuration is similar to XML configuration, but there are some
12
+ # changes to the names of configuration elements to make them simpler or
13
+ # more idiomatic to Ruby and YAML conventions. The changes are described
14
+ # below. For full documentation on the Ehcache configuration elements,
15
+ # see the Ehcache Cache Configuration documentation:
16
+ # http://ehcache.org/documentation/configuration.html
17
+ #
18
+ # The top level YAML configuration attributes and the corresponding XML
19
+ # elements or attributes are shown in the following table.
20
+ #
21
+ # name:: name attribute on ehcache element
22
+ # update_check:: updateCheck attribute on ehcache element
23
+ # monitoring:: monitoring attribute on ehcache element
24
+ # dynamic_config:: dynamicConfig attribute on ehcache element
25
+ # disk_store:: diskStore element
26
+ # transaction_manager:: transactionManagerLookup element
27
+ # event_listener:: cacheManagerEventListenerFactory element
28
+ # peer_providers (Array):: cacheManagerPeerProviderFactory elements
29
+ # peer_listeners (Array):: cacheManagerPeerListenerFactory elements
30
+ # terracotta_config:: terracottaConfig element
31
+ # default_cache:: defaultCache element
32
+ # caches (Array):: cache elements
33
+ #
34
+ # Each top level configuration attribute contains a set of key/value pairs
35
+ # that are equivalent to the Ehcache XML attributes, except that the
36
+ # attribute names are converted to use underscore_names instead of
37
+ # camelCaseNames. For instance, the Ehcache XML attribute
38
+ # diskSpoolBufferSizeMB becomes disk_spool_buffer_size_mb in YAML.
39
+ #
40
+ # Entries in the above table that are marked as (Array) should be YAML lists
41
+ # to allow for multiple values. So, for example, to configure multiple
42
+ # caches in your YAML configuration, use the following syntax:
43
+ #
44
+ # caches:
45
+ # - name: my_cache
46
+ # time_to_idle_seconds: 360
47
+ # time_to_live_seconds: 1000
48
+ # - name: my_other_cache
49
+ # max_elements_in_memory: 1000
50
+ # eternal: true
51
+ # overflow_to_disk: false
52
+ # disk_persistent: true
53
+ #
54
+ # Note the use of the '-' to separate list elements.
55
+ #
56
+ # One further difference between YAML configuration and XML configuration
57
+ # deals with cache configuration. The XML configuration allows for a set
58
+ # of XML sub elements to configure various aspects of caches (or the default
59
+ # cache). In YAML, these sub elements are translated to attributes within
60
+ # the cache configuration (or default_cache configuration) that
61
+ # refer to Hashes or Arrays. The following table shows the mapping.
62
+ #
63
+ # event_listeners (Array):: cacheEventListenerFactory sub elements
64
+ # extensions (Array):: cacheExtensionFactory sub elements
65
+ # loaders (Array):: cacheLoaderFactory sub elements
66
+ # decorators (Array):: cacheDecoratorFactory sub elements
67
+ # bootstrap_loader (Hash):: bootstrapCacheLoaderFactory sub element
68
+ # exception_handler (Hash):: cacheExceptionHandlerFactory sub element
69
+ # terracotta (Hash):: terracotta sub element
70
+ # cache_writer (Hash):: cacheWriter sub element
71
+ # copy_strategy (Hash):: copyStrategy sub element
72
+ #
73
+ # Those marked as (Array) may take a list of values, while those marked as
74
+ # (Hash) may take a single Hash value (set of key/value pairs). Here is an
75
+ # example of a cache configuration that uses one of each style:
76
+ #
77
+ # caches:
78
+ # - name: some_cache
79
+ # time_to_live_seconds: 100
80
+ # event_listeners:
81
+ # - class: net.sf.ehcache.distribution.RMICacheReplicatorFactory
82
+ # properties: "replicateAsynchronously=false"
83
+ # copy_strategy:
84
+ # class: net.sf.ehcache.store.compound.SerializationCopyStrategy
85
+ #
86
+ # Note again the use of the '-' character to separate list elements in the
87
+ # case of Array values, which is not present for Hash values.
88
+ module YamlConfig
89
+
90
+ InvalidYamlConfiguration = Class.new(StandardError)
91
+
92
+ # Not sure why, but "include Java::NetSfEhcacheConfig" does not work,
93
+ # so define local constants referring to the Ehcache classes
94
+ Configuration = Java::NetSfEhcacheConfig::Configuration
95
+ CacheConfiguration = Java::NetSfEhcacheConfig::CacheConfiguration
96
+ DiskStoreConfiguration = Java::NetSfEhcacheConfig::DiskStoreConfiguration
97
+ FactoryConfiguration = Java::NetSfEhcacheConfig::FactoryConfiguration
98
+
99
+ %w[name update_check monitoring dynamic_config
100
+ disk_store transaction_manager event_listener
101
+ peer_providers peer_listeners
102
+ terracotta_config default_cache caches
103
+ event_listeners extensions loaders decorators
104
+ ].each do |attribute|
105
+ const_set(attribute.upcase.to_sym, attribute)
106
+ end
107
+
108
+ # Parses the given yaml_config_file and returns a corresponding
109
+ # Ehcache::Config::Configuration object.
110
+ def self.parse_yaml_config(yaml_config_file)
111
+ Ehcache::LOG.warn("YAML configuration is deprecated. Please use ehcache.xml instead.")
112
+ YamlConfigBuilder.new(yaml_config_file).build
113
+ end
114
+
115
+ private
116
+
117
+ class YamlConfigBuilder
118
+
119
+ def initialize(yaml_file)
120
+ @yaml_file = yaml_file
121
+ @data = YAML.load(ERB.new(File.read(yaml_file)).result(binding))
122
+ raise InvalidYamlConfiguration unless valid?(@data)
123
+ end
124
+
125
+ def build
126
+ @config = Configuration.new
127
+ for attribute in [NAME, UPDATE_CHECK, MONITORING, DYNAMIC_CONFIG]
128
+ set_if_present(attribute)
129
+ end
130
+ set_disk_store
131
+ set_transaction_manager
132
+ set_event_listener
133
+ add_peer_providers
134
+ add_peer_listeners
135
+ set_default_cache
136
+ add_caches
137
+ @config
138
+ end
139
+
140
+ private
141
+
142
+ def valid?(data)
143
+ data.is_a?(Hash)
144
+ end
145
+
146
+ def set_if_present(key)
147
+ if @data.has_key?(key)
148
+ setter = "#{key}=".to_sym
149
+ @config.send(setter, @data[key])
150
+ end
151
+ end
152
+
153
+ def set_attributes(object, attributes)
154
+ attributes ||= []
155
+ attributes.each do |key, value|
156
+ if value.is_a?(Hash) || value.is_a?(Array)
157
+ create_cache_config_factories(object, key, value)
158
+ else
159
+ object.send("#{key}=", value)
160
+ end
161
+ end
162
+ object
163
+ end
164
+
165
+ def create_cache_config_factories(cache, key, value)
166
+ [value].flatten.each do |data|
167
+ create_cache_config_factory(cache, key, data)
168
+ end
169
+ end
170
+
171
+ def names_for_factory(key)
172
+ singular = key.singularize.sub(/s$/, '')
173
+ factory_name = if key == 'bootstrap_loader'
174
+ "BootstrapCacheLoaderFactory"
175
+ else
176
+ "Cache#{singular.camelize}Factory"
177
+ end
178
+ class_name = "#{factory_name}Configuration"
179
+ method_name = "add#{factory_name}"
180
+ return [class_name, method_name]
181
+ end
182
+
183
+ def create_cache_config_factory(cache, key, data)
184
+ class_name, method_name = names_for_factory(key)
185
+ factory_class = CacheConfiguration.const_get(class_name)
186
+ factory = factory_class.new
187
+
188
+ cache.send(method_name, factory)
189
+ set_attributes(factory, data)
190
+ end
191
+
192
+ def apply_config(key, config_class)
193
+ if @data[key]
194
+ [@data[key]].flatten.each do |data|
195
+ config = config_class.new
196
+ set_attributes(config, data)
197
+ yield config
198
+ end
199
+ end
200
+ end
201
+
202
+ def set_disk_store
203
+ apply_config(DISK_STORE, DiskStoreConfiguration) do |disk_store|
204
+ @config.add_disk_store(disk_store)
205
+ end
206
+ end
207
+
208
+ def set_transaction_manager
209
+ apply_config(TRANSACTION_MANAGER, FactoryConfiguration) do |tx_mgr|
210
+ @config.add_transaction_manager_lookup(tx_mgr)
211
+ end
212
+ end
213
+
214
+ def set_event_listener
215
+ apply_config(EVENT_LISTENER, FactoryConfiguration) do |event_listener|
216
+ @config.addCacheManagerEventListenerFactory(event_listener)
217
+ end
218
+ end
219
+
220
+ def add_peer_providers
221
+ apply_config(PEER_PROVIDERS, FactoryConfiguration) do |peer_provider|
222
+ @config.addCacheManagerPeerProviderFactory(peer_provider)
223
+ end
224
+ end
225
+
226
+ def add_peer_listeners
227
+ apply_config(PEER_LISTENERS, FactoryConfiguration) do |peer_listener|
228
+ @config.addCacheManagerPeerListenerFactory(peer_listener)
229
+ end
230
+ end
231
+
232
+ def set_default_cache
233
+ apply_config(DEFAULT_CACHE, CacheConfiguration) do |cache_config|
234
+ @config.default_cache_configuration = cache_config
235
+ end
236
+ end
237
+
238
+ def add_caches
239
+ apply_config(CACHES, CacheConfiguration) do |cache_config|
240
+ @config.add_cache(cache_config)
241
+ end
242
+ end
243
+
244
+ def create_factory_configuration(data)
245
+ result = FactoryConfiguration.new
246
+ set_attributes(result, data)
247
+ result
248
+ end
249
+ end
250
+ end
251
+ end