Skip to content

Commit 3f902c5

Browse files
committed
Add PropertyEnvironment to log4j-sdk
This PR creates a simplified version of `PropertyEnvironment` in `log4j-sdk` that supports Spring-like property classes. It provides aggregation features to allow the conversion of multiple properties at once in a typesafe way.
1 parent 1138990 commit 3f902c5

17 files changed

+1209
-1
lines changed

log4j-sdk/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
<scope>test</scope>
6161
</dependency>
6262

63+
<dependency>
64+
<groupId>org.junit.jupiter</groupId>
65+
<artifactId>junit-jupiter-params</artifactId>
66+
<scope>test</scope>
67+
</dependency>
68+
6369
<dependency>
6470
<groupId>org.javassist</groupId>
6571
<artifactId>javassist</artifactId>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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.sdk.env;
18+
19+
/**
20+
* Provides methods to modify the set of {@link PropertySource}s used by a {@link PropertyEnvironment}.
21+
*/
22+
public interface ConfigurablePropertyEnvironment extends PropertyEnvironment {
23+
24+
/**
25+
* Adds a property source to the environment.
26+
* @param source A property source.
27+
*/
28+
void addPropertySource(PropertySource source);
29+
30+
/**
31+
* Removes a property source from the environment.
32+
* @param source A property source.
33+
*/
34+
void removePropertySource(PropertySource source);
35+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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.sdk.env;
18+
19+
import java.lang.annotation.Documented;
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.RetentionPolicy;
23+
import java.lang.annotation.Target;
24+
25+
/**
26+
* Annotates a class or parameter that stores Log4j API configuration properties.
27+
* <p>
28+
* This annotation is required for root property classes.
29+
* </p>
30+
*/
31+
@Documented
32+
@Retention(RetentionPolicy.RUNTIME)
33+
@Target({ElementType.TYPE, ElementType.PARAMETER, ElementType.FIELD})
34+
public @interface Log4jProperty {
35+
36+
/**
37+
* Provides a name for the configuration property.
38+
* <p>
39+
*
40+
* </p>
41+
*/
42+
String name() default "";
43+
44+
/**
45+
* Provides the default value of the property.
46+
* <p>
47+
* This only applies to scalar values.
48+
* </p>
49+
*/
50+
String defaultValue() default "";
51+
}
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
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.sdk.env;
18+
19+
import java.nio.charset.Charset;
20+
import java.time.Duration;
21+
import org.apache.logging.log4j.sdk.env.internal.PropertiesUtilPropertyEnvironment;
22+
import org.jspecify.annotations.Nullable;
23+
24+
/**
25+
* Represents the main access point to Log4j properties.
26+
* <p>
27+
* It provides as typesafe way to access properties stored in multiple {@link PropertySource}s, type conversion
28+
* methods and property aggregation methods (cf. {@link #getProperty(Class)}).
29+
* </p>
30+
*/
31+
public interface PropertyEnvironment {
32+
33+
static PropertyEnvironment getGlobal() {
34+
return PropertiesUtilPropertyEnvironment.INSTANCE;
35+
}
36+
37+
/**
38+
* Gets the named property as a boolean value. If the property matches the string {@code "true"} (case-insensitive),
39+
* then it is returned as the boolean value {@code true}. Any other non-{@code null} text in the property is
40+
* considered {@code false}.
41+
*
42+
* @param name the name of the property to look up
43+
* @return the boolean value of the property or {@code false} if undefined.
44+
*/
45+
default boolean getBooleanProperty(final String name) {
46+
return getBooleanProperty(name, false);
47+
}
48+
49+
/**
50+
* Gets the named property as a boolean value.
51+
*
52+
* @param name the name of the property to look up
53+
* @param defaultValue the default value to use if the property is undefined
54+
* @return the boolean value of the property or {@code defaultValue} if undefined.
55+
*/
56+
@Nullable
57+
Boolean getBooleanProperty(String name, @Nullable Boolean defaultValue);
58+
59+
/**
60+
* Gets the named property as a Charset value.
61+
*
62+
* @param name the name of the property to look up
63+
* @return the Charset value of the property or {@link Charset#defaultCharset()} if undefined.
64+
*/
65+
default Charset getCharsetProperty(final String name) {
66+
return getCharsetProperty(name, Charset.defaultCharset());
67+
}
68+
69+
/**
70+
* Gets the named property as a Charset value.
71+
*
72+
* @param name the name of the property to look up
73+
* @param defaultValue the default value to use if the property is undefined
74+
* @return the Charset value of the property or {@code defaultValue} if undefined.
75+
*/
76+
@Nullable
77+
Charset getCharsetProperty(String name, @Nullable Charset defaultValue);
78+
79+
/**
80+
* Gets the named property as a Class value.
81+
*
82+
* @param name the name of the property to look up
83+
* @return the Class value of the property or {@code null} if it can not be loaded.
84+
*/
85+
default @Nullable Class<?> getClassProperty(final String name) {
86+
return getClassProperty(name, null);
87+
}
88+
89+
/**
90+
* Gets the named property as a Class value.
91+
*
92+
* @param name the name of the property to look up
93+
* @param defaultValue the default value to use if the property is undefined
94+
* @return the Class value of the property or {@code defaultValue} if it can not be loaded.
95+
*/
96+
default @Nullable Class<?> getClassProperty(final String name, final @Nullable Class<?> defaultValue) {
97+
return getClassProperty(name, defaultValue, Object.class);
98+
}
99+
100+
/**
101+
* Gets the named property as a subclass of {@code upperBound}.
102+
*
103+
* @param name the name of the property to look up
104+
* @param defaultValue the default value to use if the property is undefined
105+
* @return the Class value of the property or {@code defaultValue} if it can not be loaded.
106+
*/
107+
<T> @Nullable Class<? extends T> getClassProperty(
108+
String name, @Nullable Class<? extends T> defaultValue, Class<T> upperBound);
109+
110+
/**
111+
* Gets the named property as {@link Duration}.
112+
*
113+
* @param name The property name.
114+
* @return The value of the String as a Duration or {@link Duration#ZERO} if it was undefined or could not be parsed.
115+
*/
116+
default Duration getDurationProperty(final String name) {
117+
return getDurationProperty(name, Duration.ZERO);
118+
}
119+
120+
/**
121+
* Gets the named property as {@link Duration}.
122+
*
123+
* @param name The property name.
124+
* @param defaultValue The default value.
125+
* @return The value of the String as a Duration or {@code defaultValue} if it was undefined or could not be parsed.
126+
*/
127+
Duration getDurationProperty(String name, Duration defaultValue);
128+
129+
/**
130+
* Gets the named property as an integer.
131+
*
132+
* @param name the name of the property to look up
133+
* @return the parsed integer value of the property or {@code 0} if it was undefined or could not be
134+
* parsed.
135+
*/
136+
default int getIntegerProperty(final String name) {
137+
return getIntegerProperty(name, 0);
138+
}
139+
140+
/**
141+
* Gets the named property as an integer.
142+
*
143+
* @param name the name of the property to look up
144+
* @param defaultValue the default value to use if the property is undefined
145+
* @return the parsed integer value of the property or {@code defaultValue} if it was undefined or could not be
146+
* parsed.
147+
*/
148+
Integer getIntegerProperty(String name, Integer defaultValue);
149+
150+
/**
151+
* Gets the named property as a long.
152+
*
153+
* @param name the name of the property to look up
154+
* @return the parsed long value of the property or {@code 0} if it was undefined or could not be
155+
* parsed.
156+
*/
157+
default long getLongProperty(final String name) {
158+
return getLongProperty(name, 0L);
159+
}
160+
161+
/**
162+
* Gets the named property as a long.
163+
*
164+
* @param name the name of the property to look up
165+
* @param defaultValue the default value to use if the property is undefined
166+
* @return the parsed long value of the property or {@code defaultValue} if it was undefined or could not be parsed.
167+
*/
168+
Long getLongProperty(String name, Long defaultValue);
169+
170+
/**
171+
* Gets the named property as a String.
172+
*
173+
* @param name the name of the property to look up
174+
* @return the String value of the property or {@code null} if undefined.
175+
*/
176+
@Nullable
177+
String getStringProperty(String name);
178+
179+
/**
180+
* Gets the named property as a String.
181+
*
182+
* @param name the name of the property to look up
183+
* @param defaultValue the default value to use if the property is undefined
184+
* @return the String value of the property or {@code defaultValue} if undefined.
185+
*/
186+
default String getStringProperty(final String name, final String defaultValue) {
187+
final String prop = getStringProperty(name);
188+
return (prop == null) ? defaultValue : prop;
189+
}
190+
191+
/**
192+
* Binds properties to class {@code T}.
193+
* <p>
194+
* The implementation should at least support binding Java records with a single public constructor and enums.
195+
* </p>
196+
* @param propertyClass a class annotated by {@link Log4jProperty}.
197+
* @return an instance of T with all JavaBean properties bound.
198+
*/
199+
<T> T getProperty(final Class<T> propertyClass);
200+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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.sdk.env;
18+
19+
import org.jspecify.annotations.Nullable;
20+
21+
/**
22+
* Basic interface to retrieve property values.
23+
* <p>
24+
* We can not reuse the property sources from 2.x, since those required some sort of {@code log4j} prefix to be
25+
* included. In 3.x we want to use keys without a prefix.
26+
* </p>
27+
*/
28+
public interface PropertySource {
29+
/**
30+
* Provides the priority of the property source.
31+
* <p>
32+
* Property sources are ordered according to the natural ordering of their priority. Sources with lower
33+
* numerical value take precedence over those with higher numerical value.
34+
* </p>
35+
*
36+
* @return priority value
37+
*/
38+
int getPriority();
39+
40+
/**
41+
* Gets the named property as a String.
42+
*
43+
* @param name the name of the property to look up
44+
* @return the String value of the property or {@code null} if undefined.
45+
*/
46+
@Nullable
47+
String getProperty(String name);
48+
}

0 commit comments

Comments
 (0)