1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: AbstractConsumerMessageHandle.java,v 1.2 2005/08/30 07:26:49 tanderson Exp $
44 */
45 package org.exolab.jms.messagemgr;
46
47 import java.sql.Connection;
48 import javax.jms.JMSException;
49 import javax.jms.MessageConsumer;
50
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53
54 import org.exolab.jms.client.JmsDestination;
55 import org.exolab.jms.message.MessageImpl;
56 import org.exolab.jms.persistence.DatabaseService;
57 import org.exolab.jms.persistence.PersistenceException;
58
59
60 /***
61 * A {@link MessageHandle} for a consumer.
62 *
63 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
64 * @version $Revision: 1.2 $ $Date: 2005/08/30 07:26:49 $
65 */
66 abstract class AbstractConsumerMessageHandle implements MessageHandle {
67
68 /***
69 * The underlying handle.
70 */
71 private final MessageHandle _handle;
72
73 /***
74 * The consumer's identity.
75 */
76 private long _consumerId;
77
78 /***
79 * The consumer's persistent identity.
80 */
81 private final String _persistentId;
82
83 /***
84 * Detetmines if this handle is persistent.
85 */
86 private boolean _persistent;
87
88 /***
89 * The logger.
90 */
91 private static final Log _log
92 = LogFactory.getLog(AbstractConsumerMessageHandle.class);
93
94
95 /***
96 * Construct a new <code>AbstractConsumerMessageHandle</code>.
97 *
98 * @param handle the underlying handle
99 * @param consumer the consumer of the handle
100 * @throws JMSException if the underlying message can't be referenced
101 */
102 public AbstractConsumerMessageHandle(MessageHandle handle,
103 ConsumerEndpoint consumer)
104 throws JMSException {
105 this(handle, consumer.getId(), consumer.getPersistentId());
106 }
107
108 /***
109 * Construct a new <code>AbstractConsumerMessageHandle</code>.
110 *
111 * @param handle the underlying handle
112 * @param persistentId the persistent identity of the consumer. May be
113 * <code>null</code>
114 * @throws JMSException if the underlying message can't be referenced
115 */
116 public AbstractConsumerMessageHandle(MessageHandle handle,
117 String persistentId)
118 throws JMSException {
119 this(handle, -1L, persistentId);
120 }
121
122 /***
123 * Construct a new <code>AbstractConsumerMessageHandle</code>.
124 *
125 * @param handle the underlying handle
126 * @param consumerId the consumer identifier
127 * @param persistentId the persistent identity of the consumer. May be
128 * <code>null</code>
129 * @throws JMSException if the underlying message can't be referenced
130 */
131 protected AbstractConsumerMessageHandle(MessageHandle handle, long consumerId,
132 String persistentId)
133 throws JMSException {
134 if (handle == null) {
135 throw new IllegalArgumentException("Argument 'handle' is null");
136 }
137 _handle = handle;
138 _consumerId = consumerId;
139 _persistentId = persistentId;
140 _handle.getMessageRef().reference();
141 }
142
143 /***
144 * Returns the message identifier.
145 *
146 * @return the message identifier
147 */
148 public String getMessageId() {
149 return _handle.getMessageId();
150 }
151
152 /***
153 * Indicates if a message has been delivered to a {@link MessageConsumer},
154 * but not acknowledged.
155 *
156 * @param delivered if <code>true</code> indicates that an attempt has been
157 * made to deliver the message
158 */
159 public void setDelivered(boolean delivered) {
160 _handle.setDelivered(delivered);
161 }
162
163 /***
164 * Returns if an attempt has already been made to deliver the message.
165 *
166 * @return <code>true</code> if delivery has been attempted
167 */
168 public boolean getDelivered() {
169 return _handle.getDelivered();
170 }
171
172 /***
173 * Returns the priority of the message.
174 *
175 * @return the message priority
176 */
177 public int getPriority() {
178 return _handle.getPriority();
179 }
180
181 /***
182 * Returns the time that the corresponding message was accepted, in
183 * milliseconds.
184 *
185 * @return the time that the corresponding message was accepted
186 */
187 public long getAcceptedTime() {
188 return _handle.getAcceptedTime();
189 }
190
191 /***
192 * Returns the time that the message expires.
193 *
194 * @return the expiry time
195 */
196 public long getExpiryTime() {
197 return _handle.getExpiryTime();
198 }
199
200 /***
201 * Determines if the message has expired.
202 *
203 * @return <code>true</code> if the message has expired, otherwise
204 * <code>false</code>
205 */
206 public boolean hasExpired() {
207 return _handle.hasExpired();
208 }
209
210 /***
211 * Returns the handle's sequence number.
212 *
213 * @return the sequence number
214 */
215 public long getSequenceNumber() {
216 return _handle.getSequenceNumber();
217 }
218
219 /***
220 * Returns the message destination.
221 *
222 * @return the message destination
223 */
224 public JmsDestination getDestination() {
225 return _handle.getDestination();
226 }
227
228 /***
229 * Returns the consumer identity associated with the message.
230 *
231 * @return the consumer identity associated with the message, or *
232 * <code>-1</code> if the message isn't associated with a consumer
233 */
234 public long getConsumerId() {
235 return _consumerId;
236 }
237
238 /***
239 * Returns the name of the consumer endpoint that owns this handle. If it is
240 * set, then a consumer owns it exclusively, otherwise the handle may be
241 * shared across a number of consumers
242 *
243 * @return the consumer name, or <code>null</code>
244 */
245 public String getConsumerPersistentId() {
246 return _persistentId;
247 }
248
249 /***
250 * Returns the connection identity associated with the message.
251 *
252 * @return the connection identity associated with the message, or
253 * <code>-1</code> if the message isn't associated with a
254 * connection
255 */
256 public long getConnectionId() {
257 return _handle.getConnectionId();
258 }
259
260 /***
261 * Determines if the handle is persistent.
262 *
263 * @return <code>true</code> if the handle is persistent; otherwise
264 * <code>false</code>
265 */
266 public boolean isPersistent() {
267 return _persistent;
268 }
269
270 /***
271 * Returns the message associated with this handle.
272 *
273 * @return the associated message, or <code>null</code> if the handle is no
274 * longer valid
275 * @throws JMSException for any error
276 */
277 public MessageImpl getMessage() throws JMSException {
278 return _handle.getMessage();
279 }
280
281 /***
282 * Makes the handle persistent.
283 *
284 * @throws JMSException for any persistence error
285 */
286 public void add() throws JMSException {
287 try {
288 DatabaseService service = DatabaseService.getInstance();
289 Connection connection = service.getConnection();
290 service.getAdapter().addMessageHandle(connection, this);
291 } catch (PersistenceException exception) {
292 final String msg = "Failed to make handle persistent";
293 _log.error(msg, exception);
294 throw new JMSException(msg + ": " + exception.getMessage());
295 }
296 _persistent = true;
297 }
298
299 /***
300 * Update the persistent handle.
301 *
302 * @throws JMSException for any persistence error
303 */
304 public void update() throws JMSException {
305 try {
306 DatabaseService service = DatabaseService.getInstance();
307 Connection connection = service.getConnection();
308 service.getAdapter().updateMessageHandle(connection, this);
309 } catch (PersistenceException exception) {
310 final String msg = "Failed to update persistent handle";
311 _log.error(msg, exception);
312 throw new JMSException(msg + ": " + exception.getMessage());
313 }
314 }
315
316 /***
317 * Destroy this handle. If this is the last handle to reference the message,
318 * also destroys the message
319 *
320 * @throws JMSException for any error
321 */
322 public void destroy() throws JMSException {
323 if (_persistent) {
324 try {
325 DatabaseService service = DatabaseService.getInstance();
326 Connection connection = service.getConnection();
327 service.getAdapter().removeMessageHandle(connection, this);
328 } catch (PersistenceException exception) {
329 final String msg = "Failed to destroy persistent handle";
330 _log.error(msg, exception);
331 throw new JMSException(msg + ": " + exception.getMessage());
332 }
333 }
334 _handle.destroy();
335 _persistent = false;
336 }
337
338 /***
339 * Release the message handle back to the cache, to recover an unsent or
340 * unacknowledged message.
341 *
342 * @throws JMSException for any error
343 */
344 public void release() throws JMSException {
345 if (_handle instanceof AbstractMessageHandle) {
346 ((AbstractMessageHandle) _handle).release(this);
347 } else {
348 _handle.release();
349 }
350 }
351
352 /***
353 * Returns the message reference.
354 *
355 * @return the message reference, or <code>null</code> if none has been set
356 */
357 public MessageRef getMessageRef() {
358 return _handle.getMessageRef();
359 }
360
361 /***
362 * Set the consumer identifier.
363 *
364 * @param consumerId the consumer identifier
365 */
366 protected void setConsumerId(long consumerId) {
367 _consumerId = consumerId;
368 }
369
370 /***
371 * Indicates if the handle is persistent.
372 *
373 * @param persistent if <code>true</code> indicates the handle is
374 * persistent
375 */
376 protected void setPersistent(boolean persistent) {
377 _persistent = persistent;
378 }
379
380 }
381