All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.messaging.jmq.jmsclient.MessageProducerImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2000, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2021 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.messaging.jmq.jmsclient;

import java.util.Hashtable;
import java.util.Enumeration;
import jakarta.jms.*;

import com.sun.messaging.AdministeredObject;
import com.sun.messaging.jmq.io.*;
import com.sun.messaging.jmq.jmsclient.resources.ClientResources;
import java.util.logging.*;

/**
 * A client uses a message producer to send messages to a Destination. It is created by passing a Destination to a
 * create message producer method supplied by a Session.
 *
 * 

* A client also has the option of creating a message producer without supplying a Destination. In this case, a * Destination must be input on every send operation. A typical use for this style of message producer is to send * replies to requests using the request's replyTo Destination. * *

* A client can specify a default delivery mode, priority and time-to-live for messages sent by a message producer. It * can also specify delivery mode, priority and time-to-live per message. * *

* A client can specify a time-to-live value in milliseconds for each message it sends. This value defines a message * expiration time which is the sum of the message's time-to-live and the GMT it is sent (for transacted sends, this is * the time the client sends the message, not the time the transaction is committed). * *

* A JMS provider should do its best to accurately expire messages; however, JMS does not define the accuracy provided. * * @see jakarta.jms.TopicPublisher * @see jakarta.jms.QueueSender * @see jakarta.jms.Session */ public class MessageProducerImpl implements MessageProducer { protected boolean inClosing = false; protected boolean isClosed = false; protected boolean disableMessageId = false; // default in spec. protected boolean disableMessageTimestamp = false; // default in spec. protected int deliveryMode = DeliveryMode.PERSISTENT; // default in spec. protected int priority = 4; // default; protected long timeToLive = 0L; // default protected long deliveryDelay = jakarta.jms.Message.DEFAULT_DELIVERY_DELAY; protected Destination destination = null; protected SessionImpl session = null; protected MessageConvert messageConvert = null; // dest used when sending a message producer pkt to the broker. protected Destination addProducerDest = null; // XXX PROTOCOL3.5 -- // Producer flow control. protected Hashtable destinations = new Hashtable(); protected Hashtable producerStates = new Hashtable(); private boolean debug = Debug.debug; private boolean _forJMSBridge = false; protected static final Logger sessionLogger = SessionImpl.sessionLogger; public MessageProducerImpl(SessionImpl session, Destination destination) throws JMSException { try { this.session = session; this.destination = destination; if (destination != null) { session.getProtocolHandler().createMessageProducer(this); } session.addMessageProducer(this); if (sessionLogger.isLoggable(Level.FINE)) { this.logLifeCycle(ClientResources.I_PRODUCER_CREATED); } } catch (JMSException jmse) { ExceptionHandler.throwJMSException(jmse); } } /** * This method is called by ConnectionRecover during connection failover or auto-reconnect. */ public void recreateProducer() throws JMSException { if (destination != null) { // Create the producer again. session.getProtocolHandler().createMessageProducer(this); } else { // No need to physically recreate any producers! Instead // cleanup all the unbound producers created before. They // will be created again on demand... Enumeration enum2 = destinations.elements(); while (enum2.hasMoreElements()) { ProducerState ps = (ProducerState) enum2.nextElement(); session.connection.removeMessageProducer(Long.valueOf(ps.getProducerID())); } destinations.clear(); producerStates.clear(); } } /** * Check if this is a JMQ message. If this is, the same reference is returned. Otherwise, the message is converted to * JMQ message implementation and returned. */ protected Message checkJMQMessage(Message message) throws JMSException { if (message instanceof MessageImpl) { return message; } // this is a foreign message if (messageConvert == null) { messageConvert = MessageConvert.getInstance(); } return messageConvert.convertJMSMessage(message); } protected void checkState() throws JMSException { if (inClosing) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_PRODUCER_CLOSING); JMSException jmse = new jakarta.jms.IllegalStateException(errorString, AdministeredObject.cr.X_PRODUCER_CLOSING); ExceptionHandler.throwJMSException(jmse); } if (isClosed) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_PRODUCER_CLOSED); JMSException jmse = new jakarta.jms.IllegalStateException(errorString, AdministeredObject.cr.X_PRODUCER_CLOSED); ExceptionHandler.throwJMSException(jmse); } } /** * Reset foreign message header after it is sent. */ protected void resetForeignMessageHeader(Message message, Message foreignMessage) throws JMSException { if (!_forJMSBridge) { messageConvert.resetForeignMessageHeader(message, foreignMessage); } } protected void writeJMSMessage(Message message, CompletionListener completionListener, Message foreignMessage) throws JMSException { writeJMSMessage(destination, message, completionListener, foreignMessage); } protected void writeJMSMessage(Destination dest, Message message, CompletionListener completionListener, Message foreignMessage) throws JMSException { AsyncSendCallback asynccb = null; try { if (completionListener != null) { asynccb = new AsyncSendCallback(this, dest, message, completionListener, foreignMessage); session.addAsyncSendCallback(asynccb); checkState(); } session.connection.checkReconnecting(null, true); checkFlowControl(dest, message, true); try { session.writeJMSMessage(message, asynccb); if (sessionLogger.isLoggable(Level.FINER)) { // String pktType = // PacketType.getString // (((MessageImpl) message).getPacket().getPacketType()); // String param = pktType + ", " + session.toString() + getDestInfo (dest); // sessionLogger.log(Level.FINEST, // ClientResources.I_PRODUCER_SENDING_MESSAGE, // param); this.logMessageProduced(dest, message, completionListener); } if (asynccb != null) { asynccb.sendSuccessReturn(); } } catch (Exception e) { ExceptionHandler.handleException(e, AdministeredObject.cr.X_CAUGHT_EXCEPTION); } } finally { if (asynccb != null) { asynccb.sendReturn(); } } } private void logMessageProduced(Destination dest, Message message, CompletionListener completionListener) throws JMSException { if (sessionLogger.isLoggable(Level.FINER)) { // String pktType = // PacketType.getString // (((MessageImpl) message).getPacket().getPacketType()); // String param = pktType + ", " + session.toString() + getDestInfo (dest); // sessionLogger.log(Level.FINEST, // ClientResources.I_PRODUCER_SENDING_MESSAGE, // param); com.sun.messaging.Destination mqDest = ((com.sun.messaging.Destination) dest); String domain = (mqDest.isQueue() ? "Queue" : "Topic"); String pktType = PacketType.getString(((MessageImpl) message).getPacket().getPacketType()); ProducerState ps = (ProducerState) destinations.get(mqDest.getName()); long pid = ps.getProducerID(); String param = "MQTrace=MessageProducer" + ", ThreadID=" + Thread.currentThread().getId() + ", ClientID=" + session.connection.getClientID() + ", ConnectionID=" + session.connection.getConnectionID() + ", SessionID=" + session.getBrokerSessionID() + ", ProducerID=" + pid + ", Destination=" + mqDest.getName() + ", Domain=" + domain + ", MessageID=" + message.getJMSMessageID() + ", MessageType=" + pktType; String logkey = ClientResources.I_PRODUCER_SENT_MESSAGE; if (completionListener != null) { logkey = ClientResources.I_PRODUCER_ASYNC_SENDING_MESSAGE; } sessionLogger.log(Level.FINER, logkey, param); if (sessionLogger.isLoggable(Level.FINEST)) { param = "MQTrace=MessageProducer" + ", ProducerID=" + pid + ", Message=" + message.toString(); sessionLogger.log(Level.FINEST, logkey, param); } } } /** * Gets the Destination associated with this MessageProducer. * * @return this sender's Destination * * @exception JMSException if the JMS provider fails to get the destination for this MessageProducer due to * some internal error. * @since 1.1 */ @Override public Destination getDestination() throws JMSException { checkState(); return destination; } /** * Set whether message IDs are disabled. * *

* Since message ID's take some effort to create and increase a message's size, some JMS providers may be able to * optimize message overhead if they are given a hint that message ID is not used by an application. JMS message * Producers provide a hint to disable message ID. When a client sets a Producer to disable message ID they are saying * that they do not depend on the value of message ID for the messages it produces. These messages must either have * message ID set to null or, if the hint is ignored, messageID must be set to its normal unique value. * *

* Message IDs are enabled by default. * * @param value indicates if message IDs are disabled. * * @exception JMSException if JMS fails to set disabled message Id due to some internal error. */ @Override public void setDisableMessageID(boolean value) throws JMSException { checkState(); disableMessageId = value; } /** * Get an indication of whether message IDs are disabled. * * @return an indication of whether message IDs are disabled. * * @exception JMSException if JMS fails to get disabled message Id due to some internal error. */ @Override public boolean getDisableMessageID() throws JMSException { checkState(); return disableMessageId; } /** * Set whether message timestamps are disabled. * *

* Since timestamps take some effort to create and increase a message's size, some JMS providers may be able to optimize * message overhead if they are given a hint that timestamp is not used by an application. JMS message Producers provide * a hint to disable timestamps. When a client sets a producer to disable timestamps they are saying that they do not * depend on the value of timestamp for the messages it produces. These messages must either have timestamp set to null * or, if the hint is ignored, timestamp must be set to its normal value. * *

* Message timestamps are enabled by default. * * @param value indicates if message timestamps are disabled. * * @exception JMSException if JMS fails to set disabled message timestamp due to some internal error. */ @Override public void setDisableMessageTimestamp(boolean value) throws JMSException { checkState(); disableMessageTimestamp = value; } /** * Get an indication of whether message timestamps are disabled. * * @return an indication of whether message IDs are disabled. * * @exception JMSException if JMS fails to get disabled message timestamp due to some internal error. */ @Override public boolean getDisableMessageTimestamp() throws JMSException { checkState(); return disableMessageTimestamp; } /** * Set the producer's default delivery mode. * *

* Delivery mode is set to PERSISTENT by default. * * @param deliveryMode the message delivery mode for this message producer. Legal values are * DeliveryMode.NON_PERSISTENT or DeliveryMode.PERSISTENT. * * @exception JMSException if JMS fails to set delivery mode due to some internal error. * * @see jakarta.jms.MessageProducer#getDeliveryMode * @see jakarta.jms.DeliveryMode#NON_PERSISTENT * @see jakarta.jms.DeliveryMode#PERSISTENT * @see jakarta.jms.Message#DEFAULT_DELIVERY_MODE */ @Override public void setDeliveryMode(int deliveryMode) throws JMSException { checkState(); if (deliveryMode != DeliveryMode.NON_PERSISTENT && deliveryMode != DeliveryMode.PERSISTENT) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_INVALID_DELIVERY_PARAM, "DeliveryMode", String.valueOf(deliveryMode)); ExceptionHandler.throwJMSException(new JMSException(errorString, AdministeredObject.cr.X_INVALID_DELIVERY_PARAM)); } this.deliveryMode = deliveryMode; } /** * Get the producer's default delivery mode. * * @return the message delivery mode for this message producer. * * @exception JMSException if JMS fails to get delivery mode due to some internal error. * * @see jakarta.jms.MessageProducer#setDeliveryMode */ @Override public int getDeliveryMode() throws JMSException { checkState(); return deliveryMode; } /** * Set the producer's default priority. * *

* JMS defines a 10 level priority value with 0 as the lowest and 9 as the highest. Clients should consider 0-4 as * gradients of normal priority and 5-9 as gradients of expedited priority. Priority is set to 4, by default. * * @param defaultPriority the message priority for this message producer. Priority must be a value between 0 and 9. * * * @exception JMSException if JMS fails to set priority due to some internal error. * * @see jakarta.jms.MessageProducer#getPriority * @see jakarta.jms.Message#DEFAULT_PRIORITY */ @Override public void setPriority(int defaultPriority) throws JMSException { checkState(); if (defaultPriority < 0 || defaultPriority > 9) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_INVALID_DELIVERY_PARAM, "DeliveryPriority", String.valueOf(defaultPriority)); ExceptionHandler.throwJMSException(new JMSException(errorString, AdministeredObject.cr.X_INVALID_DELIVERY_PARAM)); } this.priority = defaultPriority; } /** * Get the producer's default priority. * * @return the message priority for this message producer. * * @exception JMSException if JMS fails to get priority due to some internal error. * * @see jakarta.jms.MessageProducer#setPriority */ @Override public int getPriority() throws JMSException { checkState(); return priority; } /** * Set the default length of time in milliseconds from its dispatch time that a produced message should be retained by * the message system. * *

* Time to live is set to zero by default. * * @param timeToLive the message time to live in milliseconds; zero is unlimited * * @exception JMSException if JMS fails to set Time to Live due to some internal error. * * @see jakarta.jms.MessageProducer#getTimeToLive * @see jakarta.jms.Message#DEFAULT_TIME_TO_LIVE */ @Override public void setTimeToLive(long timeToLive) throws JMSException { checkState(); if (timeToLive < 0) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_INVALID_DELIVERY_PARAM, "TimeToLive", String.valueOf(timeToLive)); ExceptionHandler.throwJMSException(new JMSException(errorString, AdministeredObject.cr.X_INVALID_DELIVERY_PARAM)); } this.timeToLive = timeToLive; } /** * Get the default length of time in milliseconds from its dispatch time that a produced message should be retained by * the message system. * * @return the message time to live in milliseconds; zero is unlimited * * @exception JMSException if JMS fails to get Time to Live due to some internal error. * * @see jakarta.jms.MessageProducer#setTimeToLive */ @Override public long getTimeToLive() throws JMSException { checkState(); return timeToLive; } /** * Sets the minimum length of time in milliseconds that must elapse after a message is sent before the JMS provider may * deliver the message to a consumer. *

* For transacted sends, this time starts when the client sends the message, not when the transaction is committed. *

* deliveryDelay is set to zero by default. * * @param deliveryDelay the delivery delay in milliseconds. * * @exception JMSException if the JMS provider fails to set the delivery delay due to some internal error. * * @see jakarta.jms.MessageProducer#getDeliveryDelay * @see jakarta.jms.Message#DEFAULT_DELIVERY_DELAY * * @since 2.0 */ @Override public void setDeliveryDelay(long deliveryDelay) throws JMSException { checkState(); if (deliveryDelay < 0L) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_INVALID_DELIVERY_PARAM, "DeliveryDelay", String.valueOf(deliveryDelay)); ExceptionHandler.throwJMSException(new JMSException(errorString, AdministeredObject.cr.X_INVALID_DELIVERY_PARAM)); } this.deliveryDelay = deliveryDelay; } /** * Gets the minimum length of time in milliseconds that must elapse after a message is sent before the JMS provider may * deliver the message to a consumer. * * @return the delivery delay in milliseconds. * * @exception JMSException if the JMS provider fails to get the delivery delay due to some internal error. * * @see jakarta.jms.MessageProducer#setDeliveryDelay * * @since 2.0 */ @Override public long getDeliveryDelay() throws JMSException { checkState(); return deliveryDelay; } /** * Since a provider may allocate some resources on behalf of a MessageProducer outside the JVM, clients should close * them when they are not needed. Relying on garbage collection to eventually reclaim these resources may not be timely * enough. * * @exception JMSException if JMS fails to close the producer due to some error. */ // XXX note currently producers are not cleaned up on session close // need to address this for 2.1 @Override public void close() throws JMSException { session.checkPermissionForAsyncSend(); // XXX PROTOCOL3.5 -- // Producer flow control. Raptor broker keeps track of // producers. try { inClosing = true; try { Enumeration enum2 = producerStates.elements(); while (enum2.hasMoreElements()) { ProducerState ps = (ProducerState) enum2.nextElement(); if (session.connection.getBrokerProtocolLevel() >= PacketType.VERSION350 && session.getProtocolHandler() != null) { session.connection.removeMessageProducer(Long.valueOf(ps.getProducerID())); // delete only if connection is not broken if (session.connection.isBroken() == false) { session.getProtocolHandler().deleteMessageProducer(ps.getProducerID()); } } ps.close(); } session.removeMessageProducer(this); destinations.clear(); producerStates.clear(); } finally { session.waitAllAsyncSendCompletion(this); } } finally { isClosed = true; // log producer closed if (session.sessionLogger.isLoggable(Level.FINE)) { logLifeCycle(ClientResources.I_PRODUCER_CLOSED); } } } /** * Sends a message using the MessageProducer's default delivery mode, priority, and time to live. * * @param message the message to send * * @exception JMSException if the JMS provider fails to send the message due to some internal error. * @exception MessageFormatException if an invalid message is specified. * @exception InvalidDestinationException if a client uses this method with a MessageProducer with an * invalid Destination. * @exception java.lang.UnsupportedOperationException if a client uses this method with a MessageProducer * that did not specify a destination at creation time. * * @see jakarta.jms.Session#createProducer * @see jakarta.jms.MessageProducer#getDeliveryMode * @see jakarta.jms.MessageProducer#getTimeToLive * @see jakarta.jms.MessageProducer#getPriority * @since 1.1 */ @Override public void send(Message message) throws JMSException { _send(message, null); } private void _send(Message message, CompletionListener completionListener) throws JMSException { Message foreignMessage = null; checkState(); if (destination == null) { throw new UnsupportedOperationException(); } checkTemporaryDestination(destination); if ((message instanceof MessageImpl) == false) { foreignMessage = message; } message = checkJMQMessage(message); message.setJMSDestination(destination); message.setJMSDeliveryMode(getDeliveryMode()); message.setJMSPriority(getPriority()); message.setJMSExpiration(getTimeToLive()); message.setJMSDeliveryTime(getDeliveryDelay()); if (session.connection.jmqOverrideJMSMsgHeaders) { Destination d = message.getJMSDestination(); if (session.connection.jmqOverrideMsgsToTempDests || ((!(d instanceof TemporaryQueue)) && (!(d instanceof TemporaryTopic)))) { if (session.connection.jmqOverrideJMSDeliveryMode) { message.setJMSDeliveryMode(session.connection.jmqJMSDeliveryMode); } if (session.connection.jmqOverrideJMSPriority) { message.setJMSPriority(session.connection.jmqJMSPriority); } if (session.connection.jmqOverrideJMSExpiration) { message.setJMSExpiration(session.connection.jmqJMSExpiration); } } } writeJMSMessage(message, completionListener, foreignMessage); if (foreignMessage != null && completionListener == null) { resetForeignMessageHeader(message, foreignMessage); } } /** * Sends a message to the Destination, specifying delivery mode, priority, and time to live. * * @param message the message to send * @param deliveryMode the delivery mode to use * @param priority the priority for this message * @param timeToLive the message's lifetime (in milliseconds) * * @exception JMSException if the JMS provider fails to send the message due to some internal error. * @exception MessageFormatException if an invalid message is specified. * @exception InvalidDestinationException if a client uses this method with a MessageProducer with an * invalid Destination. * @exception java.lang.UnsupportedOperationException if a client uses this method with a MessageProducer * that did not specify a destination at creation time. * * @see jakarta.jms.Session#createProducer * @since 1.1 */ @Override public void send(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { _send(message, deliveryMode, priority, timeToLive, null); } private void _send(Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener) throws JMSException { Message foreignMessage = null; checkState(); checkTimeToLiveValue(timeToLive); if (destination == null) { throw new UnsupportedOperationException(); } checkTemporaryDestination(destination); if ((message instanceof MessageImpl) == false) { foreignMessage = message; } message = checkJMQMessage(message); message.setJMSDestination(destination); message.setJMSDeliveryMode(deliveryMode); message.setJMSPriority(priority); message.setJMSExpiration(timeToLive); message.setJMSDeliveryTime(getDeliveryDelay()); if (session.connection.jmqOverrideJMSMsgHeaders) { Destination d = message.getJMSDestination(); if (session.connection.jmqOverrideMsgsToTempDests || ((!(d instanceof TemporaryQueue)) && (!(d instanceof TemporaryTopic)))) { if (session.connection.jmqOverrideJMSDeliveryMode) { message.setJMSDeliveryMode(session.connection.jmqJMSDeliveryMode); } if (session.connection.jmqOverrideJMSPriority) { message.setJMSPriority(session.connection.jmqJMSPriority); } if (session.connection.jmqOverrideJMSExpiration) { message.setJMSExpiration(session.connection.jmqJMSExpiration); } } } writeJMSMessage(message, completionListener, foreignMessage); if (foreignMessage != null && completionListener == null) { resetForeignMessageHeader(message, foreignMessage); } } /** * Sends a message to a Destination for an unidentified message producer. Uses the MessageProducer's * default delivery mode, priority, and time to live. * *

