    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    }