You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2014/08/20 05:19:09 UTC

svn commit: r1619026 - in /logging/log4j/log4j2/trunk: log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/ log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/ src/changes/ src/site/xdoc/manual/

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



Re: svn commit: r1619026 - in /logging/log4j/log4j2/trunk: log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/ log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/ src/changes/ src/site/xdoc/manual/

Posted by Ralph Goers <ra...@dslextreme.com>.
Why is the lookup that returns JVM arguments named jmx-input?  That just seems strange.

Ralph

On Aug 19, 2014, at 8:19 PM, ggregory@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-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org