in qpid-jms-client/src/main/java/org/apache/qpid/jms/JmsSession.java [888:1018]
private void send(JmsMessageProducer producer, JmsDestination destination, Message original, int deliveryMode, int priority, long timeToLive, boolean disableMsgId, boolean disableTimestamp, long deliveryDelay, CompletionListener listener) throws JMSException {
JmsMessage outbound = null;
sendLock.lock();
try {
checkClosed();
original.setJMSDeliveryMode(deliveryMode);
original.setJMSPriority(priority);
original.setJMSRedelivered(false);
original.setJMSDestination(destination);
long timeStamp = System.currentTimeMillis();
boolean hasTTL = timeToLive > Message.DEFAULT_TIME_TO_LIVE;
boolean hasDelay = deliveryDelay > Message.DEFAULT_DELIVERY_DELAY;
boolean isJmsMessage = original instanceof JmsMessage;
if (!disableTimestamp) {
original.setJMSTimestamp(timeStamp);
} else {
original.setJMSTimestamp(0);
}
if (hasTTL) {
original.setJMSExpiration(timeStamp + timeToLive);
} else {
original.setJMSExpiration(0);
}
long messageSequence = producer.getNextMessageSequence();
Object messageId = null;
if (!disableMsgId) {
messageId = producer.getMessageIDBuilder().createMessageID(producer.getProducerId().toString(), messageSequence);
}
if (isJmsMessage) {
outbound = (JmsMessage) original;
} else {
// Transform and assign the Destination as one of our own destination objects.
outbound = JmsMessageTransformation.transformMessage(connection, original);
outbound.setJMSDestination(destination);
}
// Set the delivery time. Purposefully avoided doing this earlier so
// that we use the 'outbound' JmsMessage object reference when
// updating our own message instances, avoids using the interface
// in case the JMS 1.1 Message API is actually being used due to
// being on the classpath too.
long deliveryTime = timeStamp;
if (hasDelay) {
deliveryTime = timeStamp + deliveryDelay;
}
outbound.getFacade().setDeliveryTime(deliveryTime, hasDelay);
if (!isJmsMessage) {
// If the original was a foreign message, we still need to update it too.
setForeignMessageDeliveryTime(original, deliveryTime);
}
// Set the message ID
outbound.getFacade().setProviderMessageIdObject(messageId);
if (!isJmsMessage) {
// If the original was a foreign message, we still need to update it
// with the properly encoded Message ID String, get it from the one
// we transformed from now that it is set.
original.setJMSMessageID(outbound.getJMSMessageID());
}
// If configured set the User ID using the value we have encoded and cached,
// otherwise clear to prevent caller from spoofing the user ID value.
if (connection.isPopulateJMSXUserID()) {
outbound.getFacade().setUserIdBytes(connection.getEncodedUsername());
} else {
outbound.getFacade().setUserId(null);
}
boolean sync = connection.isForceSyncSend() ||
(!connection.isForceAsyncSend() && deliveryMode == DeliveryMode.PERSISTENT && !getTransacted());
outbound.onSend(timeToLive);
JmsOutboundMessageDispatch envelope = new JmsOutboundMessageDispatch();
envelope.setMessage(outbound);
envelope.setPayload(outbound.getFacade().encodeMessage());
envelope.setProducerId(producer.getProducerId());
envelope.setDestination(destination);
envelope.setSendAsync(listener == null ? !sync : true);
envelope.setDispatchId(messageSequence);
envelope.setCompletionRequired(listener != null);
if (producer.isAnonymous()) {
envelope.setPresettle(getPresettlePolicy().isProducerPresttled(this, destination));
} else {
envelope.setPresettle(producer.isPresettled());
}
if (envelope.isSendAsync() && !envelope.isCompletionRequired() && !envelope.isPresettle()) {
envelope.setMessage(outbound.copy());
outbound.onSendComplete();
}
if (envelope.isCompletionRequired()) {
transactionContext.send(connection, envelope, new ProviderSynchronization() {
@Override
public void onPendingSuccess() {
// Provider accepted the send request so new we place the marker in
// the queue so that it can be completed asynchronously.
asyncSendQueue.addLast(new SendCompletion(envelope, listener));
}
@Override
public void onPendingFailure(ProviderException cause) {
// Provider has rejected the send request so we will throw the
// exception that is to follow so no completion will be needed.
}
});
} else {
transactionContext.send(connection, envelope, null);
}
} catch (JMSException jmsEx) {
// Ensure that on failure case the message is returned to usable state for another send attempt.
if (outbound != null) {
outbound.onSendComplete();
}
throw jmsEx;
} finally {
sendLock.unlock();
}
}