/**
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.synapse.message.store.impl.jms;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.MessageContext;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.message.MessageProducer;
import org.apache.synapse.message.store.impl.commons.MessageConverter;
import org.apache.synapse.message.store.impl.commons.StorableMessage;
import javax.jms.*;
import java.util.Map;
import java.util.Set;
public class JmsProducer implements MessageProducer {
private static final String JMS_PROD_TIME_TO_LIVE = "JMS_PROD_TIME_TO_LIVE";
private static final String JMS_PROD_DISABLE_MSG_TIMESTAMP = "JMS_PROD_DISABLE_MSG_TIMESTAMP";
private static final String JMS_PROD_DELIVERY_MODE = "JMS_PROD_DELIVERY_MODE";
private static final String JMS_PROD_DISABLE_MSG_ID = "JMS_PROD_DISABLE_MSG_ID";
private static final String JMS_PROD_PRIORITY = "JMS_PROD_PRIORITY";
private static final int DEFAULT_PRIORITY = 4;
// prefix used to set JMS Message level properties. ex: JMS_MSG_P_brokerSpecificProperty
private static final String JMS_MSG_P = "JMS_MSG_P_";
private static final Log logger = LogFactory.getLog(JmsProducer.class.getName());
private static final String OriginalMessageID = "OrigMessageID";
private Connection connection;
private Session session;
private javax.jms.MessageProducer producer;
private JmsStore store;
private String idString;
private boolean isConnectionError = false;
private boolean isInitialized = false;
public JmsProducer(JmsStore store) {
if (store == null) {
logger.error("Cannot initialize.");
return;
}
this.store = store;
isInitialized = true;
}
public boolean storeMessage(MessageContext synCtx) {
if (synCtx == null) {
return false;
}
if (!checkConnection()) {
logger.warn(getId() + ". Ignored MessageID : " + synCtx.getMessageID());
store.setCachedProducer(null);
return false;
}
StorableMessage message = MessageConverter.toStorableMessage(synCtx);
boolean error = false;
Throwable throwable = null;
try {
ObjectMessage objectMessage = session.createObjectMessage(message);
objectMessage.setStringProperty(OriginalMessageID, synCtx.getMessageID());
setPriority(producer, objectMessage, message);
setJmsProducerProperties(producer, synCtx);
setJmsMessageProperties(objectMessage, synCtx);
setTransportHeaders(objectMessage,synCtx);
producer.send(objectMessage);
if (session.getTransacted()) {
session.commit();
}
} catch (JMSException e) {
throwable = e;
error = true;
isConnectionError = true;
try {
if (session.getTransacted()) {
session.rollback();
}
} catch (JMSException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Fail to rollback message [" + synCtx.getMessageID() + "] from the message store " +
":" + store.getName(), ex);
}
}
} catch (Throwable t) {
throwable = t;
error = true;
try {
if (session.getTransacted()) {
session.rollback();
}
} catch (JMSException e) {
if (logger.isDebugEnabled()) {
logger.debug("Fail to rollback message [" + synCtx.getMessageID()+"] from the message store " +
":" + store.getName(), e);
}
}
}
if (error) {
String errorMsg = getId() + ". Ignored MessageID : " + synCtx.getMessageID()
+ ". Could not store message to store ["
+ store.getName() + "]. Error:" + throwable.getLocalizedMessage();
logger.error(errorMsg, throwable);
store.closeWriteConnection();
connection = null;
if (logger.isDebugEnabled()) {
logger.debug(getId() + ". Ignored MessageID : " + synCtx.getMessageID());
}
return false;
} else {
store.reset(null, session, false);
}
if (logger.isDebugEnabled()) {
logger.debug(getId() + ". Stored MessageID : " + synCtx.getMessageID());
}
store.enqueued();
return true;
}
public boolean cleanup() {
return store.cleanup(null, session, false);
}
public JmsProducer setConnection(Connection connection) {
this.connection = connection;
return this;
}
public JmsProducer setSession(Session session) {
this.session = session;
return this;
}
public JmsProducer setProducer(javax.jms.MessageProducer producer) {
this.producer = producer;
return this;
}
public boolean isInitialized() {
return isInitialized;
}
public void setId(int id) {
idString = "[" + store.getName() + "-P-" + id + "]";
}
public String getId() {
return getIdAsString();
}
private String getIdAsString() {
if (idString == null) {
return "[unknown-producer]";
}
return idString;
}
private boolean checkConnection() {
if (producer == null) {
if (logger.isDebugEnabled()) {
logger.error(getId() + " cannot proceed. Message producer is null.");
}
return false;
}
if (session == null) {
if (logger.isDebugEnabled()) {
logger.error(getId() + " cannot proceed. JMS Session is null.");
}
return false;
}
if (connection == null) {
if (logger.isDebugEnabled()) {
logger.error(getId() + " cannot proceed. JMS Connection is null.");
}
return false;
}
return true;
}
private void setPriority(javax.jms.MessageProducer producer, ObjectMessage objectMessage,
StorableMessage message) {
if (message.getPriority(DEFAULT_PRIORITY) != Message.DEFAULT_PRIORITY) {
try {
producer.setPriority(message.getPriority(DEFAULT_PRIORITY));
} catch (JMSException e) {
logger.warn(getId() + " could not set priority ["
+ message.getPriority(DEFAULT_PRIORITY) + "]");
}
} else {
try {
producer.setPriority(Message.DEFAULT_PRIORITY);
} catch (JMSException e) {}
}
}
private void setJmsProducerProperties(javax.jms.MessageProducer producer, MessageContext synCtx) {
Object prop = synCtx.getProperty(JMS_PROD_TIME_TO_LIVE);
long ttl = Message.DEFAULT_TIME_TO_LIVE;
if (prop instanceof String) {
ttl = Long.parseLong((String) prop);
} else if (prop instanceof Long || prop instanceof Integer) {
ttl = Long.parseLong(prop.toString());
}
prop = synCtx.getProperty(JMS_PROD_DISABLE_MSG_TIMESTAMP);
boolean disableMessageTimestamp = false;
if (prop instanceof String) {
disableMessageTimestamp = Boolean.parseBoolean((String) prop);
} else if (prop instanceof Boolean) {
disableMessageTimestamp = (Boolean) prop;
}
prop = synCtx.getProperty(JMS_PROD_DELIVERY_MODE);
int deliveryMode = Message.DEFAULT_DELIVERY_MODE;
if (prop instanceof Integer) {
deliveryMode = (Integer) prop;
} else if (prop instanceof String) {
deliveryMode = Integer.parseInt((String) prop);
}
prop = synCtx.getProperty(JMS_PROD_DISABLE_MSG_ID);
boolean disableMessageId = false;
if (prop instanceof String) {
disableMessageId = Boolean.parseBoolean((String) prop);
} else if (prop instanceof Boolean) {
disableMessageId = (Boolean) prop;
}
prop = synCtx.getProperty(JMS_PROD_PRIORITY);
int priority = Message.DEFAULT_PRIORITY;
if (prop instanceof Integer) {
priority = (Integer) prop;
} else if (prop instanceof String) {
priority = Integer.parseInt((String) prop);
}
try {
producer.setTimeToLive(ttl);
producer.setDisableMessageTimestamp(disableMessageTimestamp);
producer.setDeliveryMode(deliveryMode);
producer.setDisableMessageID(disableMessageId);
producer.setPriority(priority);
} catch (JMSException e) {
if (logger.isDebugEnabled()) {
logger.debug("Could not save Producer property: " + e.getLocalizedMessage());
}
}
}
private void setJmsMessageProperties(Message message, MessageContext synCtx) {
Set<String> properties = synCtx.getPropertyKeySet();
for (String prop : properties) {
if (prop.startsWith(JMS_MSG_P)) {
Object value = synCtx.getProperty(prop);
String key = prop.substring(JMS_MSG_P.length());
try {
if (value instanceof String) {
message.setStringProperty(key, (String) value);
} else if (value instanceof Long) {
message.setLongProperty(key, (Long) value);
} else if (value instanceof Integer) {
message.setIntProperty(key, (Integer) value);
} else if (value instanceof Boolean) {
message.setBooleanProperty(key, (Boolean) value);
} else if (value instanceof Double) {
message.setDoubleProperty(key, (Double) value);
} else if (value instanceof Float) {
message.setFloatProperty(key, (Float) value);
} else if (value instanceof Short) {
message.setShortProperty(key, (Short) value);
}
} catch (JMSException e) {
if (logger.isDebugEnabled()) {
logger.debug("Could not save Message property: " + e.getLocalizedMessage());
}
}
}
}
}
private void setTransportHeaders(Message message, MessageContext synCtx){
//Set transport headers to the message
Map<?,?> headerMap = (Map<?,?>) ((Axis2MessageContext)synCtx).getAxis2MessageContext().getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
if(headerMap != null) {
for (Object headerName : headerMap.keySet()) {
String name = (String) headerName;
Object value = headerMap.get(name);
try {
if (value instanceof String) {
message.setStringProperty(name, (String) value);
} else if (value instanceof Boolean) {
message.setBooleanProperty(name, (Boolean) value);
} else if (value instanceof Integer) {
message.setIntProperty(name, (Integer) value);
} else if (value instanceof Long) {
message.setLongProperty(name, (Long) value);
} else if (value instanceof Double) {
message.setDoubleProperty(name, (Double) value);
} else if (value instanceof Float) {
message.setFloatProperty(name, (Float) value);
}
} catch (JMSException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not save Message property: " + ex.getLocalizedMessage());
}
}
}
}
}
}