001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.activemq.tool;
019
020 import java.util.ArrayList;
021 import java.util.List;
022
023 import javax.jms.JMSException;
024 import javax.jms.Message;
025 import javax.jms.MessageListener;
026
027
028 import org.apache.commons.logging.Log;
029 import org.apache.commons.logging.LogFactory;
030
031 /**
032 * A simple container of messages for performing testing and rendezvous style
033 * code. You can use this class a {@link MessageListener} and then make
034 * assertions about how many messages it has received allowing a certain maximum
035 * amount of time to ensure that the test does not hang forever.
036 * <p/>
037 * Also you can chain these instances together with the
038 * {@link #setParent(MessageListener)} method so that you can aggregate the
039 * total number of messages consumed across a number of consumers.
040 *
041 * @version $Revision: 1.6 $
042 */
043 public class MemMessageIdList implements MessageListener {
044
045 protected static final Log log = LogFactory.getLog(MemMessageIdList.class);
046
047 private List messageIds = new ArrayList();
048 private Object semaphore;
049 private boolean verbose;
050 private MessageListener parent;
051 private long maximumDuration = 15000L;
052
053 public MemMessageIdList() {
054 this(new Object());
055 }
056
057 public MemMessageIdList(Object semaphore) {
058 this.semaphore = semaphore;
059 }
060
061 public boolean equals(Object that) {
062 if (that instanceof MemMessageIdList) {
063 MemMessageIdList thatListMem = (MemMessageIdList) that;
064 return getMessageIds().equals(thatListMem.getMessageIds());
065 }
066 return false;
067 }
068
069 public int hashCode() {
070 synchronized (semaphore) {
071 return messageIds.hashCode() + 1;
072 }
073 }
074
075 public String toString() {
076 synchronized (semaphore) {
077 return messageIds.toString();
078 }
079 }
080
081 /**
082 * @return all the messages on the list so far, clearing the buffer
083 */
084 public List flushMessages() {
085 synchronized (semaphore) {
086 List answer = new ArrayList(messageIds);
087 messageIds.clear();
088 return answer;
089 }
090 }
091
092 public synchronized List getMessageIds() {
093 synchronized (semaphore) {
094 return new ArrayList(messageIds);
095 }
096 }
097
098 public void onMessage(Message message) {
099 String id = null;
100 try {
101 id = message.getJMSMessageID();
102 synchronized (semaphore) {
103 messageIds.add(id);
104 semaphore.notifyAll();
105 }
106 if (verbose) {
107 log.info("Received message: " + message);
108 }
109 } catch (JMSException e) {
110 e.printStackTrace();
111 }
112 if (parent != null) {
113 parent.onMessage(message);
114 }
115 }
116
117 public int getMessageCount() {
118 synchronized (semaphore) {
119 return messageIds.size();
120 }
121 }
122
123 public void waitForMessagesToArrive(int messageCount) {
124 log.info("Waiting for " + messageCount + " message(s) to arrive");
125
126 long start = System.currentTimeMillis();
127
128 for (int i = 0; i < messageCount; i++) {
129 try {
130 if (hasReceivedMessages(messageCount)) {
131 break;
132 }
133 long duration = System.currentTimeMillis() - start;
134 if (duration >= maximumDuration) {
135 break;
136 }
137 synchronized (semaphore) {
138 semaphore.wait(maximumDuration - duration);
139 }
140 } catch (InterruptedException e) {
141 log.info("Caught: " + e);
142 }
143 }
144 long end = System.currentTimeMillis() - start;
145
146 log.info("End of wait for " + end + " millis and received: " + getMessageCount() + " messages");
147 }
148
149
150 public boolean hasReceivedMessage() {
151 return getMessageCount() == 0;
152 }
153
154 public boolean hasReceivedMessages(int messageCount) {
155 return getMessageCount() >= messageCount;
156 }
157
158 public boolean isVerbose() {
159 return verbose;
160 }
161
162 public void setVerbose(boolean verbose) {
163 this.verbose = verbose;
164 }
165
166 public MessageListener getParent() {
167 return parent;
168 }
169
170 /**
171 * Allows a parent listener to be specified such as to aggregate messages
172 * consumed across consumers
173 */
174 public void setParent(MessageListener parent) {
175 this.parent = parent;
176 }
177
178 }