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.cloud.config.client;
018
019import java.io.File;
020import java.io.IOException;
021import java.net.URISyntaxException;
022import java.net.URL;
023import java.net.URLConnection;
024import java.util.Arrays;
025import java.util.List;
026import java.util.Properties;
027import javax.net.ssl.HttpsURLConnection;
028
029import org.apache.logging.log4j.LogManager;
030import org.apache.logging.log4j.Logger;
031import org.apache.logging.log4j.core.LoggerContext;
032import org.apache.logging.log4j.core.config.ConfigurationFactory;
033import org.apache.logging.log4j.core.config.ConfigurationSource;
034import org.apache.logging.log4j.core.net.ssl.LaxHostnameVerifier;
035import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
036import org.apache.logging.log4j.core.net.ssl.SslConfigurationFactory;
037import org.apache.logging.log4j.core.util.AuthorizationProvider;
038import org.apache.logging.log4j.core.util.FileUtils;
039import org.apache.logging.log4j.status.StatusLogger;
040import org.apache.logging.log4j.util.PropertiesUtil;
041import org.springframework.boot.logging.LogFile;
042import org.springframework.boot.logging.LoggingInitializationContext;
043import org.springframework.boot.logging.log4j2.Log4J2LoggingSystem;
044import org.springframework.core.io.ClassPathResource;
045import org.springframework.util.Assert;
046import org.springframework.util.ClassUtils;
047import org.springframework.util.ResourceUtils;
048
049/**
050 *
051 */
052public class Log4j2CloudConfigLoggingSystem extends Log4J2LoggingSystem {
053    private static final String FILE_PROTOCOL = "file";
054    private static final String HTTPS = "https";
055    private Logger LOGGER = StatusLogger.getLogger();
056
057    public Log4j2CloudConfigLoggingSystem(ClassLoader loader) {
058        super(loader);
059    }
060
061    @Override
062    protected String[] getStandardConfigLocations() {
063        String[] locations = super.getStandardConfigLocations();
064        PropertiesUtil props = new PropertiesUtil(new Properties());
065        String location = props.getStringProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
066        if (location != null) {
067            List<String> list = Arrays.asList(super.getStandardConfigLocations());
068            list.add(location);
069            locations = list.toArray(new String[list.size()]);
070        }
071        return locations;
072    }
073
074    @Override
075    protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) {
076        if (logFile != null) {
077            this.loadConfiguration(this.getBootPackagedConfigFile("log4j2-file.xml"), logFile);
078        } else {
079            this.loadConfiguration(this.getBootPackagedConfigFile("log4j2.xml"), logFile);
080        }
081    }
082
083    private String getBootPackagedConfigFile(String fileName) {
084        String defaultPath = ClassUtils.getPackageName(Log4J2LoggingSystem.class);
085        defaultPath = defaultPath.replace('.', '/');
086        defaultPath = defaultPath + "/" + fileName;
087        defaultPath = "classpath:" + defaultPath;
088        return defaultPath;
089    }
090
091    @Override
092    protected void loadConfiguration(String location, LogFile logFile) {
093        Assert.notNull(location, "Location must not be null");
094        try {
095            LoggerContext ctx = getLoggerContext();
096            URL url = ResourceUtils.getURL(location);
097            ConfigurationSource source = getConfigurationSource(url);
098            ctx.start(ConfigurationFactory.getInstance().getConfiguration(ctx, source));
099        }
100        catch (Exception ex) {
101            throw new IllegalStateException(
102                "Could not initialize Log4J2 logging from " + location, ex);
103        }
104    }
105
106    private ConfigurationSource getConfigurationSource(URL url) throws IOException, URISyntaxException {
107        URLConnection urlConnection = url.openConnection();
108        AuthorizationProvider provider = ConfigurationFactory.getAuthorizationProvider();
109        if (provider != null) {
110            provider.addAuthorization(urlConnection);
111        }
112        if (url.getProtocol().equals(HTTPS)) {
113            SslConfiguration sslConfiguration = SslConfigurationFactory.getSslConfiguration();
114            if (sslConfiguration != null) {
115                ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslConfiguration.getSslSocketFactory());
116                if (!sslConfiguration.isVerifyHostName()) {
117                    ((HttpsURLConnection) urlConnection).setHostnameVerifier(LaxHostnameVerifier.INSTANCE);
118                }
119            }
120        }
121        File file = FileUtils.fileFromUri(url.toURI());
122        if (file != null) {
123            return new ConfigurationSource(urlConnection.getInputStream(), FileUtils.fileFromUri(url.toURI()));
124        } else {
125            return new ConfigurationSource(urlConnection.getInputStream(), url, urlConnection.getLastModified());
126        }
127    }
128
129    private LoggerContext getLoggerContext() {
130        return (LoggerContext) LogManager.getContext(false);
131    }
132}