jruby-ehcache-rails3 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +15 -0
  4. data/History.txt +15 -0
  5. data/License.txt +23 -0
  6. data/Manifest.txt +37 -0
  7. data/PostInstall.txt +2 -0
  8. data/README.txt +9 -0
  9. data/Rakefile +13 -0
  10. data/VERSION +1 -0
  11. data/config/ehcache.yml +22 -0
  12. data/config/ehcache_manual_rmi.yml +27 -0
  13. data/examples/ehcache.xml +44 -0
  14. data/examples/jruby-ehcache.rb +13 -0
  15. data/ext/ehcache-2.4.6/ehcache-core-2.4.6.jar +0 -0
  16. data/ext/ehcache-2.4.6/ehcache-terracotta-2.4.6.jar +0 -0
  17. data/ext/ehcache-2.4.6/slf4j-api-1.6.1.jar +0 -0
  18. data/ext/ehcache-2.4.6/slf4j-jdk14-1.6.1.jar +0 -0
  19. data/ext/ehcache-2.4.6/terracotta-toolkit-1.3-runtime-3.3.0.jar +0 -0
  20. data/ext/marshaled-ruby-object.jar +0 -0
  21. data/jruby-ehcache-rails2.gemspec +27 -0
  22. data/jruby-ehcache-rails3.gemspec +27 -0
  23. data/jruby-ehcache.gemspec +23 -0
  24. data/lib/ehcache/active_support_store.rb +12 -1
  25. data/lib/ehcache/cache.rb +74 -0
  26. data/lib/ehcache/cache_manager.rb +69 -0
  27. data/lib/ehcache/config.rb +51 -0
  28. data/lib/ehcache/element.rb +36 -0
  29. data/lib/ehcache/java.rb +57 -0
  30. data/lib/ehcache/version.rb +3 -0
  31. data/lib/ehcache/yaml_config.rb +251 -0
  32. data/lib/ehcache.rb +22 -0
  33. data/script/console +10 -0
  34. data/script/destroy +14 -0
  35. data/script/generate +14 -0
  36. data/script/txt2html +82 -0
  37. data/spec/cache_manager_spec.rb +81 -0
  38. data/spec/cache_spec.rb +86 -0
  39. data/spec/spec.opts +2 -0
  40. data/spec/spec_helper.rb +12 -0
  41. data/src/net/sf/ehcache/MarshaledRubyObject.java +15 -0
  42. data/tasks/deployment.rake +34 -0
  43. data/tasks/environment.rake +7 -0
  44. data/tasks/website.rake +17 -0
  45. data/test/ehcache.xml +44 -0
  46. data/test/ehcache.yml +67 -0
  47. data/test/test_cache.rb +36 -0
  48. data/test/test_cache_manager.rb +27 -0
  49. data/test/test_configuration.rb +29 -0
  50. data/test/test_ehcache.rb +22 -0
  51. data/test/test_element.rb +37 -0
  52. data/test/test_helper.rb +22 -0
  53. data/test/test_yaml_config.rb +159 -0
  54. data/website/index.html +141 -0
  55. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  56. data/website/stylesheets/screen.css +138 -0
  57. data/website/template.html.erb +48 -0
  58. metadata +76 -97
