private void send()

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();
        }
    }