001    /** 
002     * 
003     * Copyright 2004 Protique Ltd
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * 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     **/
018    
019    package org.activemq;
020    
021    import java.util.LinkedHashMap;
022    
023    import javax.jms.JMSException;
024    import javax.jms.Message;
025    
026    import org.activemq.util.BitArrayBin;
027    import org.activemq.util.IdGenerator;
028    import org.activemq.util.LRUCache;
029    
030    /**
031     * Provides basic audit functions for Messages
032     *
033     * @version $Revision: 1.1.1.1 $
034     */
035    public class ActiveMQMessageAudit {
036        private static final int DEFAULT_WINDOW_SIZE = 1024;
037        private static final int MAXIMUM_PRODUCER_COUNT = 128;
038        private int windowSize;
039        private LinkedHashMap map;
040    
041        /**
042         * Default Constructor windowSize = 1024, maximumNumberOfProducersToTrack = 128
043         */
044        public ActiveMQMessageAudit() {
045            this(DEFAULT_WINDOW_SIZE, MAXIMUM_PRODUCER_COUNT);
046        }
047    
048        /**
049         * Construct a MessageAudit
050         *
051         * @param windowSize range of ids to track
052         * @param maximumNumberOfProducersToTrack
053         *                   number of producers expected in the system
054         */
055        public ActiveMQMessageAudit(int windowSize, final int maximumNumberOfProducersToTrack) {
056            this.windowSize = windowSize;
057            map = new LRUCache(maximumNumberOfProducersToTrack);
058        }
059    
060        /**
061         * Checks if this message has beeb seen before
062         *
063         * @param message
064         * @return true if the message is a duplicate
065         * @throws JMSException
066         */
067        public boolean isDuplicate(Message message) throws JMSException {
068           return isDuplicate(message.getJMSMessageID());
069        }
070    
071    
072        /**
073         * checks whether this messageId has been seen before and adds this messageId to the list
074         *
075         * @param id
076         * @return true if the message is a duplicate
077         */
078        public boolean isDuplicate(String id) {
079            boolean answer = false;
080            String seed = IdGenerator.getSeedFromId(id);
081            if (seed != null) {
082                BitArrayBin bab = (BitArrayBin) map.get(seed);
083                if (bab == null) {
084                    bab = new BitArrayBin(windowSize);
085                    map.put(seed, bab);
086                }
087                long index = IdGenerator.getCountFromId(id);
088                if (index >= 0) {
089                    answer = bab.setBit(index, true);
090                }
091            }
092            return answer;
093        }
094    }