Skip to content

Commit 5afac25

Browse files
committed
Rename MonitorUris to MonitorResources
1 parent 23b55a7 commit 5afac25

File tree

22 files changed

+330
-238
lines changed

22 files changed

+330
-238
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.log4j.core;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.awaitility.Awaitility.waitAtMost;
21+
22+
import java.io.IOException;
23+
import java.nio.file.Files;
24+
import java.nio.file.Path;
25+
import java.util.Arrays;
26+
import java.util.Collections;
27+
import java.util.LinkedHashSet;
28+
import java.util.Set;
29+
import java.util.concurrent.TimeUnit;
30+
import java.util.stream.Collectors;
31+
import org.apache.logging.log4j.core.config.Configuration;
32+
import org.apache.logging.log4j.core.config.ConfigurationSource;
33+
import org.apache.logging.log4j.core.config.Configurator;
34+
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
35+
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
36+
import org.apache.logging.log4j.core.config.properties.PropertiesConfiguration;
37+
import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
38+
import org.apache.logging.log4j.core.util.Source;
39+
import org.junit.jupiter.api.Test;
40+
import org.junit.jupiter.api.io.CleanupMode;
41+
import org.junit.jupiter.api.io.TempDir;
42+
43+
public class MonitorResourcesTest {
44+
45+
@Test
46+
void test_reconfiguration(@TempDir(cleanup = CleanupMode.ON_SUCCESS) final Path tempDir) throws IOException {
47+
final ConfigurationBuilder<PropertiesConfiguration> configBuilder =
48+
ConfigurationBuilderFactory.newConfigurationBuilder(PropertiesConfiguration.class);
49+
final Path configFile = tempDir.resolve("log4j.xml");
50+
final Path externalResourceFile1 = tempDir.resolve("external-resource-1.txt");
51+
final Path externalResourceFile2 = tempDir.resolve("external-resource-2.txt");
52+
final ConfigurationSource configSource = new ConfigurationSource(new Source(configFile), new byte[] {}, 0);
53+
final int monitorInterval = 3;
54+
final Configuration config = configBuilder
55+
.setConfigurationSource(configSource)
56+
.setMonitorInterval(String.valueOf(monitorInterval))
57+
.add(configBuilder.newMonitorResource(
58+
externalResourceFile1.toUri().toString()))
59+
.add(configBuilder.newMonitorResource(
60+
externalResourceFile2.toUri().toString()))
61+
.build();
62+
63+
try (final LoggerContext loggerContext = Configurator.initialize(config)) {
64+
assertMonitorResourceFileNames(
65+
loggerContext,
66+
configFile.getFileName().toString(),
67+
externalResourceFile1.getFileName().toString(),
68+
externalResourceFile2.getFileName().toString());
69+
Files.write(externalResourceFile2, Collections.singletonList("a change"));
70+
waitAtMost(2 * monitorInterval, TimeUnit.SECONDS).until(() -> loggerContext.getConfiguration() != config);
71+
}
72+
}
73+
74+
@Test
75+
@LoggerContextSource("config/MonitorResource/log4j.xml")
76+
void test_config_of_type_XML(final LoggerContext loggerContext) {
77+
assertMonitorResourceFileNames(loggerContext, "log4j.xml");
78+
}
79+
80+
@Test
81+
@LoggerContextSource("config/MonitorResource/log4j.json")
82+
void test_config_of_type_JSON(final LoggerContext loggerContext) {
83+
assertMonitorResourceFileNames(loggerContext, "log4j.json");
84+
}
85+
86+
@Test
87+
@LoggerContextSource("config/MonitorResource/log4j.yaml")
88+
void test_config_of_type_YAML(final LoggerContext loggerContext) {
89+
assertMonitorResourceFileNames(loggerContext, "log4j.yaml");
90+
}
91+
92+
@Test
93+
@LoggerContextSource("config/MonitorResource/log4j.properties")
94+
void test_config_of_type_properties(final LoggerContext loggerContext) {
95+
assertMonitorResourceFileNames(loggerContext, "log4j.properties");
96+
}
97+
98+
private static void assertMonitorResourceFileNames(final LoggerContext loggerContext, final String configFileName) {
99+
assertMonitorResourceFileNames(loggerContext, configFileName, "external-file-1.txt", "external-file-2.txt");
100+
}
101+
102+
private static void assertMonitorResourceFileNames(
103+
final LoggerContext loggerContext, final String configFileName, final String... externalResourceFileNames) {
104+
final Set<Source> sources = loggerContext
105+
.getConfiguration()
106+
.getWatchManager()
107+
.getConfigurationWatchers()
108+
.keySet();
109+
final Set<String> actualFileNames =
110+
sources.stream().map(source -> source.getFile().getName()).collect(Collectors.toSet());
111+
final Set<String> expectedFileNames = new LinkedHashSet<>();
112+
expectedFileNames.add(configFileName);
113+
expectedFileNames.addAll(Arrays.asList(externalResourceFileNames));
114+
assertThat(actualFileNames).as("watch manager sources: %s", sources).isEqualTo(expectedFileNames);
115+
}
116+
}

