/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.functional.listener;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import org.mule.runtime.api.util.Preconditions;
import org.mule.runtime.core.api.MuleContext;
import org.mule.runtime.core.api.context.notification.ConnectionNotificationListener;
import org.mule.runtime.core.context.notification.ConnectionNotification;
import org.mule.runtime.core.context.notification.NotificationException;
import org.mule.runtime.core.util.concurrent.Latch;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Listener for connection notifications.
*/
public class ConnectionListener {
private CountDownLatch notificationReceivedLatch = new Latch();
private int timeout = 10000;
private Optional<Long> previousNotificationTimestamp = Optional.empty();
private Optional<Long> minimumTimeBetweenNotifications = Optional.empty();
private int expectedAction = ConnectionNotification.CONNECTION_CONNECTED;
public ConnectionListener(MuleContext muleContext) {
try {
muleContext.registerListener(new ConnectionNotificationListener<ConnectionNotification>() {
@Override
public boolean isBlocking() {
return false;
}
@Override
public void onNotification(ConnectionNotification notification) {
if (notification.getAction() == expectedAction) {
long currentNotificationTimestamp = System.currentTimeMillis();
if (previousNotificationTimestamp.isPresent()) {
long timeBetweenNotifications = currentNotificationTimestamp - previousNotificationTimestamp.get();
if (!minimumTimeBetweenNotifications.isPresent()
|| minimumTimeBetweenNotifications.get() > timeBetweenNotifications) {
minimumTimeBetweenNotifications = Optional.of(timeBetweenNotifications);
}
}
previousNotificationTimestamp = Optional.of(currentNotificationTimestamp);
notificationReceivedLatch.countDown();
}
}
});
} catch (NotificationException e) {
throw new RuntimeException(e);
}
}
public void waitUntilNotificationsAreReceived() {
try {
if (!notificationReceivedLatch.await(timeout, TimeUnit.MILLISECONDS)) {
fail("Expected notifications were not received");
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* @param numberOfExecutionsRequired number of times that the listener must be notified before releasing the latch.
*/
public ConnectionListener setNumberOfExecutionsRequired(int numberOfExecutionsRequired) {
this.notificationReceivedLatch = new CountDownLatch(numberOfExecutionsRequired);
return this;
}
public ConnectionListener setTimeoutInMillis(int timeout) {
this.timeout = timeout;
return this;
}
public ConnectionListener setExpectedAction(int expectedAction) {
this.expectedAction = expectedAction;
return this;
}
/**
* @return resets the listener state so it can be reused
*/
public ConnectionListener reset() {
this.notificationReceivedLatch = new Latch();
return this;
}
/**
* @return the minimum time tracked between all received notifications
* @throws IllegalStateException if there were less than two notifications received
*/
public void assertMinimumTimeBetweenNotifications(long expectedTimeBetweenNotifications) {
Preconditions
.checkState(minimumTimeBetweenNotifications.isPresent(),
"At least two notifications must be received in order to get the minimum time between notifications");
assertThat(minimumTimeBetweenNotifications.get(), greaterThanOrEqualTo(expectedTimeBetweenNotifications));
}
}