001: /**
002: * Copyright 2003-2007 Luck Consulting Pty Ltd
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */package net.sf.ehcache.distribution;
016:
017: import net.sf.ehcache.event.CacheEventListener;
018: import net.sf.ehcache.event.CacheEventListenerFactory;
019: import net.sf.ehcache.util.PropertyUtil;
020:
021: import java.util.Properties;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: /**
027: * Creates an RMICacheReplicator using properties. Config lines look like:
028: * <pre><cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
029: * properties="
030: * replicateAsynchronously=true,
031: * replicatePuts=true
032: * replicateUpdates=true
033: * replicateUpdatesViaCopy=true
034: * replicateRemovals=true
035: * "/></pre>
036: *
037: * @author <a href="mailto:gluck@thoughtworks.com">Greg Luck</a>
038: * @version $Id: RMICacheReplicatorFactory.java 519 2007-07-27 07:11:45Z gregluck $
039: */
040: public class RMICacheReplicatorFactory extends
041: CacheEventListenerFactory {
042:
043: /**
044: * A default for the amount of time the replication thread sleeps after it detects the replicationQueue is empty
045: * before checking again.
046: */
047: protected static final int DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS = 1000;
048:
049: private static final Log LOG = LogFactory
050: .getLog(RMICacheReplicatorFactory.class.getName());
051: private static final String REPLICATE_PUTS = "replicatePuts";
052: private static final String REPLICATE_UPDATES = "replicateUpdates";
053: private static final String REPLICATE_UPDATES_VIA_COPY = "replicateUpdatesViaCopy";
054: private static final String REPLICATE_REMOVALS = "replicateRemovals";
055: private static final String REPLICATE_ASYNCHRONOUSLY = "replicateAsynchronously";
056: private static final String ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS = "asynchronousReplicationIntervalMillis";
057: private static final int MINIMUM_REASONABLE_INTERVAL = 10;
058:
059: /**
060: * Create a <code>CacheEventListener</code> which is also a CacheReplicator.
061: * <p/>
062: * The defaults if properties are not specified are:
063: * <ul>
064: * <li>replicatePuts=true
065: * <li>replicateUpdates=true
066: * <li>replicateUpdatesViaCopy=true
067: * <li>replicateRemovals=true;
068: * <li>replicateAsynchronously=true
069: * <li>asynchronousReplicationIntervalMillis=1000
070: * </ul>
071: *
072: * @param properties implementation specific properties. These are configured as comma
073: * separated name value pairs in ehcache.xml e.g.
074: * <p/>
075: * <code>
076: * <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
077: * properties="
078: * replicateAsynchronously=true,
079: * replicatePuts=true
080: * replicateUpdates=true
081: * replicateUpdatesViaCopy=true
082: * replicateRemovals=true
083: * asynchronousReplicationIntervalMillis=1000
084: * "/></code>
085: * @return a constructed CacheEventListener
086: */
087: public final CacheEventListener createCacheEventListener(
088: Properties properties) {
089: boolean replicatePuts = extractReplicatePuts(properties);
090: boolean replicateUpdates = extractReplicateUpdates(properties);
091: boolean replicateUpdatesViaCopy = extractReplicateUpdatesViaCopy(properties);
092: boolean replicateRemovals = extractReplicateRemovals(properties);
093: boolean replicateAsynchronously = extractReplicateAsynchronously(properties);
094: int asynchronousReplicationIntervalMillis = extractReplicationIntervalMilis(properties);
095:
096: if (replicateAsynchronously) {
097: return new RMIAsynchronousCacheReplicator(replicatePuts,
098: replicateUpdates, replicateUpdatesViaCopy,
099: replicateRemovals,
100: asynchronousReplicationIntervalMillis);
101: } else {
102: return new RMISynchronousCacheReplicator(replicatePuts,
103: replicateUpdates, replicateUpdatesViaCopy,
104: replicateRemovals);
105: }
106: }
107:
108: /**
109: * Extracts the value of asynchronousReplicationIntervalMillis. Sets it to 1000ms if
110: * either not set or there is a problem parsing the number
111: * @param properties
112: */
113: protected int extractReplicationIntervalMilis(Properties properties) {
114: int asynchronousReplicationIntervalMillis;
115: String asynchronousReplicationIntervalMillisString = PropertyUtil
116: .extractAndLogProperty(
117: ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS,
118: properties);
119: if (asynchronousReplicationIntervalMillisString != null) {
120: try {
121: int asynchronousReplicationIntervalMillisCandidate = Integer
122: .parseInt(asynchronousReplicationIntervalMillisString);
123: if (asynchronousReplicationIntervalMillisCandidate < MINIMUM_REASONABLE_INTERVAL) {
124: LOG
125: .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
133: .warn("Number format exception trying to set asynchronousReplicationIntervalMillis. "
134: + "Using the default instead. String value was: '"
135: + asynchronousReplicationIntervalMillisString
136: + "'");
137: asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
138: }
139: } else {
140: asynchronousReplicationIntervalMillis = DEFAULT_ASYNCHRONOUS_REPLICATION_INTERVAL_MILLIS;
141: }
142: return asynchronousReplicationIntervalMillis;
143: }
144:
145: /**
146: * Extracts the value of replicateAsynchronously from the properties
147: * @param properties
148: */
149: protected boolean extractReplicateAsynchronously(
150: Properties properties) {
151: boolean replicateAsynchronously;
152: String replicateAsynchronouslyString = PropertyUtil
153: .extractAndLogProperty(REPLICATE_ASYNCHRONOUSLY,
154: properties);
155: if (replicateAsynchronouslyString != null) {
156: replicateAsynchronously = PropertyUtil
157: .parseBoolean(replicateAsynchronouslyString);
158: } else {
159: replicateAsynchronously = true;
160: }
161: return replicateAsynchronously;
162: }
163:
164: /**
165: * Extracts the value of replicateRemovals from the properties
166: * @param properties
167: */
168: protected boolean extractReplicateRemovals(Properties properties) {
169: boolean replicateRemovals;
170: String replicateRemovalsString = PropertyUtil
171: .extractAndLogProperty(REPLICATE_REMOVALS, properties);
172: if (replicateRemovalsString != null) {
173: replicateRemovals = PropertyUtil
174: .parseBoolean(replicateRemovalsString);
175: } else {
176: replicateRemovals = true;
177: }
178: return replicateRemovals;
179: }
180:
181: /**
182: * Extracts the value of replicateUpdatesViaCopy from the properties
183: * @param properties
184: */
185: protected boolean extractReplicateUpdatesViaCopy(
186: Properties properties) {
187: boolean replicateUpdatesViaCopy;
188: String replicateUpdatesViaCopyString = PropertyUtil
189: .extractAndLogProperty(REPLICATE_UPDATES_VIA_COPY,
190: properties);
191: if (replicateUpdatesViaCopyString != null) {
192: replicateUpdatesViaCopy = PropertyUtil
193: .parseBoolean(replicateUpdatesViaCopyString);
194: } else {
195: replicateUpdatesViaCopy = true;
196: }
197: return replicateUpdatesViaCopy;
198: }
199:
200: /**
201: * Extracts the value of replicateUpdates from the properties
202: * @param properties
203: */
204: protected boolean extractReplicateUpdates(Properties properties) {
205: boolean replicateUpdates;
206: String replicateUpdatesString = PropertyUtil
207: .extractAndLogProperty(REPLICATE_UPDATES, properties);
208: if (replicateUpdatesString != null) {
209: replicateUpdates = PropertyUtil
210: .parseBoolean(replicateUpdatesString);
211: } else {
212: replicateUpdates = true;
213: }
214: return replicateUpdates;
215: }
216:
217: /**
218: * Extracts the value of replicatePuts from the properties
219: * @param properties
220: */
221: protected boolean extractReplicatePuts(Properties properties) {
222: boolean replicatePuts;
223: String replicatePutsString = PropertyUtil
224: .extractAndLogProperty(REPLICATE_PUTS, properties);
225: if (replicatePutsString != null) {
226: replicatePuts = PropertyUtil
227: .parseBoolean(replicatePutsString);
228: } else {
229: replicatePuts = true;
230: }
231: return replicatePuts;
232: }
233:
234: }
|