| /* |
| * 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.logging.log4j.core.util; |
| |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.List; |
| import java.util.Queue; |
| import java.util.TimeZone; |
| import java.util.concurrent.BlockingQueue; |
| import java.util.concurrent.LinkedBlockingQueue; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.apache.logging.log4j.core.config.Configuration; |
| import org.apache.logging.log4j.core.config.ConfigurationListener; |
| import org.apache.logging.log4j.core.config.ConfigurationScheduler; |
| import org.apache.logging.log4j.core.config.DefaultConfiguration; |
| import org.apache.logging.log4j.core.config.HttpWatcher; |
| import org.apache.logging.log4j.core.config.Reconfigurable; |
| import org.apache.logging.log4j.core.net.ssl.TestConstants; |
| import org.apache.logging.log4j.core.time.internal.format.FastDateFormat; |
| import org.apache.logging.log4j.util.PropertiesUtil; |
| import org.junit.After; |
| import org.junit.Assume; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Rule; |
| import org.junit.Test; |
| |
| import com.github.tomakehurst.wiremock.junit.WireMockRule; |
| import com.github.tomakehurst.wiremock.stubbing.StubMapping; |
| |
| import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; |
| import static com.github.tomakehurst.wiremock.client.WireMock.get; |
| import static com.github.tomakehurst.wiremock.client.WireMock.removeStub; |
| import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; |
| import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; |
| import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| |
| /** |
| * Test the WatchManager |
| */ |
| public class WatchHttpTest { |
| |
| private static final String FORCE_RUN_KEY = WatchHttpTest.class.getSimpleName() + ".forceRun"; |
| private final String file = "log4j-test1.xml"; |
| private static FastDateFormat formatter; |
| private static final String XML = "application/xml"; |
| |
| private static final boolean IS_WINDOWS = PropertiesUtil.getProperties().isOsWindows(); |
| |
| @BeforeClass |
| public static void beforeClass() { |
| try { |
| formatter = FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss", TimeZone.getTimeZone("UTC")); |
| } catch (Exception ex) { |
| System.err.println("Unable to create date format."); |
| ex.printStackTrace(); |
| throw ex; |
| } |
| } |
| |
| @Rule |
| public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort() |
| .keystorePath(TestConstants.KEYSTORE_FILE) |
| .keystorePassword(String.valueOf(TestConstants.KEYSTORE_PWD())) |
| .keystoreType(TestConstants.KEYSTORE_TYPE)); |
| |
| @Test |
| public void testWatchManager() throws Exception { |
| BlockingQueue<String> queue = new LinkedBlockingQueue<>(); |
| List<ConfigurationListener> listeners = new ArrayList<>(); |
| listeners.add(new TestConfigurationListener(queue, "log4j-test1.xml")); |
| TimeZone timeZone = TimeZone.getTimeZone("UTC"); |
| Calendar now = Calendar.getInstance(timeZone); |
| Calendar previous = now; |
| previous.add(Calendar.MINUTE, -5); |
| Configuration configuration = new DefaultConfiguration(); |
| Assume.assumeTrue(!IS_WINDOWS || Boolean.getBoolean(FORCE_RUN_KEY)); |
| URL url = new URL("http://localhost:" + wireMockRule.port() + "/log4j-test1.xml"); |
| StubMapping stubMapping = stubFor(get(urlPathEqualTo("/log4j-test1.xml")) |
| .willReturn(aResponse() |
| .withBodyFile(file) |
| .withStatus(200) |
| .withHeader("Last-Modified", formatter.format(previous) + " GMT") |
| .withHeader("Content-Type", XML))); |
| final ConfigurationScheduler scheduler = new ConfigurationScheduler(); |
| scheduler.incrementScheduledItems(); |
| final WatchManager watchManager = new WatchManager(scheduler); |
| watchManager.setIntervalSeconds(1); |
| scheduler.start(); |
| watchManager.start(); |
| try { |
| watchManager.watch(new Source(url.toURI(), previous.getTimeInMillis()), new HttpWatcher(configuration, null, |
| listeners, previous.getTimeInMillis())); |
| final String str = queue.poll(2, TimeUnit.SECONDS); |
| assertNotNull("File change not detected", str); |
| } finally { |
| removeStub(stubMapping); |
| watchManager.stop(); |
| scheduler.stop(); |
| } |
| } |
| |
| @Test |
| public void testNotModified() throws Exception { |
| BlockingQueue<String> queue = new LinkedBlockingQueue<>(); |
| List<ConfigurationListener> listeners = new ArrayList<>(); |
| listeners.add(new TestConfigurationListener(queue, "log4j-test2.xml")); |
| TimeZone timeZone = TimeZone.getTimeZone("UTC"); |
| Calendar now = Calendar.getInstance(timeZone); |
| Calendar previous = now; |
| previous.add(Calendar.MINUTE, -5); |
| Configuration configuration = new DefaultConfiguration(); |
| Assume.assumeTrue(!IS_WINDOWS || Boolean.getBoolean(FORCE_RUN_KEY)); |
| URL url = new URL("http://localhost:" + wireMockRule.port() + "/log4j-test2.xml"); |
| StubMapping stubMapping = stubFor(get(urlPathEqualTo("/log4j-test2.xml")) |
| .willReturn(aResponse() |
| .withBodyFile(file) |
| .withStatus(304) |
| .withHeader("Last-Modified", formatter.format(now) + " GMT") |
| .withHeader("Content-Type", XML))); |
| final ConfigurationScheduler scheduler = new ConfigurationScheduler(); |
| scheduler.incrementScheduledItems(); |
| final WatchManager watchManager = new WatchManager(scheduler); |
| watchManager.setIntervalSeconds(1); |
| scheduler.start(); |
| watchManager.start(); |
| try { |
| watchManager.watch(new Source(url.toURI(), previous.getTimeInMillis()), new HttpWatcher(configuration, null, |
| listeners, previous.getTimeInMillis())); |
| final String str = queue.poll(2, TimeUnit.SECONDS); |
| assertNull("File changed.", str); |
| } finally { |
| removeStub(stubMapping); |
| watchManager.stop(); |
| scheduler.stop(); |
| } |
| } |
| |
| private class TestConfigurationListener implements ConfigurationListener { |
| private final Queue<String> queue; |
| private final String name; |
| |
| public TestConfigurationListener(final Queue<String> queue, String name) { |
| this.queue = queue; |
| this.name = name; |
| } |
| |
| @Override |
| public void onChange(Reconfigurable reconfigurable) { |
| //System.out.println("Reconfiguration detected for " + name); |
| queue.add(name); |
| } |
| } |
| } |