log4j-core-test/src/test/java/org/apache/logging/log4j/core/MonitorUriTest.java

Lines changed: 0 additions & 61 deletions
This file was deleted.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"Configuration": {
3+
"monitorInterval": "30",
4+
"MonitorResources": {
5+
"MonitorResource": [
6+
{
7+
"uri": "file://path/to/external-file-1.txt"
8+
},
9+
{
10+
"uri": "file://path/to/external-file-2.txt"
11+
}
12+
]
13+
}
14+
}
15+
}

src/site/antora/modules/ROOT/examples/manual/configuration/monitoruris.properties renamed to log4j-core-test/src/test/resources/config/MonitorResource/log4j.properties

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616
#
17-
##
1817
monitorInterval = 30
19-
monitorUri.0.uri = to-be-monitored-1.file
20-
monitorUri.1.uri = to-be-monitored-2.file
18+
monitorResources.0.uri = file://path/to/external-file-1.txt
19+
monitorResources.1.uri = file://path/to/external-file-2.txt

src/site/antora/modules/ROOT/examples/manual/configuration/monitoruris.xml renamed to log4j-core-test/src/test/resources/config/MonitorResource/log4j.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
https://logging.apache.org/xml/ns
2222
https://logging.apache.org/xml/ns/log4j-config-2.xsd"
2323
monitorInterval="30">
24-
<MonitorUris>
25-
<Uri uri="to-be-monitored-1.file"/>
26-
<Uri uri="to-be-monitored-2.file"/>
27-
</MonitorUris>
24+
<MonitorResources>
25+
<MonitorResource uri="file://path/to/external-file-1.txt"/>
26+
<MonitorResource uri="file://path/to/external-file-2.txt"/>
27+
</MonitorResources>
2828
</Configuration>

src/site/antora/modules/ROOT/examples/manual/configuration/monitoruris.yaml renamed to log4j-core-test/src/test/resources/config/MonitorResource/log4j.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#
1717
Configuration:
1818
monitorInterval: '30'
19-
MonitorUris:
20-
Uri:
21-
- uri: to-be-monitored-1.file
22-
- uri: to-be-monitored-2.file
19+
MonitorResources:
20+
MonitorResource:
21+
- uri: "file://path/to/external-file-1.txt"
22+
- uri: "file://path/to/external-file-2.txt"

log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.io.InputStream;
2323
import java.lang.ref.WeakReference;
2424
import java.net.URI;
25-
import java.net.URISyntaxException;
2625
import java.util.ArrayList;
2726
import java.util.Arrays;
2827
import java.util.Collection;
@@ -133,7 +132,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
133132
private ConcurrentMap<String, Appender> appenders = new ConcurrentHashMap<>();
134133
private ConcurrentMap<String, LoggerConfig> loggerConfigs = new ConcurrentHashMap<>();
135134
private List<CustomLevelConfig> customLevels = Collections.emptyList();
136-
private List<URI> uris = Collections.emptyList();
135+
private Set<MonitorResource> monitorResources = Collections.emptySet();
137136
private final ConcurrentMap<String, String> propertyMap = new ConcurrentHashMap<>();
138137
private final Interpolator tempLookup = new Interpolator(propertyMap);
139138
private final StrSubstitutor runtimeStrSubstitutor = new RuntimeStrSubstitutor(tempLookup);
@@ -269,7 +268,7 @@ public void initialize() {
269268
setup();
270269
setupAdvertisement();
271270
doConfigure();
272-
watchMonitorUris();
271+
watchMonitorResources();
273272
setState(State.INITIALIZED);
274273
LOGGER.debug("Configuration {} initialized", this);
275274
}
@@ -350,10 +349,10 @@ public void start() {
350349
LOGGER.info("Configuration {} started.", this);
351350
}
352351

