// Copyright 2010 NexJ Systems Inc. This software is licensed under the terms of the Eclipse Public License 1.0
package nexj.core.rpc.jms;
import java.util.Enumeration;
import javax.jms.JMSException;
import javax.jms.Message;
import nexj.core.meta.integration.channel.jms.MessageQueue;
import nexj.core.rpc.jms.ra.platform.JMSPlatformAdapter;
import nexj.core.util.HashTab;
import nexj.core.util.Logger;
import nexj.core.util.Lookup;
/**
* JMS utility class.
*/
public class JMSUtil
{
//constructors
protected JMSUtil()
{
}
// associations
/**
* The logger.
*/
protected final static Logger s_logger = Logger.getLogger(JMSUtil.class);
// operations
/**
* Uses the MessageProperyUpdater to set new properties on Message.
* @param message The message to set properties on.
* @param updater The updater that sets the properties.
* @throws JMSException
*/
public static void setMessageProperties(Message message, MessagePropertyUpdater updater) throws JMSException
{
Lookup propMap = new HashTab();
for (Enumeration enm = message.getPropertyNames(); enm.hasMoreElements();)
{
String sName = (String)enm.nextElement();
propMap.put(sName, message.getObjectProperty(sName));
}
updater.getProperties(message);
message.clearProperties();
for (Lookup.Iterator itr = propMap.iterator(); itr.hasNext();)
{
itr.next();
message.setObjectProperty((String)itr.getKey(), itr.getValue());
}
updater.setProperties(message);
}
// inner classes
/**
* Interface implemented by strategies for JMS property updating.
*/
public interface MessagePropertyUpdater
{
/**
* Gets the properties from a message.
* @param message The message.
*/
void getProperties(Message message) throws JMSException;
/**
* Sets the properties on a message.
* @param message The message to update.
*/
void setProperties(Message message) throws JMSException;
}
/**
* @return The JMS message id of the message or empty string if a problem occurred.
*/
protected static String getMessageId(Message message)
{
try
{
return message.getJMSMessageID();
}
catch (JMSException e)
{
return "";
}
}
/**
* Returns the maximum error count of message on mq.
* @param mq The MessageQueue of message.
* @param message The Message for which to determine the error count.
* @return The maximum error count.
*/
public static int getMaxErrorCount(MessageQueue mq, Message message) throws JMSException
{
int nMaxErrorCount = mq.getErrorCount();
if (mq.isTransactional())
{
if (nMaxErrorCount > 0 && mq.getErrorQueue() != null)
{
if (message.propertyExists(JMS.MAX_ERROR_COUNT))
{
nMaxErrorCount = message.getIntProperty(JMS.MAX_ERROR_COUNT);
}
}
}
else
{
nMaxErrorCount = 0;
}
return nMaxErrorCount;
}
/**
* Returns the error count of message on mq.
* @param mq The MessageQueue of message.
* @param message The Message for which to determine the error count.
* @param nMaxErrorCount The maximum error count.
* @param bRequired True if a warning should be logged when the error count is not present.
* @return The error count.
*/
public static int getErrorCount(MessageQueue mq, Message message, int nMaxErrorCount, boolean bRequired)
throws JMSException
{
if (mq.isTransactional())
{
if (nMaxErrorCount > 0 && mq.getErrorQueue() != null)
{
if (message.propertyExists(JMS.ERROR_COUNT))
{
return message.getIntProperty(JMS.ERROR_COUNT) + 1;
}
else if (message.propertyExists(JMS.JMS_DELIVERY_COUNT))
{
return message.getIntProperty(JMS.JMS_DELIVERY_COUNT) - 1;
}
else if (message.propertyExists(JMS.JBOSS_REDELIVERY_COUNT))
{
return message.getIntProperty(JMS.JBOSS_REDELIVERY_COUNT);
}
else
{
if (!bRequired)
{
return 0;
}
if (s_logger.isWarnEnabled())
{
s_logger.warn("Unknown error/delivery count in message " +
getMessageId(message) + " from " + mq.getName());
s_logger.dump(message);
}
return Integer.MAX_VALUE - 1;
}
}
else
{
return (nMaxErrorCount > 0) ? nMaxErrorCount - 1 : 0;
}
}
else
{
return 0;
}
}
/**
* Fix the context class loader, depending on the platform.
* @param loader The new context loader to set. Can be null to avoid any change.
* @return The old context class loader, or null if the argument was null.
*/
public static ClassLoader setContextClassLoader(ClassLoader loader)
{
if (loader == null)
{
return null;
}
Thread thread = Thread.currentThread();
ClassLoader oldClassLoader = thread.getContextClassLoader();
thread.setContextClassLoader(loader);
return oldClassLoader;
}
/**
* A method that returns true if connection factory implements a platform adapter.
*
* @param sFactory The message queue name.
* @return True if the connection factory implements a platform adapter.
*/
public static boolean isPlatformAdapter(String sFactory)
{
if (sFactory != null && sFactory.startsWith("class:"))
{
Class factoryClass;
try
{
factoryClass = Class.forName(sFactory.substring("class:".length()), false, JMSUtil.class.getClassLoader());
}
catch (Throwable t)
{
throw new RuntimeException("Invalid connection factory \"" + sFactory + "\"", t);
}
if (JMSPlatformAdapter.class.isAssignableFrom(factoryClass))
{
return true;
}
}
return false;
}
}