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.spring.boot;
018
019import org.apache.logging.log4j.Logger;
020import org.apache.logging.log4j.core.LogEvent;
021import org.apache.logging.log4j.core.config.plugins.Plugin;
022import org.apache.logging.log4j.core.lookup.StrLookup;
023import org.apache.logging.log4j.status.StatusLogger;
024import org.springframework.core.env.Environment;
025
026import java.util.regex.Matcher;
027import java.util.regex.Pattern;
028
029/**
030 * Lookup for Spring properties.
031 */
032@Plugin(name = "spring", category = StrLookup.CATEGORY)
033public class SpringLookup extends SpringEnvironmentHolder implements StrLookup {
034
035    private static final Logger LOGGER = StatusLogger.getLogger();
036    private static final String ACTIVE = "profiles.active";
037    private static final String DEFAULT = "profiles.default";
038    private static final String PATTERN = "\\[(\\d+?)\\]";
039    private static final Pattern ACTIVE_PATTERN = Pattern.compile(ACTIVE + PATTERN);
040    private static final Pattern DEFAULT_PATTERN = Pattern.compile(DEFAULT + PATTERN);
041
042    public SpringLookup() {
043        getEnvironment();
044    }
045
046    @Override
047    public String lookup(String key) {
048        Environment env = getEnvironment();
049        if (env != null) {
050            String lowerKey = key.toLowerCase();
051            if (lowerKey.startsWith(ACTIVE)) {
052                switch (env.getActiveProfiles().length) {
053                    case 0: {
054                        return null;
055                    }
056                    case 1: {
057                        return env.getActiveProfiles()[0];
058                    }
059                    default: {
060                        Matcher matcher = ACTIVE_PATTERN.matcher(key);
061                        if (matcher.matches()) {
062                            try {
063                                int index = Integer.parseInt(matcher.group(1));
064                                if (index < env.getActiveProfiles().length) {
065                                    return env.getActiveProfiles()[index];
066                                }
067                                LOGGER.warn("Index out of bounds for Spring active profiles: {}", index);
068                                return null;
069                            } catch (Exception ex) {
070                                LOGGER.warn("Unable to parse {} as integer value", matcher.group(1));
071                                return null;
072                            }
073
074                        }
075                        return String.join(",", env.getActiveProfiles());
076                    }
077                }
078            } else if (lowerKey.startsWith(DEFAULT)) {
079                switch (env.getDefaultProfiles().length) {
080                    case 0: {
081                        return null;
082                    }
083                    case 1: {
084                        return env.getDefaultProfiles()[0];
085                    }
086                    default: {
087                        Matcher matcher = DEFAULT_PATTERN.matcher(key);
088                        if (matcher.matches()) {
089                            try {
090                                int index = Integer.parseInt(matcher.group(1));
091                                if (index < env.getDefaultProfiles().length) {
092                                    return env.getDefaultProfiles()[index];
093                                }
094                                LOGGER.warn("Index out of bounds for Spring default profiles: {}", index);
095                                return null;
096                            } catch (Exception ex) {
097                                LOGGER.warn("Unable to parse {} as integer value", matcher.group(1));
098                                return null;
099                            }
100
101                        }
102                        return String.join(",", env.getDefaultProfiles());
103                    }
104                }
105            }
106
107            return env.getProperty(key);
108
109        }
110        return null;
111    }
112
113    @Override
114    public String lookup(LogEvent event, String key) {
115        return lookup((key));
116    }
117}