View Javadoc

1   /**
2    *  Copyright 2003-2007 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.distribution;
18  
19  import net.sf.ehcache.event.CacheEventListener;
20  import net.sf.ehcache.event.CacheEventListenerFactory;
21  import net.sf.ehcache.util.PropertyUtil;
22  
23  import java.util.Properties;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  /**
29   * Creates an RMICacheReplicator using properties. Config lines look like:
30   * <pre>&lt;cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
31   * properties="
32   * replicateAsynchronously=true,
33   * replicatePuts=true
34   * replicateUpdates=true
35   * replicateUpdatesViaCopy=true
36   * replicateRemovals=true
37   * "/&gt;</pre>
38   *
39   * @author <a href="mailto:gluck@thoughtworks.com">Greg Luck</a>
40   * @version $Id: RMICacheReplicatorFactory.java 512 2007-07-10 09:18:45Z gregluck $
41   */
42  public class RMICacheReplicatorFactory extends CacheEventListenerFactory {
43  
44      /**
45       * A default for the amount of time the replication thread sleeps after it detects the replicationQueue is empty
46       * before checking again.
47       */
48      protected static final int DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS = 1000;
49  
50      private static final Log LOG = LogFactory.getLog(RMICacheReplicatorFactory.class.getName());
51      private static final String REPLICATE_PUTS = "replicatePuts";
52      private static final String REPLICATE_UPDATES = "replicateUpdates";
53      private static final String REPLICATE_UPDATES_VIA_COPY = "replicateUpdatesViaCopy";
54      private static final String REPLICATE_REMOVALS = "replicateRemovals";
55      private static final String REPLICATE_ASYNCHRONOUSLY = "replicateAsynchronously";
56      private static final String ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS = "asynchronousReplicationIntervalMillis";
57      private static final int MINIMUM_REASONABLE_INTERVAL = 10;
58  
59      /**
60       * Create a <code>CacheEventListener</code> which is also a CacheReplicator.
61       * <p/>
62       * The defaults if properties are not specified are:
63       * <ul>
64       * <li>replicatePuts=true
65       * <li>replicateUpdates=true
66       * <li>replicateUpdatesViaCopy=true
67       * <li>replicateRemovals=true;
68       * <li>replicateAsynchronously=true
69       * <li>asynchronousReplicationIntervalMillis=1000
70       * </ul>
71       *
72       * @param properties implementation specific properties. These are configured as comma
73       *                   separated name value pairs in ehcache.xml e.g.
74       *                   <p/>
75       *                   <code>
76       *                   &lt;cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
77       *                   properties="
78       *                   replicateAsynchronously=true,
79       *                   replicatePuts=true
80       *                   replicateUpdates=true
81       *                   replicateUpdatesViaCopy=true
82       *                   replicateRemovals=true
83       *                   asynchronousReplicationIntervalMillis=1000
84       *                   "/&gt;</code>
85       * @return a constructed CacheEventListener
86       */
87      public final CacheEventListener createCacheEventListener(Properties properties) {
88          boolean replicatePuts = extractReplicatePuts(properties);
89          boolean replicateUpdates = extractReplicateUpdates(properties);
90          boolean replicateUpdatesViaCopy = extractReplicateUpdatesViaCopy(properties);
91          boolean replicateRemovals = extractReplicateRemovals(properties);
92          boolean replicateAsynchronously = extractReplicateAsynchronously(properties);
93          int asynchronousReplicationIntervalMillis = extractReplicationIntervalMilis(properties);
94  
95          if (replicateAsynchronously) {
96              return new RMIAsynchronousCacheReplicator(
97                      replicatePuts,
98                      replicateUpdates,
99                      replicateUpdatesViaCopy,
100                     replicateRemovals,
101                     asynchronousReplicationIntervalMillis);
102         } else {
103             return new RMISynchronousCacheReplicator(
104                     replicatePuts,
105                     replicateUpdates,
106                     replicateUpdatesViaCopy,
107                     replicateRemovals);
108         }
109     }
110 
111     /**
112      * Extracts the value of asynchronousReplicationIntervalMillis. Sets it to 1000ms if
113      * either not set or there is a problem parsing the number
114      * @param properties
115      */
116     protected int extractReplicationIntervalMilis(Properties properties) {
117         int asynchronousReplicationIntervalMillis;
118         String asynchronousReplicationIntervalMillisString =
119                 PropertyUtil.extractAndLogProperty(ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS, properties);
120         if (asynchronousReplicationIntervalMillisString != null) {
121             try {
122                 int asynchronousReplicationIntervalMillisCandidate =
123                         Integer.parseInt(asynchronousReplicationIntervalMillisString);
124                 if (asynchronousReplicationIntervalMillisCandidate < MINIMUM_REASONABLE_INTERVAL) {
125                     LOG.warn("Trying to set the asynchronousReplicationIntervalMillis to an unreasonable number." +
126                             " Using the default instead.");
127                     asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
128                 } else {
129                     asynchronousReplicationIntervalMillis = asynchronousReplicationIntervalMillisCandidate;
130                 }
131             } catch (NumberFormatException e) {
132                 LOG.warn("Number format exception trying to set asynchronousReplicationIntervalMillis. " +
133                         "Using the default instead. String value was: '" + asynchronousReplicationIntervalMillisString + "'");
134                 asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
135             }
136         } else {
137             asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
138         }
139         return asynchronousReplicationIntervalMillis;
140     }
141 
142     /**
143      * Extracts the value of replicateAsynchronously from the properties
144      * @param properties
145      */
146     protected boolean extractReplicateAsynchronously(Properties properties) {
147         boolean replicateAsynchronously;
148         String replicateAsynchronouslyString = PropertyUtil.extractAndLogProperty(REPLICATE_ASYNCHRONOUSLY, properties);
149         if (replicateAsynchronouslyString != null) {
150             replicateAsynchronously = PropertyUtil.parseBoolean(replicateAsynchronouslyString);
151         } else {
152             replicateAsynchronously = true;
153         }
154         return replicateAsynchronously;
155     }
156 
157     /**
158      * Extracts the value of replicateRemovals from the properties
159      * @param properties
160      */
161     protected boolean extractReplicateRemovals(Properties properties) {
162         boolean replicateRemovals;
163         String replicateRemovalsString = PropertyUtil.extractAndLogProperty(REPLICATE_REMOVALS, properties);
164         if (replicateRemovalsString != null) {
165             replicateRemovals = PropertyUtil.parseBoolean(replicateRemovalsString);
166         } else {
167             replicateRemovals = true;
168         }
169         return replicateRemovals;
170     }
171 
172     /**
173      * Extracts the value of replicateUpdatesViaCopy from the properties
174      * @param properties
175      */
176     protected boolean extractReplicateUpdatesViaCopy(Properties properties) {
177         boolean replicateUpdatesViaCopy;
178         String replicateUpdatesViaCopyString = PropertyUtil.extractAndLogProperty(REPLICATE_UPDATES_VIA_COPY, properties);
179         if (replicateUpdatesViaCopyString != null) {
180             replicateUpdatesViaCopy = PropertyUtil.parseBoolean(replicateUpdatesViaCopyString);
181         } else {
182             replicateUpdatesViaCopy = true;
183         }
184         return replicateUpdatesViaCopy;
185     }
186 
187     /**
188      * Extracts the value of replicateUpdates from the properties
189      * @param properties
190      */
191     protected boolean extractReplicateUpdates(Properties properties) {
192         boolean replicateUpdates;
193         String replicateUpdatesString = PropertyUtil.extractAndLogProperty(REPLICATE_UPDATES, properties);
194         if (replicateUpdatesString != null) {
195             replicateUpdates = PropertyUtil.parseBoolean(replicateUpdatesString);
196         } else {
197             replicateUpdates = true;
198         }
199         return replicateUpdates;
200     }
201 
202     /**
203      * Extracts the value of replicatePuts from the properties
204      * @param properties
205      */
206     protected boolean extractReplicatePuts(Properties properties) {
207         boolean replicatePuts;
208         String replicatePutsString = PropertyUtil.extractAndLogProperty(REPLICATE_PUTS, properties);
209         if (replicatePutsString != null) {
210             replicatePuts = PropertyUtil.parseBoolean(replicatePutsString);
211         } else {
212             replicatePuts = true;
213         }
214         return replicatePuts;
215     }
216 
217 
218 }