/*
* JBoss, Home of Professional Open Source
* Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.messaging.jms.client;
import org.jboss.messaging.core.client.ClientMessage;
import org.jboss.messaging.core.client.ClientProducer;
import org.jboss.messaging.core.client.ClientSession;
import org.jboss.messaging.core.exception.MessagingException;
import org.jboss.messaging.core.logging.Logger;
import org.jboss.messaging.jms.JBossDestination;
import org.jboss.messaging.util.SimpleString;
import org.jboss.messaging.util.UUIDGenerator;
import javax.jms.BytesMessage;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.IllegalStateException;
import javax.jms.InvalidDestinationException;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueSender;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicPublisher;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author <a href="mailto:ovidiu@feodorov.com">Ovidiu Feodorov</a>
* @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a>
* @author <a href="mailto:ataylor@redhat.com">Andy Taylor</a>
* @version <tt>$Revision$</tt>
*
* $Id$
*/
public class JBossMessageProducer implements MessageProducer, QueueSender, TopicPublisher
{
// Constants -----------------------------------------------------
// Static --------------------------------------------------------
private static final Logger log = Logger.getLogger(JBossMessageProducer.class);
// Attributes ----------------------------------------------------
private JBossConnection jbossConn;
private final SimpleString connID;
private ClientProducer producer;
private boolean disableMessageID = false;
private boolean disableMessageTimestamp = false;
private int defaultPriority = 4;
private long defaultTimeToLive = 0;
private int defaultDeliveryMode = DeliveryMode.PERSISTENT;
private JBossDestination defaultDestination;
private final String messageIDPrefix;
private final AtomicLong sequenceNumber = new AtomicLong(0);
private ClientSession clientSession;
// Constructors --------------------------------------------------
public JBossMessageProducer(final JBossConnection jbossConn, final ClientProducer producer,
final JBossDestination defaultDestination, final ClientSession clientSession) throws JMSException
{
this.jbossConn = jbossConn;
this.connID = jbossConn.getUID();
this.producer = producer;
this.defaultDestination = defaultDestination;
this.clientSession = clientSession;
//TODO the UUID should be generated at the JMS Connection level,
// then session, producers & messages ID could be created using simple sequences
String uuid = UUIDGenerator.getInstance().generateSimpleStringUUID().toString();
messageIDPrefix = "ID:" + uuid + ":";
}
// MessageProducer implementation --------------------------------
public void setDisableMessageID(boolean value) throws JMSException
{
checkClosed();
disableMessageID = value;
}
public boolean getDisableMessageID() throws JMSException
{
checkClosed();
return disableMessageID;
}
public void setDisableMessageTimestamp(boolean value) throws JMSException
{
checkClosed();
disableMessageTimestamp = value;
}
public boolean getDisableMessageTimestamp() throws JMSException
{
checkClosed();
return disableMessageTimestamp;
}
public void setDeliveryMode(int deliveryMode) throws JMSException
{
checkClosed();
this.defaultDeliveryMode = deliveryMode;
}
public int getDeliveryMode() throws JMSException
{
checkClosed();
return this.defaultDeliveryMode;
}
public void setPriority(int defaultPriority) throws JMSException
{
checkClosed();
this.defaultPriority = defaultPriority;
}
public int getPriority() throws JMSException
{
checkClosed();
return defaultPriority;
}
public void setTimeToLive(long timeToLive) throws JMSException
{
checkClosed();
this.defaultTimeToLive = timeToLive;
}
public long getTimeToLive() throws JMSException
{
checkClosed();
return defaultTimeToLive;
}
public Destination getDestination() throws JMSException
{
checkClosed();
return defaultDestination;
}
public void close() throws JMSException
{
try
{
producer.close();
}
catch (MessagingException e)
{
throw JMSExceptionHelper.convertFromMessagingException(e);
}
}
public void send(Message message) throws JMSException
{
checkClosed();
message.setJMSDeliveryMode(defaultDeliveryMode);
message.setJMSPriority(defaultPriority);
doSend(message, defaultTimeToLive, null);
}
public void send(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException
{
checkClosed();
message.setJMSDeliveryMode(deliveryMode);
message.setJMSPriority(priority);
doSend(message, timeToLive, null);
}
public void send(Destination destination, Message message) throws JMSException
{
checkClosed();
if (destination != null && !(destination instanceof JBossDestination))
{
throw new InvalidDestinationException("Not a JBoss Destination:" + destination);
}
message.setJMSDeliveryMode(defaultDeliveryMode);
message.setJMSPriority(defaultPriority);
doSend(message, defaultTimeToLive, (JBossDestination)destination);
}
public void send(Destination destination,
Message message,
int deliveryMode,
int priority,
long timeToLive) throws JMSException
{
checkClosed();
if (destination != null && !(destination instanceof JBossDestination))
{
throw new InvalidDestinationException("Not a JBoss Destination:" + destination);
}
message.setJMSDeliveryMode(deliveryMode);
message.setJMSPriority(priority);
doSend(message, timeToLive, (JBossDestination)destination);
}
// TopicPublisher Implementation ---------------------------------
public Topic getTopic() throws JMSException
{
return (Topic)getDestination();
}
public void publish(Message message) throws JMSException
{
send(message);
}
public void publish(Topic topic, Message message) throws JMSException
{
send(topic, message);
}
public void publish(Message message, int deliveryMode, int priority, long timeToLive)
throws JMSException
{
send(message, deliveryMode, priority, timeToLive);
}
public void publish(Topic topic, Message message, int deliveryMode,
int priority, long timeToLive) throws JMSException
{
send(topic, message, deliveryMode, priority, timeToLive);
}
// QueueSender Implementation ------------------------------------
public void send(Queue queue, Message message) throws JMSException
{
send((Destination)queue, message);
}
public void send(Queue queue, Message message, int deliveryMode, int priority,
long timeToLive) throws JMSException
{
send((Destination)queue, message, deliveryMode, priority, timeToLive);
}
public Queue getQueue() throws JMSException
{
return (Queue)getDestination();
}
// Public --------------------------------------------------------
public String toString()
{
return "JBossMessageProducer->" + producer;
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
private void doSend(Message message, long timeToLive, JBossDestination destination) throws JMSException
{
if (timeToLive == 0)
{
message.setJMSExpiration(0);
}
else
{
message.setJMSExpiration(System.currentTimeMillis() + timeToLive);
}
if (!disableMessageTimestamp)
{
message.setJMSTimestamp(System.currentTimeMillis());
}
else
{
message.setJMSTimestamp(0);
}
SimpleString address = null;
if (destination == null)
{
if (defaultDestination == null)
{
throw new InvalidDestinationException("Destination must be specified on send with an anonymous producer");
}
destination = defaultDestination;
}
else
{
if (defaultDestination != null)
{
if (!destination.equals(defaultDestination))
{
throw new JMSException("Where a default destination is specified " +
"for the sender and a destination is " +
"specified in the arguments to the send, " +
"these destinations must be equal");
}
}
address = destination.getSimpleAddress();
}
JBossMessage jbm;
boolean foreign = false;
// First convert from foreign message if appropriate
if (!(message instanceof JBossMessage))
{
// JMS 1.1 Sect. 3.11.4: A provider must be prepared to accept, from a client,
// a message whose implementation is not one of its own.
if (message instanceof BytesMessage)
{
jbm = new JBossBytesMessage((BytesMessage)message, clientSession );
}
else if (message instanceof MapMessage)
{
jbm = new JBossMapMessage((MapMessage)message, clientSession);
}
else if (message instanceof ObjectMessage)
{
jbm = new JBossObjectMessage((ObjectMessage)message, clientSession);
}
else if (message instanceof StreamMessage)
{
jbm = new JBossStreamMessage((StreamMessage)message, clientSession);
}
else if (message instanceof TextMessage)
{
jbm = new JBossTextMessage((TextMessage)message, clientSession);
}
else
{
jbm = new JBossMessage(message, clientSession);
}
// Set the destination on the original message
message.setJMSDestination(destination);
foreign = true;
}
else
{
jbm = (JBossMessage)message;
}
if (!disableMessageID)
{
// Generate an id
jbm.setJMSMessageID(messageIDPrefix + sequenceNumber.incrementAndGet());
}
if (foreign)
{
message.setJMSMessageID(jbm.getJMSMessageID());
}
jbm.setJMSDestination(destination);
try
{
jbm.doBeforeSend();
}
catch (Exception e)
{
JMSException je = new JMSException(e.getMessage());
je.initCause(e);
throw je;
}
ClientMessage coreMessage = jbm.getCoreMessage();
if (jbossConn.hasNoLocal())
{
coreMessage.putStringProperty(JBossConnection.CONNECTION_ID_PROPERTY_NAME, connID);
}
try
{
//check to see if this message needs to be scheduled
if(jbm.getScheduledDeliveryTime() > 0)
{
producer.send(address, coreMessage, jbm.getScheduledDeliveryTime());
}
else
{
producer.send(address, coreMessage);
}
}
catch (MessagingException e)
{
throw JMSExceptionHelper.convertFromMessagingException(e);
}
}
private void checkClosed() throws JMSException
{
if (producer.isClosed())
{
throw new IllegalStateException("Producer is closed");
}
}
// Inner classes -------------------------------------------------
}