Why is the lookup that returns JVM arguments named jmx-input? That just seems strange.
Ralph On Aug 19, 2014, at 8:19 PM, ggreg...@apache.org wrote: > Author: ggregory > Date: Wed Aug 20 03:19:09 2014 > New Revision: 1619026 > > URL: http://svn.apache.org/r1619026 > Log: > [LOG4J2-771] Add lookup for application main arguments. > [LOG4J2-787] Add lookup for JVM arguments. > > Added: > > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java > (with props) > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java > (with props) > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java > (with props) > Modified: > > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java > > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java > > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java > logging/log4j/log4j2/trunk/src/changes/changes.xml > logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm > logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml > > Modified: > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java?rev=1619026&r1=1619025&r2=1619026&view=diff > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java > (original) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java > Wed Aug 20 03:19:09 2014 > @@ -27,7 +27,7 @@ import org.apache.logging.log4j.core.uti > import org.apache.logging.log4j.status.StatusLogger; > > /** > - * Proxies all the other StrLookups. > + * Proxies all the other {@link StrLookup}s. > */ > public class Interpolator implements StrLookup { > > @@ -72,6 +72,8 @@ public class Interpolator implements Str > // TODO: this ought to use the PluginManager > lookups.put("sys", new SystemPropertiesLookup()); > lookups.put("env", new EnvironmentLookup()); > + lookups.put("main", MapLookup.MAIN_SINGLETON); > + // JNDI > try { > // [LOG4J2-703] We might be on Android > lookups.put("jndi", > @@ -82,6 +84,17 @@ public class Interpolator implements Str > "JNDI lookup class is not available because this JRE does > not support JNDI. JNDI string lookups will not be available, continuing > configuration.", > e); > } > + // JMX input args > + try { > + // We might be on Android > + lookups.put("jmx-input", > + > Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup", > StrLookup.class)); > + } catch (Throwable e) { > + // java.lang.VerifyError: > org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup > + LOGGER.warn( > + "JMX runtime input lookup class is not available because > this JRE does not support JMX. JMX lookups will not be available, continuing > configuration.", > + e); > + } > lookups.put("date", new DateLookup()); > lookups.put("ctx", new ContextMapLookup()); > if (Loader.isClassAvailable("javax.servlet.ServletContext")) { > > Added: > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java?rev=1619026&view=auto > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java > (added) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java > Wed Aug 20 03:19:09 2014 > @@ -0,0 +1,29 @@ > +package org.apache.logging.log4j.core.lookup; > + > +import java.lang.management.ManagementFactory; > +import java.util.List; > +import java.util.Map; > + > +import org.apache.logging.log4j.core.config.plugins.Plugin; > + > +/** > + * Maps JVM input arguments (but not main arguments) using JMX to acquire > JVM arguments. > + * > + * @see java.lang.management.RuntimeMXBean#getInputArguments() > + * @since 2.1 > + */ > +@Plugin(name = "jmx-input", category = "Lookup") > +public class JmxRuntimeInputArgumentsLookup extends MapLookup { > + > + static { > + List<String> argsList = > ManagementFactory.getRuntimeMXBean().getInputArguments(); > + JMX_SINGLETON = new > JmxRuntimeInputArgumentsLookup(MapLookup.toMap(argsList)); > + } > + > + public static final JmxRuntimeInputArgumentsLookup JMX_SINGLETON; > + > + public JmxRuntimeInputArgumentsLookup(Map<String, String> map) { > + super(map); > + } > + > +} > > Propchange: > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Propchange: > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java > ------------------------------------------------------------------------------ > svn:keywords = Id > > Modified: > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java?rev=1619026&r1=1619025&r2=1619026&view=diff > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java > (original) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java > Wed Aug 20 03:19:09 2014 > @@ -16,6 +16,8 @@ > */ > package org.apache.logging.log4j.core.lookup; > > +import java.util.HashMap; > +import java.util.List; > import java.util.Map; > > import org.apache.logging.log4j.core.LogEvent; > @@ -23,25 +25,82 @@ import org.apache.logging.log4j.core.con > import org.apache.logging.log4j.message.MapMessage; > > /** > - * The basis for a lookup based on a Map. > + * A map-based lookup. > */ > @Plugin(name = "map", category = "Lookup") > public class MapLookup implements StrLookup { > - > + > /** > - * Map keys are variable names and value. > + * A singleton used by a main method to save its arguments. > */ > - private final Map<String, String> map; > + static final MapLookup MAIN_SINGLETON = new MapLookup(newMap(0)); > + > + static Map<String, String> initMap(final String[] srcArgs, final > Map<String, String> destMap) { > + for (int i = 0; i < srcArgs.length; i++) { > + final int next = i + 1; > + final String value = srcArgs[i]; > + destMap.put(Integer.toString(i), value); > + destMap.put(value, next < srcArgs.length ? srcArgs[next] : null); > + } > + return destMap; > + } > + > + private static HashMap<String, String> newMap(final int initialCapacity) > { > + return new HashMap<String, String>(initialCapacity); > + } > > /** > - * Creates a new instance backed by a Map. Used by the default lookup. > - * > - * @param map the map of keys to values, may be null > + * An application's {@code public static main(String[])} method calls > this method to make its main arguments > + * available for lookup with the prefix {@code main}. > + * <p> > + * The map provides two kinds of access: First by index, starting at > {@code "0"}, {@code "1"} and so on. For > + * example, the command line {@code --file path/file.txt -x 2} can be > accessed from a configuration file with: > + * </p> > + * <ul> > + * <li>{@code "main:0"} = {@code "--file"}</li> > + * <li>{@code "main:1"} = {@code "path/file.txt"}</li> > + * <li>{@code "main:2"} = {@code "-x"}</li> > + * <li>{@code "main:3"} = {@code "2"}</li> > + * </ul> > + * <p> > + * 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> > + * </ul> > + * > + * @param args > + * An application's {@code public static main(String[])} > arguments. > + * @since 2.1 > */ > - public MapLookup(final Map<String, String> map) { > - this.map = map; > + public static void setMainArguments(final String[] args) { > + if (args == null) { > + return; > + } > + initMap(args, MAIN_SINGLETON.map); > + } > + > + static Map<String, String> toMap(final List<String> args) { > + if (args == null) { > + return null; > + } > + final int size = args.size(); > + return initMap(args.toArray(new String[size]), newMap(size)); > } > > + static Map<String, String> toMap(final String[] args) { > + if (args == null) { > + return null; > + } > + return initMap(args, newMap(args.length)); > + } > + > + /** > + * Map keys are variable names and value. > + */ > + private final Map<String, String> map; > + > /** > * Constructor when used directly as a plugin. > */ > @@ -50,21 +109,13 @@ public class MapLookup implements StrLoo > } > > /** > - * Looks up a String key to a String value using the map. > - * <p> > - * If the map is null, then null is returned. > - * The map result object is converted to a string using toString(). > - * </p> > + * Creates a new instance backed by a Map. Used by the default lookup. > * > - * @param key the key to be looked up, may be null > - * @return the matching value, null if no match > + * @param map > + * the map of keys to values, may be null > */ > - @Override > - public String lookup(final String key) { > - if (map == null) { > - return null; > - } > - return map.get(key); > + public MapLookup(final Map<String, String> map) { > + this.map = map; > } > > @Override > @@ -83,4 +134,23 @@ public class MapLookup implements StrLoo > } > return null; > } > + > + /** > + * Looks up a String key to a String value using the map. > + * <p> > + * If the map is null, then null is returned. The map result object is > converted to a string using toString(). > + * </p> > + * > + * @param key > + * the key to be looked up, may be null > + * @return the matching value, null if no match > + */ > + @Override > + public String lookup(final String key) { > + if (map == null) { > + return null; > + } > + return map.get(key); > + } > + > } > > Added: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java?rev=1619026&view=auto > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java > (added) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java > Wed Aug 20 03:19:09 2014 > @@ -0,0 +1,57 @@ > +/* > + * 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 static org.junit.Assert.assertEquals; > + > +import org.junit.Test; > + > +/** > + * Tests {@link JmxRuntimeInputArgumentsLookup} from the command line, not a > JUnit test. > + * > + * From an IDE or CLI: --file foo.txt > + * > + * @since 2.1 > + */ > +public class MainInputArgumentsJmxLookupTest { > + > + public static void main(String[] args) { > + new MainInputArgumentsJmxLookupTest().callFromMain(); > + } > + > + @Test > + public void testMap() { > + JmxRuntimeInputArgumentsLookup lookup = > JmxRuntimeInputArgumentsLookup.JMX_SINGLETON; > + assertEquals(null, lookup.lookup(null)); > + assertEquals(null, lookup.lookup("X")); > + assertEquals(null, lookup.lookup("foo.txt")); > + } > + > + public void callFromMain() { > + JmxRuntimeInputArgumentsLookup lookup = > JmxRuntimeInputArgumentsLookup.JMX_SINGLETON; > + assertEquals(null, lookup.lookup(null)); > + assertEquals(null, lookup.lookup("X")); > + // Eclipse adds -Dfile.encoding=Cp1252 > + // assertEquals("--file", lookup.lookup("0")); > + // assertEquals("foo.txt", lookup.lookup("1")); > + // > + // JMX does not include the main arguments. > + // assertEquals("foo.txt", lookup.lookup("--file")); > + // assertEquals(null, lookup.lookup("foo.txt")); > + } > + > +} > > Propchange: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Propchange: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java > ------------------------------------------------------------------------------ > svn:keywords = Id > > Added: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java?rev=1619026&view=auto > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java > (added) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java > Wed Aug 20 03:19:09 2014 > @@ -0,0 +1,41 @@ > +package org.apache.logging.log4j.core.lookup; > + > +import java.util.Map; > + > +/** > + * Work in progress, saved for future experimentation. > + * > + * TODO The goal is to use the Sun debugger API to find the main arg values > on the stack. > + */ > +public class MainInputArgumentsMapLookup extends MapLookup { > + > + public static final MainInputArgumentsMapLookup SINGLETON_STACK; > + > + static { > + Map<Thread, StackTraceElement[]> allStackTraces = > Thread.getAllStackTraces(); > + String[] args = null; > + for (Map.Entry<Thread, StackTraceElement[]> entry : > allStackTraces.entrySet()) { > + StackTraceElement[] stackTraceElements = entry.getValue(); > + Thread thread = entry.getKey(); > + // Can't use the thread name to look for "main" since anyone can > set it. > + // Can't use thread ID since it can be any positive value, and > is likely vender dependent. Oracle seems to > + // use 1. > + // We are left to look for "main" at the top of the stack > + if (stackTraceElements != null) { > + final int frame0 = stackTraceElements.length - 1; > + if > ("main".equals(stackTraceElements[frame0].getMethodName())) { > + // We could further validate the main is a public static > void method that takes a String[], if not, > + // look at the other threads. > + // > + // How do we get the main args from the stack with the > debug API? > + // Must we be started in debug mode? Seems like it. > + } > + } > + } > + SINGLETON_STACK = new > MainInputArgumentsMapLookup(MapLookup.toMap(args)); > + } > + > + public MainInputArgumentsMapLookup(Map<String, String> map) { > + super(map); > + } > +} > > Propchange: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Propchange: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java > ------------------------------------------------------------------------------ > svn:keywords = Id > > Modified: > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java?rev=1619026&r1=1619025&r2=1619026&view=diff > ============================================================================== > --- > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java > (original) > +++ > logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java > Wed Aug 20 03:19:09 2014 > @@ -49,4 +49,19 @@ public class MapLookupTest { > assertEquals(null, lookup.lookup(null)); > assertEquals(null, lookup.lookup("X")); > } > + > + @Test > + public void testMainMap() { > + MapLookup.setMainArguments(new String[] { > + "--file", > + "foo.txt" }); > + MapLookup lookup = MapLookup.MAIN_SINGLETON; > + assertEquals(null, lookup.lookup(null)); > + assertEquals(null, lookup.lookup("X")); > + assertEquals("--file", lookup.lookup("0")); > + assertEquals("foo.txt", lookup.lookup("1")); > + assertEquals("foo.txt", lookup.lookup("--file")); > + assertEquals(null, lookup.lookup("foo.txt")); > + } > + > } > > Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1619026&r1=1619025&r2=1619026&view=diff > ============================================================================== > --- logging/log4j/log4j2/trunk/src/changes/changes.xml (original) > +++ logging/log4j/log4j2/trunk/src/changes/changes.xml Wed Aug 20 03:19:09 > 2014 > @@ -21,10 +21,16 @@ > <title>Changes</title> > </properties> > <body> > - <release version="2.?.?" date="2014-??-??" description="Bug fixes and > enhancements"> > + <release version="2.?.?" date="2014-??-??" description="Bug fixes and > enhancements"> > <action issue="LOG4J2-783" dev="rpopma" type="fix" due-to="Minglei Lee"> > PatternLayout should use platform character encoding by default, not > UTF-8. > </action> > + <action issue="LOG4J2-771" dev="ggregory" type="add"> > + Add lookup for application main arguments. > + </action> > + <action issue="LOG4J2-787" dev="ggregory" type="add"> > + Add lookup for JVM arguments. > + </action> > </release> > <release version="2.0.2" date="2014-08-16" description="Bug fixes and > enhancements"> > <action issue="LOG4J2-775" dev="ggregory" type="update"> > > Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm?rev=1619026&r1=1619025&r2=1619026&view=diff > ============================================================================== > --- logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm > (original) > +++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm Wed > Aug 20 03:19:09 2014 > @@ -869,6 +869,14 @@ public class Bar { > <td>System environment variables</td> > </tr> > <tr> > + <td>jmx-input</td> > + <td>A JVM input argument accessed through JMX, but not a > main argument; see <a > href="http://docs.oracle.com/javase/8/docs/api/java/lang/management/RuntimeMXBean.html#getInputArguments--">RuntimeMXBean.html#getInputArguments()</a></td> > + </tr> > + <tr> > + <td>main</td> > + <td>A value set with <a > href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/MapLookup.html#setMainArguments%28java.lang.String[]%29">MapLookup.setMainArguments(String[])</a></td> > + </tr> > + <tr> > <td>map</td> > <td>A value from a MapMessage</td> > </tr> > > Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml > URL: > http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml?rev=1619026&r1=1619025&r2=1619026&view=diff > ============================================================================== > --- logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml (original) > +++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml Wed Aug 20 > 03:19:09 2014 > @@ -98,11 +98,12 @@ > <subsection name="MapLookup"> > <a name="MapLookup"/> > <p> > - The MapLookup serves two purposes. > + The MapLookup serves several purposes. > </p> > <ol> > <li>Provide the base for Properties declared in the > configuration file.</li> > <li>Retrieve values from MapMessages in LogEvents.</li> > + <li>Retrieve values set with <a > href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/MapLookup.html#setMainArguments%28java.lang.String[]%29">MapLookup.setMainArguments(String[])</a></li> > </ol> > <p> > The first item simply means that the MapLookup is used to > substitute properties that are defined > > --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org