/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.soa.esb.notification;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.nio.ByteBuffer;
import javax.jms.DeliveryMode;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.QueueConnection;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.NamingException;
import junit.framework.JUnit4TestAdapter;
import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.rosetta.pooling.ConnectionException;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.helpers.NamingContextException;
import org.jboss.soa.esb.helpers.NamingContextPool;
import org.jboss.soa.esb.message.format.MessageFactory;
import org.jboss.soa.esb.message.format.MessageType;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockejb.jms.MockQueue;
import org.mockejb.jms.MockTopic;
import org.mockejb.jms.QueueConnectionFactoryImpl;
import org.mockejb.jndi.MockContextFactory;
/**
* NotifyQueues unit tests.
* @author <a href="mailto:tom.fennelly@jboss.com">tom.fennelly@jboss.com</a>
* @author <a href="mailto:daniel.bevenius@gmail.com">Daniel Bevenius</a>
*/
public class NotifyQueuesUnitTest {
private Logger log = Logger.getLogger( NotifyQueuesUnitTest.class );
private MockQueue mockQueue1;
private MockQueue mockQueue2;
private NotifyJMS notifyQueues;
private ConfigTree rootEl;
@Before
public void setUp() {
try {
MockContextFactory.setAsInitial();
final Context ctx = NamingContextPool.getNamingContext(null);
try
{
ctx.rebind(NotifyQueues.CONNECTION_FACTORY, new MockQueueConnectionFactory());
}
finally
{
NamingContextPool.releaseNamingContext(ctx) ;
}
rootEl = new ConfigTree("rootEl");
addMessagePropertyConfigs(rootEl);
addQueueConfig(rootEl, "queue1", "false");
addQueueConfig(rootEl, "queue2", "true");
mockQueue1 = createAndBindQueue("queue1");
mockQueue2 = createAndBindQueue("queue2");
notifyQueues = new NotifyQueues(rootEl);
} catch (Exception e) {
e.printStackTrace();
fail("Test setup failed: " + e.getMessage());
}
}
@After
public void tearDown() throws Exception {
MockContextFactory.revertSetAsInitial();
}
@Test
public void test_StringObj() throws Exception {
org.jboss.soa.esb.message.Message message = MessageFactory.getInstance().getMessage(MessageType.JBOSS_XML);
message.getBody().add("Hello".getBytes());
notifyQueues.sendNotification(message);
checkQueueTextMessage(mockQueue1, 0, "Hello");
checkQueueTextMessage(mockQueue2, 0, "Hello");
}
@Test
public void test_NonStringObj() throws Exception {
org.jboss.soa.esb.message.Message message = MessageFactory.getInstance().getMessage(MessageType.JAVA_SERIALIZED);
message.getBody().add(((new Integer(123).toString().getBytes())));
message.getProperties().setProperty(Environment.JMS_NATIVE_MESSAGE_TYPE, NotifyJMS.NativeMessage.object);
notifyQueues.sendNotification(message);
checkQueueObjectMessage(mockQueue1, 0, new Integer(123).toString().getBytes());
checkQueueObjectMessage(mockQueue2, 0, new Integer(123).toString().getBytes());
}
@Test
public void sendNotification_without_body()
{
org.jboss.soa.esb.message.Message message = MessageFactory.getInstance().getMessage(MessageType.JAVA_SERIALIZED);
message.getProperties().setProperty(Environment.JMS_NATIVE_MESSAGE_TYPE, NotifyJMS.NativeMessage.object);
try
{
notifyQueues.sendNotification(message);
} catch (NotificationException e)
{
fail(e.getMessage());
}
}
@Test
public void sendNotification_persistent() throws ConfigurationException, JMSException, ConnectionException
{
assertEquals( DeliveryMode.NON_PERSISTENT, notifyQueues.deliveryModes[0] );
}
@Test
public void sendNotification_priority() throws ConfigurationException, JMSException, ConnectionException
{
assertEquals( 10, notifyQueues.priorities[0] );
}
@Test
public void sendNotification_ttl() throws ConfigurationException, JMSException, ConnectionException
{
assertEquals( 600l, notifyQueues.timeToLives[0] );
}
private void checkQueueTextMessage(MockQueue mockQueue, int messageIdx, String expectedText) throws JMSException {
assertTrue(mockQueue.getMessages().size() > messageIdx);
Message message = mockQueue.getMessageAt(0);
assertTrue(message instanceof TextMessage);
assertEquals(expectedText, ((TextMessage)message).getText());
assertEquals("testpropvalue", message.getStringProperty("testpropname"));
}
private void checkQueueObjectMessage(MockQueue mockQueue, int messageIdx, Object expectedObj) throws JMSException {
assertTrue(mockQueue.getMessages().size() > messageIdx);
Message message = mockQueue.getMessageAt(0);
assertTrue(message instanceof ObjectMessage);
ByteBuffer byteBuffer = ByteBuffer.wrap((byte[]) ((ObjectMessage) message).getObject());
ByteBuffer expectedByteBuffer = ByteBuffer.wrap((byte[]) (expectedObj));
assertEquals(expectedByteBuffer, byteBuffer);
// Note that the property bindings don't seem to work in this test i.e.
// it's returning null but should be returning the same as for a
// TextMessage (See above). This is most likely a mockejb lib issue
// and so we're ignoring it :-)
assertEquals(null, message.getStringProperty("testpropname"));
}
private void addMessagePropertyConfigs(ConfigTree rootEl) {
ConfigTree propEl = new ConfigTree(NotifyJMS.CHILD_MSG_PROP,rootEl);
propEl.setAttribute(NotifyJMS.ATT_PROP_NAME, "testpropname");
propEl.setAttribute(NotifyJMS.ATT_PROP_VALUE, "testpropvalue");
}
private void addQueueConfig(ConfigTree rootEl, String queueName, String persistent) {
ConfigTree queueEl = new ConfigTree(NotifyQueues.CHILD_QUEUE,rootEl);
queueEl.setAttribute( NotifyJMS.PERSISTENT_ATTR, persistent);
queueEl.setAttribute( NotifyJMS.PRIORITY_ATTR, "10");
queueEl.setAttribute( NotifyJMS.TIME_TO_LIVE_ATTR, "600");
queueEl.setAttribute(NotifyJMS.ATT_DEST_NAME, queueName);
}
private MockQueue createAndBindQueue(String queueName) throws NamingException, NamingContextException {
MockQueue mockQueue = new MockQueue(queueName);
final Context ctx = NamingContextPool.getNamingContext(null);
try
{
ctx.rebind(queueName, mockQueue);
}
finally
{
NamingContextPool.releaseNamingContext(ctx) ;
}
return mockQueue;
}
@SuppressWarnings("unused")
private MockTopic createAndBindTopic(String topicName) throws NamingException, NamingContextException {
MockTopic mockTopic = new MockTopic(topicName);
final Context ctx = NamingContextPool.getNamingContext(null);
try
{
ctx.rebind(topicName, mockTopic);
}
finally
{
NamingContextPool.releaseNamingContext(ctx) ;
}
return mockTopic;
}
private static final class MockQueueConnectionFactory extends QueueConnectionFactoryImpl
{
@Override
public QueueConnection createQueueConnection() throws JMSException
{
return (QueueConnection)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {QueueConnection.class},
new MockQueueExceptionHandlerInvocationHandler(super.createQueueConnection())) ;
}
}
private static final class MockQueueExceptionHandlerInvocationHandler implements InvocationHandler
{
private final QueueConnection queueConnection ;
private ExceptionListener exceptionListener ;
MockQueueExceptionHandlerInvocationHandler(final QueueConnection queueConnection)
{
this.queueConnection = queueConnection ;
}
public Object invoke(final Object proxy, final Method method, final Object[] args)
throws Throwable
{
final String methodName = method.getName() ;
if ("setExceptionListener".equals(methodName))
{
exceptionListener = (ExceptionListener)args[0] ;
return null ;
}
else if ("getExceptionListener".equals(methodName))
{
return exceptionListener ;
}
else
{
final Object response = method.invoke(queueConnection, args) ;
if (response instanceof QueueSession)
{
final QueueSession queueSession = (QueueSession)response ;
return (QueueSession)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {QueueSession.class},
new MockQueueSessionInvocationHandler(queueSession)) ;
}
else
{
return response ;
}
}
}
}
private static final class MockQueueSessionInvocationHandler implements InvocationHandler
{
private final QueueSession queueSession ;
MockQueueSessionInvocationHandler(final QueueSession queueSession)
{
this.queueSession = queueSession ;
}
public Object invoke(final Object proxy, final Method method, final Object[] args)
throws Throwable
{
final String methodName = method.getName() ;
if ("recover".equals(methodName))
{
return null ;
}
else
{
return method.invoke(queueSession, args) ;
}
}
}
public static junit.framework.Test suite()
{
return new JUnit4TestAdapter(NotifyQueuesUnitTest.class);
}
}