001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.processor.idempotent;
018    
019    import java.util.Map;
020    
021    import org.apache.camel.spi.IdempotentRepository;
022    import org.apache.camel.util.LRUCache;
023    
024    /**
025     * A memory based implementation of {@link org.apache.camel.spi.IdempotentRepository}. 
026     * <p/>
027     * Care should be taken to use a suitable underlying {@link Map} to avoid this class being a
028     * memory leak.
029     *
030     * @version $Revision: 13190 $
031     */
032    public class MemoryIdempotentRepository implements IdempotentRepository<String> {
033    
034        private Map<String, Object> cache;
035    
036        public MemoryIdempotentRepository() {
037            this.cache = new LRUCache<String, Object>(1000);
038        }
039    
040        public MemoryIdempotentRepository(Map<String, Object> set) {
041            this.cache = set;
042        }
043    
044        /**
045         * Creates a new memory based repository using a {@link LRUCache}
046         * with a default of 1000 entries in the cache.
047         */
048        public static IdempotentRepository<String> memoryIdempotentRepository() {
049            return new MemoryIdempotentRepository();
050        }
051    
052        /**
053         * Creates a new memory based repository using a {@link LRUCache}.
054         *
055         * @param cacheSize  the cache size
056         */
057        public static IdempotentRepository<String> memoryIdempotentRepository(int cacheSize) {
058            return memoryIdempotentRepository(new LRUCache<String, Object>(cacheSize));
059        }
060    
061        /**
062         * Creates a new memory based repository using the given {@link Map} to
063         * use to store the processed message ids.
064         * <p/>
065         * Care should be taken to use a suitable underlying {@link Map} to avoid this class being a
066         * memory leak.
067         *
068         * @param cache  the cache
069         */
070        public static IdempotentRepository<String> memoryIdempotentRepository(Map<String, Object> cache) {
071            return new MemoryIdempotentRepository(cache);
072        }
073    
074        public boolean add(String messageId) {
075            synchronized (cache) {
076                if (cache.containsKey(messageId)) {
077                    return false;
078                } else {
079                    cache.put(messageId, messageId);
080                    return true;
081                }
082            }
083        }
084    
085        public boolean contains(String key) {
086            synchronized (cache) {
087                return cache.containsKey(key);
088            }
089        }
090    
091        public boolean remove(String key) {
092            synchronized (cache) {
093                return cache.remove(key) != null;
094            }
095        }
096    
097        public boolean confirm(String key) {
098            // noop
099            return true;
100        }
101    
102        public Map<String, Object> getCache() {
103            return cache;
104        }
105    
106        public void setCache(Map<String, Object> cache) {
107            this.cache = cache;
108        }
109    }