* Typically, a message producer is assigned a destination at creation time; however, the JMS API also supports * unidentified message producers, which require that the Destination be supplied every time a message is sent. * * @param destination the destination to send this message to * @param message the message to send * * @exception JMSException if the JMS provider fails to send the message due to some internal error. * @exception MessageFormatException if an invalid message is specified. * @exception InvalidDestinationException if a client uses this method with an invalid Destination. * @exception java.lang.UnsupportedOperationException if a client uses this method with a MessageProducer * that did specify a destination at creation time. * * @see jakarta.jms.Session#createProducer * @see jakarta.jms.MessageProducer#getDeliveryMode * @see jakarta.jms.MessageProducer#getTimeToLive * @see jakarta.jms.MessageProducer#getPriority * @since 1.1 */ @Override public void send(Destination destination, Message message) throws JMSException { _send(destination, message, null); } private void _send(Destination destination, Message message, CompletionListener completionListener) throws JMSException { Message foreignMessage = null; checkState(); if (destination == null) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_DESTINATION_NOTFOUND, "null"); ExceptionHandler.throwJMSException(new InvalidDestinationException(errorString, AdministeredObject.cr.X_DESTINATION_NOTFOUND)); } if (this.destination != null) { throw new UnsupportedOperationException(); } checkTemporaryDestination(destination); if ((message instanceof MessageImpl) == false) { foreignMessage = message; } checkForUnspecifiedProducer(destination); message = checkJMQMessage(message); message.setJMSDestination(destination); message.setJMSDeliveryMode(getDeliveryMode()); message.setJMSPriority(getPriority()); message.setJMSExpiration(getTimeToLive()); message.setJMSDeliveryTime(getDeliveryDelay()); if (session.connection.jmqOverrideJMSMsgHeaders) { Destination d = message.getJMSDestination(); if (session.connection.jmqOverrideMsgsToTempDests || ((!(d instanceof TemporaryQueue)) && (!(d instanceof TemporaryTopic)))) { if (session.connection.jmqOverrideJMSDeliveryMode) { message.setJMSDeliveryMode(session.connection.jmqJMSDeliveryMode); } if (session.connection.jmqOverrideJMSPriority) { message.setJMSPriority(session.connection.jmqJMSPriority); } if (session.connection.jmqOverrideJMSExpiration) { message.setJMSExpiration(session.connection.jmqJMSExpiration); } } } writeJMSMessage(destination, message, completionListener, foreignMessage); if (foreignMessage != null && completionListener == null) { resetForeignMessageHeader(message, foreignMessage); } } /** * Sends a message to a Destination for an unidentified message producer, specifying delivery mode, priority and time to * live. * *

