You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2020/02/16 07:38:52 UTC
[logging-log4j2] branch release-2.x updated: LOG4J2-2211 - Allow
Lookup keys with leading dashes by using a slash as an escape character.
This is an automated email from the ASF dual-hosted git repository.
rgoers pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/release-2.x by this push:
new bb17938 LOG4J2-2211 - Allow Lookup keys with leading dashes by using a slash as an escape character.
bb17938 is described below
commit bb1793874d3fada1c55dfe265e7a9d7ed4aa4c74
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Sun Feb 16 00:38:41 2020 -0700
LOG4J2-2211 - Allow Lookup keys with leading dashes by using a slash as an escape character.
---
.../logging/log4j/core/lookup/Interpolator.java | 6 +-
.../logging/log4j/core/lookup/MainMapLookup.java | 8 ++-
.../logging/log4j/core/lookup/StrSubstitutor.java | 75 +++++++++++++++++++---
...pTest.java => MainInputArgumentsLookupApp.java} | 4 +-
.../logging/log4j/core/lookup/MainLookupTest.java | 56 ++++++++++++++++
src/changes/changes.xml | 3 +
src/site/xdoc/manual/configuration.xml.vm | 7 ++
src/site/xdoc/manual/lookups.xml | 14 +++-
8 files changed, 156 insertions(+), 17 deletions(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
index 328b21a..f0c40f5 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
@@ -36,6 +36,9 @@ import org.apache.logging.log4j.util.Constants;
*/
public class Interpolator extends AbstractConfigurationAwareLookup {
+ /** Constant for the prefix separator. */
+ public static final char PREFIX_SEPARATOR = ':';
+
private static final String LOOKUP_KEY_WEB = "web";
private static final String LOOKUP_KEY_DOCKER = "docker";
@@ -50,9 +53,6 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
private static final Logger LOGGER = StatusLogger.getLogger();
- /** Constant for the prefix separator. */
- private static final char PREFIX_SEPARATOR = ':';
-
private final Map<String, StrLookup> strLookupMap = new HashMap<>();
private final StrLookup defaultLookup;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MainMapLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MainMapLookup.java
index 34b2fd3..d90241e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MainMapLookup.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MainMapLookup.java
@@ -64,9 +64,13 @@ public class MainMapLookup extends MapLookup {
* Second using the argument at position n as the key to access the value at n+1.
* </p>
* <ul>
- * <li>{@code "main:--file"} = {@code "path/file.txt"}</li>
- * <li>{@code "main:-x"} = {@code "2"}</li>
+ * <li>{@code "main:\--file"} = {@code "path/file.txt"}</li>
+ * <li>{@code "main:\-x"} = {@code "2"}</li>
* </ul>
+ *<p>Note: Many applications use leading dashes to identify command arguments. Specifying {@code "main:--file}
+ * would result in the lookup failing because it would look for a variable named "main" with a default
+ * value of "-file". To avoid this the ":" separating the Lookup name from the key must be followed by
+ * a backslash as an escape character.</p>
*
* @param args
* An application's {@code public static main(String[])} arguments.
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrSubstitutor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrSubstitutor.java
index 405ca28..33fc535 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrSubstitutor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrSubstitutor.java
@@ -158,7 +158,11 @@ public class StrSubstitutor implements ConfigurationAware {
/**
* Constant for the default value delimiter of a variable.
*/
- public static final StrMatcher DEFAULT_VALUE_DELIMITER = StrMatcher.stringMatcher(":-");
+ public static final String DEFAULT_VALUE_DELIMITER_STRING = ":-";
+ public static final StrMatcher DEFAULT_VALUE_DELIMITER = StrMatcher.stringMatcher(DEFAULT_VALUE_DELIMITER_STRING);
+
+ public static final String ESCAPE_DELIMITER_STRING = ":\\-";
+ public static final StrMatcher DEFAULT_VALUE_ESCAPE_DELIMITER = StrMatcher.stringMatcher(ESCAPE_DELIMITER_STRING);
private static final int BUF_SIZE = 256;
@@ -180,9 +184,15 @@ public class StrSubstitutor implements ConfigurationAware {
/**
* Stores the default variable value delimiter
*/
+ private String valueDelimiterString;
private StrMatcher valueDelimiterMatcher;
/**
+ * Escape string to avoid matching the value delimiter matcher;
+ */
+ private StrMatcher valueEscapeDelimiterMatcher;
+
+ /**
* Variable resolution is delegated to an implementer of VariableResolver.
*/
private StrLookup variableResolver;
@@ -323,7 +333,28 @@ public class StrSubstitutor implements ConfigurationAware {
public StrSubstitutor(final StrLookup variableResolver, final StrMatcher prefixMatcher,
final StrMatcher suffixMatcher,
final char escape) {
- this(variableResolver, prefixMatcher, suffixMatcher, escape, DEFAULT_VALUE_DELIMITER);
+ this(variableResolver, prefixMatcher, suffixMatcher, escape, DEFAULT_VALUE_DELIMITER,
+ DEFAULT_VALUE_ESCAPE_DELIMITER);
+ this.valueDelimiterString = DEFAULT_VALUE_DELIMITER_STRING;
+ }
+
+ /**
+ * Creates a new instance and initializes it.
+ *
+ * @param variableResolver the variable resolver, may be null
+ * @param prefixMatcher the prefix for variables, not null
+ * @param suffixMatcher the suffix for variables, not null
+ * @param escape the escape character
+ * @param valueDelimiterMatcher the variable default value delimiter matcher, may be null
+ * @throws IllegalArgumentException if the prefix or suffix is null
+ */
+ public StrSubstitutor(final StrLookup variableResolver, final StrMatcher prefixMatcher,
+ final StrMatcher suffixMatcher, final char escape, final StrMatcher valueDelimiterMatcher) {
+ this.setVariableResolver(variableResolver);
+ this.setVariablePrefixMatcher(prefixMatcher);
+ this.setVariableSuffixMatcher(suffixMatcher);
+ this.setEscapeChar(escape);
+ this.setValueDelimiterMatcher(valueDelimiterMatcher);
}
/**
@@ -334,15 +365,18 @@ public class StrSubstitutor implements ConfigurationAware {
* @param suffixMatcher the suffix for variables, not null
* @param escape the escape character
* @param valueDelimiterMatcher the variable default value delimiter matcher, may be null
+ * @param valueEscapeMatcher the matcher to escape defaulting, may be null.
* @throws IllegalArgumentException if the prefix or suffix is null
*/
- public StrSubstitutor(
- final StrLookup variableResolver, final StrMatcher prefixMatcher, final StrMatcher suffixMatcher, final char escape, final StrMatcher valueDelimiterMatcher) {
+ public StrSubstitutor(final StrLookup variableResolver, final StrMatcher prefixMatcher,
+ final StrMatcher suffixMatcher, final char escape, final StrMatcher valueDelimiterMatcher,
+ final StrMatcher valueEscapeMatcher) {
this.setVariableResolver(variableResolver);
this.setVariablePrefixMatcher(prefixMatcher);
this.setVariableSuffixMatcher(suffixMatcher);
this.setEscapeChar(escape);
this.setValueDelimiterMatcher(valueDelimiterMatcher);
+ valueEscapeDelimiterMatcher = valueEscapeMatcher;
}
//-----------------------------------------------------------------------
@@ -960,10 +994,32 @@ public class StrSubstitutor implements ConfigurationAware {
&& prefixMatcher.isMatch(varNameExprChars, i, i, varNameExprChars.length) != 0) {
break;
}
- if ((valueDelimiterMatchLen = valueDelimiterMatcher.isMatch(varNameExprChars, i)) != 0) {
- varName = varNameExpr.substring(0, i);
- varDefaultValue = varNameExpr.substring(i + valueDelimiterMatchLen);
- break;
+ if (valueEscapeDelimiterMatcher != null) {
+ int matchLen = valueEscapeDelimiterMatcher.isMatch(varNameExprChars, i);
+ if (matchLen != 0) {
+ String varNamePrefix = varNameExpr.substring(0, i) + Interpolator.PREFIX_SEPARATOR;
+ varName = varNamePrefix + varNameExpr.substring(i + matchLen - 1);
+ for (int j = i + matchLen; j < varNameExprChars.length; ++j){
+ if ((valueDelimiterMatchLen = valueDelimiterMatcher.isMatch(varNameExprChars, j)) != 0) {
+ varName = varNamePrefix + varNameExpr.substring(i + matchLen, j);
+ varDefaultValue = varNameExpr.substring(j + valueDelimiterMatchLen);
+ break;
+ }
+ }
+ break;
+ } else {
+ if ((valueDelimiterMatchLen = valueDelimiterMatcher.isMatch(varNameExprChars, i)) != 0) {
+ varName = varNameExpr.substring(0, i);
+ varDefaultValue = varNameExpr.substring(i + valueDelimiterMatchLen);
+ break;
+ }
+ }
+ } else {
+ if ((valueDelimiterMatchLen = valueDelimiterMatcher.isMatch(varNameExprChars, i)) != 0) {
+ varName = varNameExpr.substring(0, i);
+ varDefaultValue = varNameExpr.substring(i + valueDelimiterMatchLen);
+ break;
+ }
}
}
}
@@ -1294,6 +1350,9 @@ public class StrSubstitutor implements ConfigurationAware {
setValueDelimiterMatcher(null);
return this;
}
+ String escapeValue = valueDelimiter.substring(0, valueDelimiter.length() - 1) + "\\"
+ + valueDelimiter.substring(valueDelimiter.length() - 1);
+ valueEscapeDelimiterMatcher = StrMatcher.stringMatcher(escapeValue);
return setValueDelimiterMatcher(StrMatcher.stringMatcher(valueDelimiter));
}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsLookupApp.java
similarity index 94%
rename from log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsLookupTest.java
rename to log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsLookupApp.java
index 966c6fd..44149a8 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsLookupTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsLookupApp.java
@@ -28,11 +28,11 @@ import org.apache.logging.log4j.core.config.Configurator;
*
* @since 2.4
*/
-public class MainInputArgumentsLookupTest {
+public class MainInputArgumentsLookupApp {
public static void main(final String[] args) {
MainMapLookup.setMainArguments(args);
- try (final LoggerContext ctx = Configurator.initialize(MainInputArgumentsLookupTest.class.getName(),
+ try (final LoggerContext ctx = Configurator.initialize(MainInputArgumentsLookupApp.class.getName(),
"target/test-classes/log4j-lookup-main.xml")) {
LogManager.getLogger().error("this is an error message");
}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainLookupTest.java
new file mode 100644
index 0000000..b019c2a
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainLookupTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.lookup;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests MainLookup.
+ */
+public class MainLookupTest {
+
+ @Test
+ public void testMainArgs(){
+ MainMapLookup.setMainArguments("--file", "foo.txt", "--verbose", "-x", "bar");
+ String str ="${key} ${main:-1} ${main:0} ${main:1} ${main:2} ${main:3} ${main:4} ${main:\\--file} ${main:foo.txt} ${main:\\--verbose} ${main:\\-x} ${main:bar} ${main:\\--quiet:-true}";
+ Map<String, String> properties = new HashMap<String, String>();
+ properties.put("key", "value");
+ properties.put("bar", "default_bar_value");
+ Interpolator lookup = new Interpolator(properties);
+ StrSubstitutor substitutor = new StrSubstitutor(lookup);
+ String replacedValue = substitutor.replace(null, str);
+ String[] values = replacedValue.split(" ");
+ assertEquals("Item 0 is incorrect ", "value", values[0]);
+ assertEquals("Item 1 is incorrect ", "1", values[1]);
+ assertEquals("Item 2 is incorrect", "--file", values[2]);
+ assertEquals("Item 3 is incorrect", "foo.txt", values[3]);
+ assertEquals("Item 4 is incorrect", "--verbose", values[4]);
+ assertEquals("Item 5 is incorrect", "-x", values[5]);
+ assertEquals("Iten 6 is incorrect", "bar", values[6]);
+ assertEquals("Item 7 is incorrect", "foo.txt", values[7]);
+ assertEquals("Item 8 is incorrect", "--verbose", values[8]);
+ assertEquals("Item 9 is incorrect", "-x", values[9]);
+ assertEquals("Item 10 is incorrect", "bar", values[10]);
+ assertEquals("Item 11 is incorrect", "default_bar_value", values[11]);
+ assertEquals("Item 12 is incorrect", "true", values[12]);
+ }
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 72adc8e..cf0f4fd 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,6 +30,9 @@
- "remove" - Removed
-->
<release version="2.13.1" date="2019-MM-DD" description="GA Release 2.13.1">
+ <action issue="LOG4J2-2211" dev="rgoers" type="fix">
+ Allow Lookup keys with leading dashes by using a slash as an escape character.
+ </action>
<action issue="LOG4J2-2782" dev="rgoers" type="update">
Use LinkedBlockingQueue instead of synchronized collction in StatusConfiguration.
</action>
diff --git a/src/site/xdoc/manual/configuration.xml.vm b/src/site/xdoc/manual/configuration.xml.vm
index 9fd2e31..a057ab4 100644
--- a/src/site/xdoc/manual/configuration.xml.vm
+++ b/src/site/xdoc/manual/configuration.xml.vm
@@ -1073,6 +1073,13 @@ rootLogger.appenderRef.stdout.ref = STDOUT
the "contextName" with is the value of the current logging context. See many places
a Properties element is used in this section for examples.
</p>
+ <p>
+ Default properties may also be specified in the Lookup by using the syntax <code>${dollar}{lookupName:key:-defaultValue}</code>.
+ In some cases the key might contain a leading '-'. When this is the case an escape character must be
+ included, such as <code>${dollar}{main:\--file:-app.properties}</code>. This would use the
+ <code>MainMapLookup</code> for a key named <code>--file</code>. If the key is not found then
+ <code>app.properties</code> would be used as the default value.
+ </p>
</subsection>
<a name="RuntimeLookup"/>
<subsection name="Lookup Variables with Multiple Leading '$' Characters">
diff --git a/src/site/xdoc/manual/lookups.xml b/src/site/xdoc/manual/lookups.xml
index 40322bd..a5dbca6 100644
--- a/src/site/xdoc/manual/lookups.xml
+++ b/src/site/xdoc/manual/lookups.xml
@@ -315,6 +315,10 @@ public static void main(String args[]) {
or a string, where <code>${main:myString}</code> is substituted with the value that follows
<code>myString</code> in the main argument list.
</p>
+ Note: Many applications use leading dashes to identify command arguments. Specifying
+ <code>${main:--file}</code> would result in the lookup failing because it would look for a variable
+ named "main" with a default value of "-file". To avoid this the ":" separating the Lookup name from the
+ key must be followed by a backslash as an escape character as in <code>${main:\--file}</code>
<p>
For example, suppose the static void main String[] arguments are:
</p>
@@ -358,13 +362,13 @@ public static void main(String args[]) {
</td>
</tr>
<tr>
- <td>${main:--file}</td>
+ <td>${main:\--file}</td>
<td>
<p><code>foo.txt</code></p>
</td>
</tr>
<tr>
- <td>${main:-x}</td>
+ <td>${main:\-x}</td>
<td>
<p><code>bar</code></p>
</td>
@@ -375,6 +379,12 @@ public static void main(String args[]) {
<p><code>null</code></p>
</td>
</tr>
+ <tr>
+ <td>${main:\--quiet:-true}</td>
+ <td>
+ <p><code>true</code></p>
+ </td>
+ </tr>
</table>
<p>
Example usage: