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.util; 18 19 import java.io.Serializable; 20 import java.util.ArrayList; 21 import java.util.List; 22 import java.util.Map; 23 import java.util.Objects; 24 import java.util.concurrent.ConcurrentHashMap; 25 import java.util.regex.Matcher; 26 import java.util.regex.Pattern; 27 28 /** 29 * A source for global configuration properties. 30 * 31 * @since 2.10.0 32 */ 33 public interface PropertySource { 34 35 /** 36 * Returns the order in which this PropertySource has priority. A higher value means that the source will be 37 * applied later so as to take precedence over other property sources. 38 * 39 * @return priority value 40 */ 41 int getPriority(); 42 43 /** 44 * Iterates over all properties and performs an action for each key/value pair. 45 * 46 * @param action action to perform on each key/value pair 47 */ 48 default void forEach(BiConsumer<String, String> action) { 49 } 50 51 /** 52 * Converts a list of property name tokens into a normal form. For example, a list of tokens such as 53 * "foo", "bar", "baz", might be normalized into the property name "log4j2.fooBarBaz". 54 * 55 * @param tokens list of property name tokens 56 * @return a normalized property name using the given tokens 57 */ 58 default CharSequence getNormalForm(Iterable<? extends CharSequence> tokens) { 59 return null; 60 } 61 62 /** 63 * For PropertySources that cannot iterate over all the potential properties this provides a direct lookup. 64 * @param key The key to search for. 65 * @return The value or null; 66 * @since 2.13.0 67 */ 68 default String getProperty(String key) { 69 return null; 70 } 71 72 73 /** 74 * For PropertySources that cannot iterate over all the potential properties this provides a direct lookup. 75 * @param key The key to search for. 76 * @return The value or null; 77 * @since 2.13.0 78 */ 79 default boolean containsProperty(String key) { 80 return false; 81 } 82 83 /** 84 * Comparator for ordering PropertySource instances by priority. 85 * 86 * @since 2.10.0 87 */ 88 class Comparator implements java.util.Comparator<PropertySource>, Serializable { 89 private static final long serialVersionUID = 1L; 90 91 @Override 92 public int compare(final PropertySource o1, final PropertySource o2) { 93 return Integer.compare(Objects.requireNonNull(o1).getPriority(), Objects.requireNonNull(o2).getPriority()); 94 } 95 } 96 97 /** 98 * Utility methods useful for PropertySource implementations. 99 * 100 * @since 2.10.0 101 */ 102 final class Util { 103 private static final String PREFIXES = "(?i:^log4j2?[-._/]?|^org\\.apache\\.logging\\.log4j\\.)?"; 104 private static final Pattern PROPERTY_TOKENIZER = Pattern.compile(PREFIXES + "([A-Z]*[a-z0-9]+|[A-Z0-9]+)[-._/]?"); 105 private static final Map<CharSequence, List<CharSequence>> CACHE = new ConcurrentHashMap<>(); 106 107 /** 108 * Converts a property name string into a list of tokens. This will strip a prefix of {@code log4j}, 109 * {@code log4j2}, {@code Log4j}, or {@code org.apache.logging.log4j}, along with separators of 110 * dash {@code -}, dot {@code .}, underscore {@code _}, and slash {@code /}. Tokens can also be separated 111 * by camel case conventions without needing a separator character in between. 112 * 113 * @param value property name 114 * @return the property broken into lower case tokens 115 */ 116 public static List<CharSequence> tokenize(final CharSequence value) { 117 if (CACHE.containsKey(value)) { 118 return CACHE.get(value); 119 } 120 final List<CharSequence> tokens = new ArrayList<>(); 121 final Matcher matcher = PROPERTY_TOKENIZER.matcher(value); 122 while (matcher.find()) { 123 tokens.add(matcher.group(1).toLowerCase()); 124 } 125 CACHE.put(value, tokens); 126 return tokens; 127 } 128 129 /** 130 * Joins a list of strings using camelCaseConventions. 131 * 132 * @param tokens tokens to convert 133 * @return tokensAsCamelCase 134 */ 135 public static CharSequence joinAsCamelCase(final Iterable<? extends CharSequence> tokens) { 136 final StringBuilder sb = new StringBuilder(); 137 boolean first = true; 138 for (final CharSequence token : tokens) { 139 if (first) { 140 sb.append(token); 141 } else { 142 sb.append(Character.toUpperCase(token.charAt(0))); 143 if (token.length() > 1) { 144 sb.append(token.subSequence(1, token.length())); 145 } 146 } 147 first = false; 148 } 149 return sb.toString(); 150 } 151 152 private Util() { 153 } 154 } 155 }