001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j.core.lookup; 018 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.logging.log4j.core.LogEvent; 024import org.apache.logging.log4j.core.config.plugins.Plugin; 025import org.apache.logging.log4j.message.MapMessage; 026 027/** 028 * A map-based lookup. 029 */ 030@Plugin(name = "map", category = StrLookup.CATEGORY) 031public class MapLookup implements StrLookup { 032 033 /** 034 * A singleton used by a main method to save its arguments. 035 */ 036 static final MapLookup MAIN_SINGLETON = new MapLookup(newMap(0)); 037 038 static Map<String, String> initMap(final String[] srcArgs, final Map<String, String> destMap) { 039 for (int i = 0; i < srcArgs.length; i++) { 040 final int next = i + 1; 041 final String value = srcArgs[i]; 042 destMap.put(Integer.toString(i), value); 043 destMap.put(value, next < srcArgs.length ? srcArgs[next] : null); 044 } 045 return destMap; 046 } 047 048 private static HashMap<String, String> newMap(final int initialCapacity) { 049 return new HashMap<String, String>(initialCapacity); 050 } 051 052 /** 053 * An application's {@code public static main(String[])} method calls this method to make its main arguments 054 * available for lookup with the prefix {@code main}. 055 * <p> 056 * The map provides two kinds of access: First by index, starting at {@code "0"}, {@code "1"} and so on. For 057 * example, the command line {@code --file path/file.txt -x 2} can be accessed from a configuration file with: 058 * </p> 059 * <ul> 060 * <li>{@code "main:0"} = {@code "--file"}</li> 061 * <li>{@code "main:1"} = {@code "path/file.txt"}</li> 062 * <li>{@code "main:2"} = {@code "-x"}</li> 063 * <li>{@code "main:3"} = {@code "2"}</li> 064 * </ul> 065 * <p> 066 * Second using the argument at position n as the key to access the value at n+1. 067 * </p> 068 * <ul> 069 * <li>{@code "main:--file"} = {@code "path/file.txt"}</li> 070 * <li>{@code "main:-x"} = {@code "2"}</li> 071 * </ul> 072 * 073 * @param args 074 * An application's {@code public static main(String[])} arguments. 075 * @since 2.1 076 */ 077 public static void setMainArguments(final String[] args) { 078 if (args == null) { 079 return; 080 } 081 initMap(args, MAIN_SINGLETON.map); 082 } 083 084 static Map<String, String> toMap(final List<String> args) { 085 if (args == null) { 086 return null; 087 } 088 final int size = args.size(); 089 return initMap(args.toArray(new String[size]), newMap(size)); 090 } 091 092 static Map<String, String> toMap(final String[] args) { 093 if (args == null) { 094 return null; 095 } 096 return initMap(args, newMap(args.length)); 097 } 098 099 /** 100 * Map keys are variable names and value. 101 */ 102 private final Map<String, String> map; 103 104 /** 105 * Constructor when used directly as a plugin. 106 */ 107 public MapLookup() { 108 this.map = null; 109 } 110 111 /** 112 * Creates a new instance backed by a Map. Used by the default lookup. 113 * 114 * @param map 115 * the map of keys to values, may be null 116 */ 117 public MapLookup(final Map<String, String> map) { 118 this.map = map; 119 } 120 121 @Override 122 public String lookup(final LogEvent event, final String key) { 123 if (map == null && !(event.getMessage() instanceof MapMessage)) { 124 return null; 125 } 126 if (map != null && map.containsKey(key)) { 127 final String obj = map.get(key); 128 if (obj != null) { 129 return obj; 130 } 131 } 132 if (event.getMessage() instanceof MapMessage) { 133 return ((MapMessage) event.getMessage()).get(key); 134 } 135 return null; 136 } 137 138 /** 139 * Looks up a String key to a String value using the map. 140 * <p> 141 * If the map is null, then null is returned. The map result object is converted to a string using toString(). 142 * </p> 143 * 144 * @param key 145 * the key to be looked up, may be null 146 * @return the matching value, null if no match 147 */ 148 @Override 149 public String lookup(final String key) { 150 if (map == null) { 151 return null; 152 } 153 return map.get(key); 154 } 155 156}