353-
private void watchMonitorUris() {
352+
private void watchMonitorResources() {
354353
if (this instanceof Reconfigurable && watchManager.getIntervalSeconds() >= 0) {
355-
uris.stream().forEach(uri -> {
356-
Source source = new Source(uri);
354+
monitorResources.forEach(monitorResource -> {
355+
Source source = new Source(monitorResource.getUri());
357356
final ConfigurationFileWatcher watcher = new ConfigurationFileWatcher(
358357
this, (Reconfigurable) this, listeners, source.getFile().lastModified());
359358
watchManager.watch(source, watcher);
@@ -743,16 +742,16 @@ protected void doConfigure() {
743742
} else if (child.isInstanceOf(AsyncWaitStrategyFactoryConfig.class)) {
744743
final AsyncWaitStrategyFactoryConfig awsfc = child.getObject(AsyncWaitStrategyFactoryConfig.class);
745744
asyncWaitStrategyFactory = awsfc.createWaitStrategyFactory();
746-
} else if (child.isInstanceOf(MonitorUris.class)) {
747-
uris = convertToJavaNetUris(child.getObject(MonitorUris.class).getUris());
745+
} else if (child.isInstanceOf(MonitorResources.class)) {
746+
monitorResources = child.getObject(MonitorResources.class).getResources();
748747
} else {
749748
final List<String> expected = Arrays.asList(
750749
"\"Appenders\"",
751750
"\"Loggers\"",
752751
"\"Properties\"",
753752
"\"Scripts\"",
754753
"\"CustomLevels\"",
755-
"\"MonitorUris\"");
754+
"\"MonitorResources\"");
756755
LOGGER.error(
757756
"Unknown object \"{}\" of type {} is ignored: try nesting it inside one of: {}.",
758757
child.getName(),
@@ -788,18 +787,6 @@ protected void doConfigure() {
788787
setParents();
789788
}
790789

791-
private List<URI> convertToJavaNetUris(final List<Uri> uris) {
792-
final List<URI> javaNetUris = new ArrayList<>();
793-
for (Uri uri : uris) {
794-
try {
795-
javaNetUris.add(new URI(uri.getUri()));
796-
} catch (URISyntaxException e) {
797-
throw new ConfigurationException("Invalid URI provided for MonitorUri " + uri);
798-
}
799-
}
800-
return javaNetUris;
801-
}
802-
803790
public static Level getDefaultLevel() {
804791
final String levelName = PropertiesUtil.getProperties()
805792
.getStringProperty(DefaultConfiguration.DEFAULT_LEVEL, Level.ERROR.name());

log4j-core/src/main/java/org/apache/logging/log4j/core/config/Uri.java renamed to log4j-core/src/main/java/org/apache/logging/log4j/core/config/MonitorResource.java

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,37 @@
1616
*/
1717
package org.apache.logging.log4j.core.config;
1818

19-
import java.util.Objects;
19+
import static java.util.Objects.requireNonNull;
20+
21+
import java.net.URI;
2022
import org.apache.logging.log4j.core.Core;
2123
import org.apache.logging.log4j.core.config.plugins.Plugin;
24+
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
2225
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
23-
import org.apache.logging.log4j.core.config.plugins.PluginValue;
24-
import org.apache.logging.log4j.status.StatusLogger;
2526

2627
/**
27-
* Descriptor of a URI object that is created via configuration.
28+
* Container for the {@code MonitorResource} element.
2829
*/
29-
@Plugin(name = "Uri", category = Core.CATEGORY_NAME, printObject = true)
30-
public final class Uri {
31-
32-
/**
33-
* The empty array.
34-
*/
35-
static final Uri[] EMPTY_ARRAY = {};
30+
@Plugin(name = "MonitorResource", category = Core.CATEGORY_NAME, printObject = true)
31+
public final class MonitorResource {
3632

37-
private final String uri;
33+
private final URI uri;
3834

39-
private Uri(final String uri) {
40-
this.uri = Objects.requireNonNull(uri, "uri is null");
35+
private MonitorResource(final URI uri) {
36+
this.uri = requireNonNull(uri, "uri");
37+
if (!"file".equals(uri.getScheme())) {
38+
final String message =
39+
String.format("Only `file` scheme is supported in monitor resource URIs! Illegal URI: `%s`", uri);
40+
throw new IllegalArgumentException(message);
41+
}
4142
}
4243

43-
/**
44-
* Creates a Uri object.
45-
*
46-
* @param uri the URI.
47-
* @return A Uri object.
48-
*/
4944
@PluginFactory
50-
public static Uri createUri( // @formatter:off
51-
@PluginValue("uri") final String uri) {
52-
// @formatter:on
53-
54-
StatusLogger.getLogger().debug("Creating Uri('{}')", uri);
55-
return new Uri(uri);
45+
public static MonitorResource createMonitorResource(@PluginAttribute("uri") final URI uri) {
46+
return new MonitorResource(uri);
5647
}
5748

58-
/**
59-
* Returns the URI.
60-
*
61-
* @return the URI
62-
*/
63-
public String getUri() {
49+
public URI getUri() {
6450
return uri;
6551
}
6652

@@ -74,15 +60,15 @@ public boolean equals(final Object object) {
7460
if (this == object) {
7561
return true;
7662
}
77-
if (!(object instanceof Uri)) {
63+
if (!(object instanceof MonitorResource)) {
7864
return false;
7965
}
80-
final Uri other = (Uri) object;
66+
final MonitorResource other = (MonitorResource) object;
8167
return this.uri == other.uri;
8268
}
8369

8470
@Override
8571
public String toString() {
86-
return "Uri[" + uri + "]";
72+
return String.format("MonitorResource{%s}", uri);
8773
}
8874
}

0 commit comments

Comments
 (0)