/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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.qpid.jms.discovery; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileOutputStream; import java.net.URI; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.jms.Connection; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Session; import org.apache.qpid.jms.JmsConnection; import org.apache.qpid.jms.JmsConnectionFactory; import org.apache.qpid.jms.JmsConnectionListener; import org.apache.qpid.jms.message.JmsInboundMessageDispatch; import org.apache.qpid.jms.support.AmqpTestSupport; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Test that the file watcher Discovery Provider finds a broker URI in * the file it is directed to watch. */ public class FileWatcherDiscoveryTest extends AmqpTestSupport { private static final Logger LOG = LoggerFactory.getLogger(FileWatcherDiscoveryTest.class); @Rule public TemporaryFolder folder = new TemporaryFolder(new File("./target")); private CountDownLatch connected; private CountDownLatch interrupted; private CountDownLatch restored; private JmsConnection jmsConnection; private File primaryBrokerList; private File secondaryBrokerList; @Override @Before public void setUp() throws Exception { super.setUp(); connected = new CountDownLatch(1); interrupted = new CountDownLatch(1); restored = new CountDownLatch(1); primaryBrokerList = folder.newFile("primaryBrokerURIsFile.txt"); secondaryBrokerList = folder.newFile("secondaryBrokerURIsFile.txt"); LOG.info("Broker URIs going to file: {}", primaryBrokerList); writeOutBrokerURIsToFile(primaryBrokerList); } @Test(timeout = 60000) public void testConnectedToStoredBrokerURI() throws Exception { assertTrue(primaryBrokerList.exists()); connection = createConnection(); connection.start(); assertTrue("connection never connected.", connected.await(30, TimeUnit.SECONDS)); } @Test(timeout = 60000) public void testReconnectWhenURIUpdates() throws Exception { assertTrue(primaryBrokerList.exists()); connection = createConnection(); connection.start(); assertTrue("connection never connected.", connected.await(30, TimeUnit.SECONDS)); stopPrimaryBroker(); assertTrue("connection should be interrupted.", interrupted.await(30, TimeUnit.SECONDS)); startPrimaryBroker(); writeOutBrokerURIsToFile(primaryBrokerList); assertTrue("connection should have been reestablished.", restored.await(30, TimeUnit.SECONDS)); } @Test(timeout = 60000) public void testReconnectUsingTwoFiles() throws Exception { assertTrue(primaryBrokerList.exists()); assertTrue(secondaryBrokerList.exists()); connection = createConnection(new File[]{ primaryBrokerList, secondaryBrokerList }); connection.start(); assertTrue("connection never connected.", connected.await(30, TimeUnit.SECONDS)); stopPrimaryBroker(); assertTrue("connection should be interrupted.", interrupted.await(30, TimeUnit.SECONDS)); startPrimaryBroker(); writeOutBrokerURIsToFile(secondaryBrokerList); assertTrue("connection should have been reestablished.", restored.await(30, TimeUnit.SECONDS)); } @Test(timeout = 60000) public void testWithInitiallyNonExistingFile() throws Exception { assertTrue(primaryBrokerList.exists()); final String FILENAME = "nonExistentFile.txt"; File nonExistentFile = new File(folder.getRoot(), FILENAME); assertFalse(nonExistentFile.exists()); connection = createConnection(new File[]{ primaryBrokerList, nonExistentFile }); connection.start(); assertTrue("connection never connected.", connected.await(30, TimeUnit.SECONDS)); stopPrimaryBroker(); assertTrue("connection should be interrupted.", interrupted.await(30, TimeUnit.SECONDS)); startPrimaryBroker(); folder.newFile(FILENAME); assertTrue(nonExistentFile.exists()); writeOutBrokerURIsToFile(nonExistentFile); assertTrue("connection should have been reestablished.", restored.await(30, TimeUnit.SECONDS)); } protected Connection createConnection() throws Exception { return createConnection(new File[]{ primaryBrokerList }); } protected Connection createConnection(File[] filesToWatch) throws Exception { StringBuilder fileURIs = new StringBuilder(); for (File file : filesToWatch) { if (fileURIs.length() == 0) { fileURIs.append(file.toURI()); fileURIs.append("?updateInterval=1000"); } else { fileURIs.append(","); fileURIs.append(file.toURI()); fileURIs.append("?updateInterval=1000"); } } JmsConnectionFactory factory = new JmsConnectionFactory( "discovery:(" + fileURIs.toString() + ")?discovery.maxReconnectDelay=500"); connection = factory.createConnection(); jmsConnection = (JmsConnection) connection; jmsConnection.addConnectionListener(new JmsConnectionListener() { @Override public void onConnectionEstablished(URI remoteURI) { LOG.info("Connection reports established. Connected to -> {}", remoteURI); connected.countDown(); } @Override public void onConnectionInterrupted(URI remoteURI) { LOG.info("Connection reports interrupted. Lost connection to -> {}", remoteURI); interrupted.countDown(); } @Override public void onConnectionRestored(URI remoteURI) { LOG.info("Connection reports restored. Connected to -> {}", remoteURI); restored.countDown(); } @Override public void onConnectionFailure(Throwable error) { } @Override public void onInboundMessage(JmsInboundMessageDispatch envelope) { } @Override public void onSessionClosed(Session session, Throwable exception) { } @Override public void onConsumerClosed(MessageConsumer consumer, Throwable cause) { } @Override public void onProducerClosed(MessageProducer producer, Throwable cause) { } @Override public void onRemoteDiscovery(List<URI> remotes) { } }); return connection; } protected void writeOutBrokerURIsToFile(File targetFile) throws Exception { try (FileOutputStream out = new FileOutputStream(targetFile);) { for (URI brokerURI : getBrokerURIs()) { LOG.info("Broker URI being written: {}", brokerURI); out.write(brokerURI.toString().getBytes("UTF-8")); } } } }