* Typically, a message producer is assigned a destination at creation time; however, the JMS API also supports * unidentified message producers, which require that the Destination be supplied every time a message is sent. * * @param destination the destination to send this message to * @param message the message to send * @param deliveryMode the delivery mode to use * @param priority the priority for this message * @param timeToLive the message's lifetime (in milliseconds) * * @exception JMSException if the JMS provider fails to send the message due to some internal error. * @exception MessageFormatException if an invalid message is specified. * @exception InvalidDestinationException if a client uses this method with an invalid Destination. * @exception java.lang.UnsupportedOperationException if a client uses this method with a MessageConsumer * that specified a destination at creation time. * * @see jakarta.jms.Session#createProducer * @since 1.1 */ @Override public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException { _send(destination, message, deliveryMode, priority, timeToLive, null); } private void _send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener) throws JMSException { Message foreignMessage = null; checkState(); checkTimeToLiveValue(timeToLive); if (destination == null) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_DESTINATION_NOTFOUND, "null"); ExceptionHandler.throwJMSException(new InvalidDestinationException(errorString, AdministeredObject.cr.X_DESTINATION_NOTFOUND)); } if (this.destination != null) { throw new UnsupportedOperationException(); } checkTemporaryDestination(destination); if ((message instanceof MessageImpl) == false) { foreignMessage = message; } checkForUnspecifiedProducer(destination); message = checkJMQMessage(message); message.setJMSDestination(destination); message.setJMSDeliveryMode(deliveryMode); message.setJMSPriority(priority); message.setJMSExpiration(timeToLive); message.setJMSDeliveryTime(getDeliveryDelay()); if (session.connection.jmqOverrideJMSMsgHeaders) { Destination d = message.getJMSDestination(); if (session.connection.jmqOverrideMsgsToTempDests || (!(d instanceof TemporaryQueue))) { if (session.connection.jmqOverrideJMSDeliveryMode) { message.setJMSDeliveryMode(session.connection.jmqJMSDeliveryMode); } if (session.connection.jmqOverrideJMSPriority) { message.setJMSPriority(session.connection.jmqJMSPriority); } if (session.connection.jmqOverrideJMSExpiration) { message.setJMSExpiration(session.connection.jmqJMSExpiration); } } } writeJMSMessage(destination, message, completionListener, foreignMessage); if (foreignMessage != null && completionListener == null) { resetForeignMessageHeader(message, foreignMessage); } } public void _setForJMSBridge() { _forJMSBridge = true; } protected void setProducerID(Destination dest, long producerID) { String dn = ((com.sun.messaging.Destination) dest).getName(); ProducerState ps = (ProducerState) destinations.get(dn); if (ps == null) { ps = new ProducerState(); destinations.put(dn, ps); } else { if (debug) { Debug.println("Replacing ProducerID. old = " + ps.getProducerID() + ", new = " + producerID); } producerStates.remove(Long.valueOf(ps.getProducerID())); session.connection.removeMessageProducer(Long.valueOf(ps.getProducerID())); } ps.setProducerID(producerID); producerStates.put(Long.valueOf(producerID), ps); session.connection.addMessageProducer(Long.valueOf(producerID), this); } protected void setFlowLimit(long producerID, int flowLimit) { if (debug) { Debug.println("Setting flowLimit = " + flowLimit + " for producerID = " + producerID); } ProducerState ps = (ProducerState) producerStates.get(Long.valueOf(producerID)); ps.setFlowLimit(flowLimit); } protected void setFlowBytesLimit(long producerID, long flowBytesLimit) { if (debug) { Debug.println("Setting flowBytesLimit = " + flowBytesLimit + " for producerID = " + producerID); } ProducerState ps = (ProducerState) producerStates.get(Long.valueOf(producerID)); ps.setFlowBytesLimit(flowBytesLimit); } private void checkFlowControl(Destination dest, Message message, boolean block) throws JMSException { String dn = ((com.sun.messaging.Destination) dest).getName(); ProducerState ps = (ProducerState) destinations.get(dn); if (ps != null) { ps.checkFlowControl(message, block); } } protected SessionImpl getSession() { return session; } @Override public String toString() { // return "MessageProducer: " + session.getConnection().toString(); String destName = null; long pid = -1; try { if (destination != null) { destName = ((com.sun.messaging.Destination) destination).getName(); ProducerState ps = (ProducerState) destinations.get(destName); pid = ps.getProducerID(); } } catch (Exception e) { // if we catch exception, pid would be -1 if (debug) { Debug.printStackTrace(e); } } return session.toString() + ", ProducerID=" + pid + ", DestName=" + destName; } protected void checkForUnspecifiedProducer(Destination dest) throws JMSException { // XXX: Should not be using d.getName(); com.sun.messaging.Destination d = (com.sun.messaging.Destination) dest; String dn = d.getName(); if (destinations.get(dn) == null) { session.getProtocolHandler().createMessageProducer(this, d); } } protected void checkTemporaryDestination(Destination dest) throws JMSException { if (dest instanceof TemporaryDestination) { // check whether the temporary destination has been deleted if (((TemporaryDestination) dest).isDeleted()) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_TEMP_DESTINATION_DELETED, ((TemporaryDestination) dest).getName()); ExceptionHandler.throwJMSException(new InvalidDestinationException(errorString, AdministeredObject.cr.X_TEMP_DESTINATION_DELETED)); } // check whether the owning connection is closed ConnectionImpl connection = ((TemporaryDestination) dest).connection; if (connection != null) { // local temp destination. if (connection.isClosed) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_TEMP_DESTINATION_INVALID, ((TemporaryDestination) dest).getName()); ExceptionHandler.throwJMSException(new InvalidDestinationException(errorString, AdministeredObject.cr.X_TEMP_DESTINATION_INVALID)); } } } } private static void checkTimeToLiveValue(long timeToLive) throws JMSException { if (timeToLive < 0) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_INVALID_DELIVERY_PARAM, "TimeToLive", String.valueOf(timeToLive)); ExceptionHandler.throwJMSException(new JMSException(errorString, AdministeredObject.cr.X_INVALID_DELIVERY_PARAM)); } } public void logLifeCycle(String key) { if (sessionLogger.isLoggable(Level.FINE)) { sessionLogger.log(Level.FINE, key, this); } } class ProducerState { private long flowBytesLimit; private int flowLimit; private long producerID; private boolean blocked = false; private boolean _psclosed = false; private int TEST_minResume = Integer.MAX_VALUE; private int TEST_maxResume = -1; private int TEST_resumeCount = 0; private int TEST_pauseCount = 0; private int TEST_forcePauseCount = 0; protected long getFlowBytesLimit() { return flowBytesLimit; } protected synchronized void setFlowBytesLimit(long flowBytesLimit) { this.flowBytesLimit = flowBytesLimit; } protected int getFlowLimit() { return flowLimit; } protected synchronized void setFlowLimit(int flowLimit) { this.flowLimit = flowLimit; if (flowLimit < TEST_minResume) { TEST_minResume = flowLimit; } if (flowLimit > TEST_maxResume) { TEST_maxResume = flowLimit; } if (flowLimit != 0) { TEST_resumeCount++; } else { TEST_forcePauseCount++; } notifyAll(); } protected long getProducerID() { return producerID; } protected void setProducerID(long producerID) { this.producerID = producerID; } protected synchronized void close() { _psclosed = true; notifyAll(); } private synchronized void checkFlowControl(Message message, boolean block) throws JMSException { while (flowLimit == 0 && !isClosed && !_psclosed) { try { if (!block) { throw new JMSException("XXXWOULD-BLOCK"); } blocked = true; wait(); blocked = false; } catch (InterruptedException e) { } } if (isClosed || _psclosed) { String errorString = AdministeredObject.cr.getKString(AdministeredObject.cr.X_PRODUCER_CLOSED); JMSException jmse = new jakarta.jms.JMSException(errorString, AdministeredObject.cr.X_PRODUCER_CLOSED); ExceptionHandler.throwJMSException(jmse); } if (flowLimit > 0) { flowLimit--; } if (flowLimit == 0) { TEST_pauseCount++; } ReadWritePacket pkt = ((MessageImpl) message).getPacket(); pkt.setProducerID(producerID); pkt.setConsumerFlow((flowLimit == 0)); } protected Hashtable getDebugState(boolean verbose) { Hashtable ht = new Hashtable(); ht.put("producerID", String.valueOf(producerID)); ht.put("flowLimit", String.valueOf(flowLimit)); ht.put("flowBytesLimit", String.valueOf(flowBytesLimit)); ht.put("blocked", String.valueOf(blocked)); ht.put("pauseCount", String.valueOf(TEST_pauseCount)); ht.put("resumeCount", String.valueOf(TEST_resumeCount)); ht.put("maxResume", String.valueOf(TEST_maxResume)); ht.put("minResume", String.valueOf(TEST_minResume)); ht.put("forcedPauses", String.valueOf(TEST_forcePauseCount)); return ht; } } protected Hashtable getDebugState(boolean verbose) { Hashtable ht = new Hashtable(); ht.put("isClosed", String.valueOf(isClosed)); ht.put("deliveryMode", String.valueOf(deliveryMode)); ht.put("priority", String.valueOf(priority)); ht.put("timeToLive", String.valueOf(timeToLive)); ht.put("deliveryDelay", String.valueOf(deliveryDelay)); ht.put("disableMessageId", String.valueOf(disableMessageId)); ht.put("disableTimestamp", String.valueOf(disableMessageTimestamp)); if (destination != null) { ht.put("Destination Class", destination.getClass().getName()); if (destination instanceof com.sun.messaging.Destination) { ht.put("Destination", ((com.sun.messaging.Destination) destination).getName()); } Enumeration enum2 = producerStates.elements(); while (enum2.hasMoreElements()) { ProducerState ps = (ProducerState) enum2.nextElement(); ht.putAll(ps.getDebugState(verbose)); } } else { // Unbound producer... ht.put("isBound", "false"); ht.put("# Destinations", String.valueOf(destinations.size())); int n = 0; Enumeration enum2 = destinations.keys(); while (enum2.hasMoreElements()) { String dn = (String) enum2.nextElement(); ProducerState ps = (ProducerState) destinations.get(dn); Hashtable tmp = ps.getDebugState(verbose); tmp.put("Destination", dn); ht.put("ProducerState[" + n + "]", tmp); n++; } } return ht; } @Override public void send(Message message, CompletionListener completionListener) throws JMSException { if (completionListener == null) { throw new IllegalArgumentException("CompletionListener must not be null"); } _send(message, completionListener); } @Override public void send(Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener) throws JMSException { if (completionListener == null) { throw new IllegalArgumentException("CompletionListener must not be null"); } _send(message, deliveryMode, priority, timeToLive, completionListener); } @Override public void send(Destination destination, Message message, CompletionListener completionListener) throws JMSException { if (completionListener == null) { throw new IllegalArgumentException("CompletionListener must not be null"); } _send(destination, message, completionListener); } @Override public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, CompletionListener completionListener) throws JMSException { if (completionListener == null) { throw new IllegalArgumentException("CompletionListener must not be null"); } _send(destination, message, deliveryMode, priority, timeToLive, completionListener); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy