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 */
017
018 package org.apache.logging.log4j.core.config.plugins.visitors;
019
020 import java.lang.annotation.Annotation;
021 import java.lang.reflect.Member;
022 import java.util.Map;
023
024 import org.apache.logging.log4j.Logger;
025 import org.apache.logging.log4j.core.config.plugins.convert.TypeConverters;
026 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
027 import org.apache.logging.log4j.core.util.Assert;
028 import org.apache.logging.log4j.status.StatusLogger;
029 import org.apache.logging.log4j.util.Strings;
030
031 /**
032 * Base class for PluginVisitor implementations. Provides convenience methods as well as all method implementations
033 * other than the {@code visit} method.
034 *
035 * @param <A> the Plugin annotation type.
036 */
037 public abstract class AbstractPluginVisitor<A extends Annotation> implements PluginVisitor<A> {
038
039 protected static final Logger LOGGER = StatusLogger.getLogger();
040
041 protected final Class<A> clazz;
042 protected A annotation;
043 protected String[] aliases;
044 protected Class<?> conversionType;
045 protected StrSubstitutor substitutor;
046 protected Member member;
047
048 /**
049 * This constructor must be overridden by implementation classes as a no-arg constructor.
050 *
051 * @param clazz the annotation class this PluginVisitor is for.
052 */
053 protected AbstractPluginVisitor(final Class<A> clazz) {
054 this.clazz = clazz;
055 }
056
057 @SuppressWarnings("unchecked")
058 @Override
059 public PluginVisitor<A> setAnnotation(final Annotation annotation) {
060 final Annotation a = Assert.requireNonNull(annotation, "No annotation was provided");
061 if (this.clazz.isInstance(a)) {
062 this.annotation = (A) a;
063 }
064 return this;
065 }
066
067 @Override
068 public PluginVisitor<A> setAliases(final String... aliases) {
069 this.aliases = aliases;
070 return this;
071 }
072
073 @Override
074 public PluginVisitor<A> setConversionType(final Class<?> conversionType) {
075 this.conversionType = Assert.requireNonNull(conversionType, "No conversion type class was provided");
076 return this;
077 }
078
079 @Override
080 public PluginVisitor<A> setStrSubstitutor(final StrSubstitutor substitutor) {
081 this.substitutor = Assert.requireNonNull(substitutor, "No StrSubstitutor was provided");
082 return this;
083 }
084
085 @Override
086 public PluginVisitor<A> setMember(final Member member) {
087 this.member = member;
088 return this;
089 }
090
091 /**
092 * Removes an Entry from a given Map using a key name and aliases for that key. Keys are case-insensitive.
093 *
094 * @param attributes the Map to remove an Entry from.
095 * @param name the key name to look up.
096 * @param aliases optional aliases of the key name to look up.
097 * @return the value corresponding to the given key or {@code null} if nonexistent.
098 */
099 protected static String removeAttributeValue(final Map<String, String> attributes,
100 final String name,
101 final String... aliases) {
102 for (final Map.Entry<String, String> entry : attributes.entrySet()) {
103 final String key = entry.getKey();
104 final String value = entry.getValue();
105 if (key.equalsIgnoreCase(name)) {
106 attributes.remove(key);
107 return value;
108 }
109 if (aliases != null) {
110 for (final String alias : aliases) {
111 if (key.equalsIgnoreCase(alias)) {
112 attributes.remove(key);
113 return value;
114 }
115 }
116 }
117 }
118 return null;
119 }
120
121 /**
122 * Converts the given value into the configured type falling back to the provided default value.
123 *
124 * @param value the value to convert.
125 * @param defaultValue the fallback value to use in case of no value or an error.
126 * @return the converted value whether that be based on the given value or the default value.
127 */
128 protected Object convert(final String value, final Object defaultValue) {
129 if (defaultValue instanceof String) {
130 return TypeConverters.convert(value, this.conversionType, Strings.trimToNull((String) defaultValue));
131 }
132 return TypeConverters.convert(value, this.conversionType, defaultValue);
133 }
134 }