View Javadoc
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.spring.cloud.config.client;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.net.URISyntaxException;
22  import java.net.URL;
23  import java.net.URLConnection;
24  import java.util.Arrays;
25  import java.util.List;
26  import java.util.Properties;
27  import javax.net.ssl.HttpsURLConnection;
28  
29  import org.apache.logging.log4j.LogManager;
30  import org.apache.logging.log4j.Logger;
31  import org.apache.logging.log4j.core.LoggerContext;
32  import org.apache.logging.log4j.core.config.ConfigurationFactory;
33  import org.apache.logging.log4j.core.config.ConfigurationSource;
34  import org.apache.logging.log4j.core.net.ssl.LaxHostnameVerifier;
35  import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
36  import org.apache.logging.log4j.core.net.ssl.SslConfigurationFactory;
37  import org.apache.logging.log4j.core.util.AuthorizationProvider;
38  import org.apache.logging.log4j.core.util.FileUtils;
39  import org.apache.logging.log4j.status.StatusLogger;
40  import org.apache.logging.log4j.util.PropertiesUtil;
41  import org.springframework.boot.logging.LogFile;
42  import org.springframework.boot.logging.LoggingInitializationContext;
43  import org.springframework.boot.logging.log4j2.Log4J2LoggingSystem;
44  import org.springframework.core.io.ClassPathResource;
45  import org.springframework.util.Assert;
46  import org.springframework.util.ClassUtils;
47  import org.springframework.util.ResourceUtils;
48  
49  /**
50   *
51   */
52  public class Log4j2CloudConfigLoggingSystem extends Log4J2LoggingSystem {
53      private static final String FILE_PROTOCOL = "file";
54      private static final String HTTPS = "https";
55      private Logger LOGGER = StatusLogger.getLogger();
56  
57      public Log4j2CloudConfigLoggingSystem(ClassLoader loader) {
58          super(loader);
59      }
60  
61      @Override
62      protected String[] getStandardConfigLocations() {
63          String[] locations = super.getStandardConfigLocations();
64          PropertiesUtil props = new PropertiesUtil(new Properties());
65          String location = props.getStringProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
66          if (location != null) {
67              List<String> list = Arrays.asList(super.getStandardConfigLocations());
68              list.add(location);
69              locations = list.toArray(new String[list.size()]);
70          }
71          return locations;
72      }
73  
74      @Override
75      protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) {
76          if (logFile != null) {
77              this.loadConfiguration(this.getBootPackagedConfigFile("log4j2-file.xml"), logFile);
78          } else {
79              this.loadConfiguration(this.getBootPackagedConfigFile("log4j2.xml"), logFile);
80          }
81      }
82  
83      private String getBootPackagedConfigFile(String fileName) {
84          String defaultPath = ClassUtils.getPackageName(Log4J2LoggingSystem.class);
85          defaultPath = defaultPath.replace('.', '/');
86          defaultPath = defaultPath + "/" + fileName;
87          defaultPath = "classpath:" + defaultPath;
88          return defaultPath;
89      }
90  
91      @Override
92      protected void loadConfiguration(String location, LogFile logFile) {
93          Assert.notNull(location, "Location must not be null");
94          try {
95              LoggerContext ctx = getLoggerContext();
96              URL url = ResourceUtils.getURL(location);
97              ConfigurationSource source = getConfigurationSource(url);
98              ctx.start(ConfigurationFactory.getInstance().getConfiguration(ctx, source));
99          }
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 }