data/test/ehcache.xml ADDED
@@ -0,0 +1,44 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+
3
+ <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:noNamespaceSchemaLocation="../../main/config/ehcache.xsd">
5
+
6
+ <!-- Disable for test ehcache.xml. Should go to the same place. -->
7
+ <diskStore path="java.io.tmpdir"/>
8
+
9
+ <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
10
+ properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446, timeToLive=0"/>
11
+
12
+
13
+ <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
14
+ properties="hostName=, port=, socketTimeoutMillis="/>
15
+
16
+
17
+ <defaultCache
18
+ name="default"
19
+ maxElementsInMemory="10"
20
+ eternal="false"
21
+ timeToIdleSeconds="5"
22
+ timeToLiveSeconds="10"
23
+ overflowToDisk="true"
24
+ />
25
+
26
+
27
+ <!-- Sample cache named sampleCache1 -->
28
+ <cache name="sampleCache1"
29
+ maxElementsInMemory="10000"
30
+ maxElementsOnDisk="1000"
31
+ eternal="false"
32
+ timeToIdleSeconds="360"
33
+ timeToLiveSeconds="1000"
34
+ overflowToDisk="true">
35
+ </cache>
36
+
37
+ <!-- Sample cache named sampleCache2. Is eternal. Is diskPersistent but does not overflow to disk -->
38
+ <cache name="sampleCache2"
39
+ maxElementsInMemory="1000"
40
+ eternal="true"
41
+ overflowToDisk="false"
42
+ diskPersistent="true"
43
+ />
44
+ </ehcache>
data/test/ehcache.yml ADDED
@@ -0,0 +1,67 @@
1
+ name: testing
2
+ update_check: false
3
+ monitoring: autodetect
4
+ dynamic_config: true
5
+
6
+ disk_store:
7
+ path: java.io.tmpdir
8
+
9
+ transaction_manager:
10
+ class: net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup
11
+ properties: jndiName=java:/TransactionManager
12
+ property_separator: ";"
13
+
14
+ peer_providers:
15
+ - class: net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory
16
+ properties: peerDiscovery=automatic,multicastGroupAddress=230.0.0.1,multicastGroupPort=4446,timeToLive=1
17
+ property_separator: ","
18
+
19
+ peer_listeners:
20
+ - class: net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory
21
+
22
+ default_cache:
23
+ max_elements_in_memory: 10000
24
+ time_to_live_seconds: 0
25
+ time_to_idle_seconds: 0
26
+ overflow_to_disk: true
27
+ eternal: false
28
+ disk_spool_buffer_size_mb: 30
29
+ disk_persistent: false
30
+ disk_expiry_thread_interval_seconds: 120
31
+ memory_store_eviction_policy: LRU
32
+
33
+ caches:
34
+ # Sample cache named sampleCache1
35
+ - name: sampleCache1
36
+ max_elements_in_memory: 10000
37
+ max_elements_on_disk: 1000
38
+ eternal: false
39
+ time_to_idle_seconds: 360
40
+ time_to_live_seconds: 1000
41
+ overflow_to_disk: true
42
+
43
+ #Sample cache named sampleCache2. Is eternal. Is diskPersistent but does not overflow to disk
44
+ - name: sampleCache2
45
+ max_elements_in_memory: 1000
46
+ eternal: true
47
+ overflow_to_disk: false
48
+ disk_persistent: true
49
+
50
+ - name: sampleCacheWithCacheConfigurations
51
+ max_elements_in_memory: 10
52
+ eternal: false
53
+ time_to_idle_seconds: 100
54
+ time_to_live_seconds: 100
55
+ overflow_to_disk: false
56
+ bootstrap_loader:
57
+ class: net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory
58
+ properties: "bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"
59
+ property_separator: ","
60
+ event_listeners:
61
+ - class: net.sf.ehcache.distribution.RMICacheReplicatorFactory
62
+ properties: "replicateAsynchronously=false, replicatePuts=false, replicatePutsViaCopy=false, replicateUpdates=true, replicateUpdatesViaCopy=true, replicateRemovals=false"
63
+ - class: net.sf.ehcache.distribution.RMICacheReplicatorFactory
64
+ properties: "replicateAsynchronously=false, replicatePuts=false, replicatePutsViaCopy=false, replicateUpdates=true, replicateUpdatesViaCopy=true, replicateRemovals=false"
65
+ # extensions:
66
+ # - class: com.example.FileWatchingCacheRefresherExtensionFactory
67
+ # properties: "refreshIntervalMillis=18000, loaderTimeout=3000, flushPeriod=whatever, someOtherProperty=someValue"
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestCache < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @manager = Ehcache::CacheManager.new
7
+ @cache = @manager.cache
8
+ end
9
+
10
+ def teardown
11
+ @manager.shutdown if @manager
12
+ end
13
+
14
+ must 'correctly implement compare and swap' do
15
+ @cache.put('number', 42, {:ttl => 120})
16
+ assert_equal(42, @cache['number'])
17
+ @cache.compare_and_swap('number') {|n| n - 31}
18
+ assert_equal(11, @cache['number'])
19
+ end
20
+
21
+ must 'have aliases for isKeyInCache called include and member' do
22
+ @cache.put('something', 'no matter')
23
+ for key in %w[something nothing]
24
+ assert_equal(@cache.isKeyInCache(key), @cache.include?(key))
25
+ assert_equal(@cache.isKeyInCache(key), @cache.member?(key))
26
+ end
27
+ end
28
+
29
+ must 'implement each and include Enumerable' do
30
+ assert_kind_of(Enumerable, @cache)
31
+ assert_respond_to(@cache, :each)
32
+ @cache.put('1', 1)
33
+ @cache.put('2', 2)
34
+ assert @cache.all? {|e| e.is_a?(Java::NetSfEhcache::Element)}
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestCacheManager < Test::Unit::TestCase
4
+ def setup
5
+ @cache_manager = Ehcache::CacheManager.new
6
+ end
7
+
8
+ def teardown
9
+ @cache_manager.shutdown if @cache_manager
10
+ end
11
+
12
+ must 'be the real Ehcache Java CacheManager' do
13
+ assert_kind_of(Java::NetSfEhcache::CacheManager, @cache_manager)
14
+ end
15
+
16
+ must 'use the ehcache.xml file in the test directory' do
17
+ @cache_manager.cache_names.each do |name|
18
+ puts "Cache: #{name}"
19
+ end
20
+ end
21
+
22
+ must 'implement each and include Enumerable' do
23
+ assert_kind_of(Enumerable, @cache_manager)
24
+ assert_respond_to(@cache_manager, :each)
25
+ assert @cache_manager.all? {|cache| cache.is_a?(Java::NetSfEhcache::Ehcache)}
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestConfiguration < Test::Unit::TestCase
4
+ def setup
5
+ create_config
6
+ end
7
+
8
+ def test_is_a_real_ehcache_java_configuration_object
9
+ assert_valid_configuration(@config)
10
+ end
11
+
12
+ must 'initialize with ehcache.xml' do
13
+ create_config(File.join(File.dirname(__FILE__), 'ehcache.xml'))
14
+ assert_valid_configuration(@config)
15
+ assert_not_nil(@config.configuration_source)
16
+ cache_configs = @config.cache_configurations
17
+ assert_equal(2, cache_configs.size)
18
+ end
19
+
20
+ private
21
+
22
+ def create_config(*args)
23
+ @config = Ehcache::Config::Configuration.create(*args)
24
+ end
25
+
26
+ def assert_valid_configuration(config)
27
+ assert_kind_of(Java::NetSfEhcacheConfig::Configuration, config)
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestEhcache < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @manager = Ehcache::CacheManager.new
7
+ @cache = @manager.cache
8
+ end
9
+
10
+ def teardown
11
+ @manager.shutdown if @manager
12
+ end
13
+
14
+ def test_demo_usage
15
+ @cache.put("answer", "42", {:ttl => 120})
16
+ answer = @cache.get("answer")
17
+ assert_equal("42", answer.value)
18
+ assert_equal(120, answer.ttl)
19
+ question = @cache["question"] || 'unknown'
20
+ assert_equal('unknown', question)
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestElement < Test::Unit::TestCase
4
+ ALIASES = {
5
+ :tti => :time_to_idle,
6
+ :ttl => :time_to_live
7
+ }
8
+
9
+ ALIASES.each do |short, long|
10
+ must "have reader alias named #{short} referring to #{long}" do
11
+ element = Ehcache::Element.new('', '')
12
+ assert_respond_to(element, long)
13
+ assert_respond_to(element, short)
14
+ assert_equal(element.send(long), element.send(long))
15
+ end
16
+
17
+ must "have writer alias named #{short} referring to #{long}" do
18
+ element = Ehcache::Element.new('', '')
19
+ long_writer = "#{long}=".to_sym
20
+ short_writer = "#{short}=".to_sym
21
+ assert_respond_to(element, long_writer)
22
+ assert_respond_to(element, short_writer)
23
+
24
+ element.send(long_writer, 1)
25
+ assert_equal(1, element.send(long))
26
+ assert_equal(1, element.send(short))
27
+ element.send(short_writer, 2)
28
+ assert_equal(2, element.send(long))
29
+ assert_equal(2, element.send(short))
30
+ end
31
+ end
32
+
33
+ must 'process ttl option on create' do
34
+ element = Ehcache::Element.create('k', 'v', :ttl => 42)
35
+ assert_equal(element.ttl, 42)
36
+ end
37
+ end
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'test/unit'
4
+ require 'ehcache'
5
+ require 'java'
6
+
7
+ module Test::Unit
8
+ class TestCase
9
+ def self.must(name, &block)
10
+ test_name = "test_#{name.gsub(/[\s.]+/, '_')}".to_sym
11
+ defined = instance_method(test_name) rescue false
12
+ raise "#{test_name} is already defined in #{self}" if defined
13
+ if block_given?
14
+ define_method(test_name, &block)
15
+ else
16
+ define_method(test_name) do
17
+ flunk "No implementation provided for #{name}"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,159 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestConfiguration < Test::Unit::TestCase
4
+ def setup
5
+ @yaml_file = File.join(File.dirname(__FILE__), 'ehcache.yml')
6
+ @config = Ehcache::Config::Configuration.create(@yaml_file)
7
+ end
8
+
9
+ must 'have valid top level attributes' do
10
+ assert_equal('testing', @config.getName)
11
+ assert_equal(false, @config.getUpdateCheck)
12
+ assert_equal(Ehcache::Config::Configuration::Monitoring::AUTODETECT, @config.getMonitoring)
13
+ assert_equal(true, @config.getDynamicConfig)
14
+ end
15
+
16
+ must 'have valid disk store configuration' do
17
+ disk_store = @config.getDiskStoreConfiguration
18
+ assert_not_nil(disk_store)
19
+ assert_equal(java.lang.System.getProperty('java.io.tmpdir'),
20
+ disk_store.getPath)
21
+ end
22
+
23
+ must 'have valid transaction manager' do
24
+ tx_mgr = @config.getTransactionManagerLookupConfiguration
25
+ assert_factory_configuration_equals(tx_mgr,
26
+ :class => 'net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup',
27
+ :properties => 'jndiName=java:/TransactionManager',
28
+ :property_separator => ';')
29
+ end
30
+
31
+ must 'have valid peer provider' do
32
+ peer_providers = @config.getCacheManagerPeerProviderFactoryConfiguration
33
+ assert_equal(1, peer_providers.size)
34
+ peer_provider = peer_providers.first
35
+ assert_factory_configuration_equals(peer_provider,
36
+ :class => 'net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory',
37
+ :properties => 'peerDiscovery=automatic,multicastGroupAddress=230.0.0.1,multicastGroupPort=4446,timeToLive=1',
38
+ :property_separator => ',')
39
+ end
40
+
41
+ must 'have valid peer listener' do
42
+ peer_listeners = @config.getCacheManagerPeerListenerFactoryConfigurations
43
+ assert_equal(1, peer_listeners.size)
44
+ peer_listener = peer_listeners.first
45
+ assert_factory_configuration_equals(peer_listener,
46
+ :class => 'net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory')
47
+ end
48
+
49
+ must 'have valid default cache' do
50
+ default_cache = @config.getDefaultCacheConfiguration
51
+ expected = {
52
+ :getMaxElementsInMemory => 10000,
53
+ :getTimeToLiveSeconds => 0,
54
+ :getTimeToIdleSeconds => 0,
55
+ :isOverflowToDisk => true,
56
+ :isEternal => false,
57
+ :getDiskSpoolBufferSizeMB => 30,
58
+ :isDiskPersistent => false,
59
+ :getDiskExpiryThreadIntervalSeconds => 120,
60
+ :getMemoryStoreEvictionPolicy => Java::NetSfEhcacheStore::MemoryStoreEvictionPolicy::LRU
61
+ }
62
+ expected.each do |key, value|
63
+ assert_equal(value, default_cache.send(key))
64
+ end
65
+ end
66
+
67
+ must 'have two cache configurations' do
68
+ caches = @config.getCacheConfigurations
69
+ assert_equal(3, caches.size)
70
+ assert(caches.containsKey("sampleCache1"), "Should have sampleCache1")
71
+ assert(caches.containsKey("sampleCache2"), "Should have sampleCache2")
72
+ end
73
+
74
+ must 'have valid sampleCache1 configuration' do
75
+ cache = @config.getCacheConfigurations['sampleCache1']
76
+ expected = {
77
+ :getMaxElementsInMemory => 10000,
78
+ :getMaxElementsOnDisk => 1000,
79
+ :getTimeToLiveSeconds => 1000,
80
+ :getTimeToIdleSeconds => 360,
81
+ :isOverflowToDisk => true,
82
+ :isEternal => false
83
+ }
84
+ expected.each do |key, value|
85
+ assert_equal(value, cache.send(key))
86
+ end
87
+ end
88
+
89
+ must 'have valid sampleCache2 configuration' do
90
+ cache = @config.getCacheConfigurations['sampleCache2']
91
+ expected = {
92
+ :getMaxElementsInMemory => 1000,
93
+ :isOverflowToDisk => false,
94
+ :isEternal => true,
95
+ :isDiskPersistent => true
96
+ }
97
+ expected.each do |key, value|
98
+ assert_equal(value, cache.send(key))
99
+ end
100
+ end
101
+
102
+ must 'have valid sampleCacheWithCacheConfigurations configuration' do
103
+ cache = @config.getCacheConfigurations['sampleCacheWithCacheConfigurations']
104
+ expected = {
105
+ :getMaxElementsInMemory => 10,
106
+ :isEternal => false,
107
+ :getTimeToIdleSeconds => 100,
108
+ :getTimeToLiveSeconds => 100,
109
+ :isOverflowToDisk => false
110
+ }
111
+ expected.each do |key, value|
112
+ assert_equal(value, cache.send(key))
113
+ end
114
+ end
115
+
116
+ must 'have 2 event listeners in sampleCacheWithCacheConfigurations' do
117
+ cache = @config.getCacheConfigurations['sampleCacheWithCacheConfigurations']
118
+ assert_equal(2, cache.getCacheEventListenerConfigurations.size)
119
+ expected = {
120
+ :getFullyQualifiedClassPath => 'net.sf.ehcache.distribution.RMICacheReplicatorFactory',
121
+ :getProperties => "replicateAsynchronously=false, replicatePuts=false, replicatePutsViaCopy=false, replicateUpdates=true, replicateUpdatesViaCopy=true, replicateRemovals=false"
122
+ }
123
+ cache.getCacheEventListenerConfigurations.each do |event_listener|
124
+ expected.each do |key, value|
125
+ assert_equal(value, event_listener.send(key))
126
+ end
127
+ end
128
+ end
129
+
130
+ must 'have valid bootstrap loader in sampleCacheWithCacheConfigurations' do
131
+ cache = @config.getCacheConfigurations['sampleCacheWithCacheConfigurations']
132
+ assert_not_nil(cache.getBootstrapCacheLoaderFactoryConfiguration)
133
+ expected = {
134
+ :getFullyQualifiedClassPath => "net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory",
135
+ :getProperties => "bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000",
136
+ :getPropertySeparator => ","
137
+ }
138
+ bootstrap_loader = cache.getBootstrapCacheLoaderFactoryConfiguration
139
+ expected.each do |key, value|
140
+ assert_equal(value, bootstrap_loader.send(key))
141
+ end
142
+ end
143
+
144
+ private
145
+
146
+ def assert_factory_configuration_equals(factory, values)
147
+ assert_not_nil(factory)
148
+ assert_kind_of(Hash, values)
149
+ if values.has_key?(:class)
150
+ assert_equal(values[:class], factory.getFullyQualifiedClassPath)
151
+ end
152
+ if values.has_key?(:properties)
153
+ assert_equal(values[:properties], factory.getProperties)
154
+ end
155
+ if values.has_key?(:property_separator)
156
+ assert_equal(values[:property_separator], factory.getPropertySeparator)
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,141 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
+ <title>
8
+ ehcache
9
+ </title>
10
+ <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
+ <style>
12
+
13
+ </style>
14
+ <script type="text/javascript">
15
+ window.onload = function() {
16
+ settings = {
17
+ tl: { radius: 10 },
18
+ tr: { radius: 10 },
19
+ bl: { radius: 10 },
20
+ br: { radius: 10 },
21
+ antiAlias: true,
22
+ autoPad: true,
23
+ validTags: ["div"]
24
+ }
25
+ var versionBox = new curvyCorners(settings, document.getElementById("version"));
26
+ versionBox.applyCornersToAll();
27
+ }
28
+ </script>
29
+ </head>
30
+ <body>
31
+ <div id="main">
32
+
33
+ <h1>ehcache</h1>
34
+ <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/ehcache"; return false'>
35
+ <p>Get Version</p>
36
+ <a href="http://rubyforge.org/projects/ehcache" class="numbers">0.0.1</a>
37
+ </div>
38
+ <h1>&#x2192; &#8216;ehcache&#8217;</h1>
39
+
40
+
41
+ <h2>What</h2>
42
+
43
+
44
+ <h2>Installing</h2>
45
+
46
+
47
+ <p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">ehcache</span></pre></p>
48
+
49
+
50
+ <h2>The basics</h2>
51
+
52
+
53
+ <h2>Demonstration of usage</h2>
54
+
55
+
56
+ <h2>Forum</h2>
57
+
58
+
59
+ <p><a href="http://groups.google.com/group/ehcache">http://groups.google.com/group/ehcache</a></p>
60
+
61
+
62
+ <p><span class="caps">TODO</span> &#8211; create Google Group &#8211; ehcache</p>
63
+
64
+
65
+ <h2>How to submit patches</h2>
66
+
67
+
68
+ <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
69
+
70
+
71
+ <p><span class="caps">TODO</span> &#8211; pick <span class="caps">SVN</span> or Git instructions</p>
72
+
73
+
74
+ <p>The trunk repository is <code>svn://rubyforge.org/var/svn/ehcache/trunk</code> for anonymous access.</p>
75
+
76
+
77
+ <p><span class="caps">OOOORRRR</span></p>
78
+
79
+
80
+ <p>You can fetch the source from either:</p>
81
+
82
+
83
+ <ul>
84
+ <li>rubyforge: <span class="caps">MISSING IN ACTION</span></li>
85
+ </ul>
86
+
87
+
88
+ <p><span class="caps">TODO</span> &#8211; You can not created a RubyForge project, OR have not run <code>rubyforge config</code>
89
+ yet to refresh your local rubyforge data with this projects&#8217; id information.</p>
90
+
91
+
92
+ <p>When you do this, this message will magically disappear!</p>
93
+
94
+
95
+ <p>Or you can hack website/index.txt and make it all go away!!</p>
96
+
97
+
98
+ <ul>
99
+ <li>github: <a href="http://github.com/GITHUB_USERNAME/ehcache/tree/master">http://github.com/GITHUB_USERNAME/ehcache/tree/master</a></li>
100
+ </ul>
101
+
102
+
103
+ <pre>git clone git://github.com/GITHUB_USERNAME/ehcache.git</pre>
104
+
105
+ <p><span class="caps">TODO</span> &#8211; add &#8220;github_username: username&#8221; to ~/.rubyforge/user-config.yml and newgem will reuse it for future projects.</p>
106
+
107
+
108
+ <ul>
109
+ <li>gitorious: <a href="git://gitorious.org/ehcache/mainline.git">git://gitorious.org/ehcache/mainline.git</a></li>
110
+ </ul>
111
+
112
+
113
+ <pre>git clone git://gitorious.org/ehcache/mainline.git</pre>
114
+
115
+ <h3>Build and test instructions</h3>
116
+
117
+
118
+ <pre>cd ehcache
119
+ rake test
120
+ rake install_gem</pre>
121
+
122
+ <h2>License</h2>
123
+
124
+
125
+ <p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
126
+
127
+
128
+ <h2>Contact</h2>
129
+
130
+
131
+ <p>Comments are welcome. Send an email to <a href="mailto:FIXME"><span class="caps">FIXME</span> full name</a> email via the <a href="http://groups.google.com/group/ehcache">forum</a></p>
132
+ <p class="coda">
133
+ <a href="FIXME email">FIXME full name</a>, 5th June 2008<br>
134
+ Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
135
+ </p>
136
+ </div>
137
+
138
+ <!-- insert site tracking codes here, like Google Urchin -->
139
+
140
+ </body>
141
+ </html>