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.util;
18  
19  import java.io.IOException;
20  import java.net.URL;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Enumeration;
24  import java.util.Properties;
25  
26  import org.apache.logging.log4j.Logger;
27  import org.apache.logging.log4j.spi.Provider;
28  import org.apache.logging.log4j.status.StatusLogger;
29  
30  /**
31   * <em>Consider this class private.</em>
32   */
33  public final class ProviderUtil {
34  
35      private static final String PROVIDER_RESOURCE = "META-INF/log4j-provider.properties";
36      private static final String API_VERSION = "Log4jAPIVersion";
37  
38      private static final String[] COMPATIBLE_API_VERSIONS = {
39          "2.0.0"
40      };
41  
42      private static final Logger LOGGER = StatusLogger.getLogger();
43  
44      private static final Collection<Provider> PROVIDERS = new ArrayList<Provider>();
45  
46      private ProviderUtil() {
47      }
48  
49      static {
50          final ClassLoader cl = findClassLoader();
51          Enumeration<URL> enumResources = null;
52          try {
53              enumResources = cl.getResources(PROVIDER_RESOURCE);
54          } catch (final IOException e) {
55              LOGGER.fatal("Unable to locate {}", PROVIDER_RESOURCE, e);
56          }
57          loadProviders(enumResources);
58      }
59  
60      protected static void loadProviders(final Enumeration<URL> enumResources) {
61          if (enumResources != null) {
62              while (enumResources.hasMoreElements()) {
63                  final URL url = enumResources.nextElement();
64                  try {
65                      final Properties props = PropertiesUtil.loadClose(url.openStream(), url);
66                      if (!validVersion(props.getProperty(API_VERSION))) {
67                          continue;
68                      }
69                      PROVIDERS.add(new Provider(props, url));
70                  } catch (final IOException ioe) {
71                      LOGGER.error("Unable to open {}", url, ioe);
72                  }
73              }
74          }
75      }
76  
77      public static Iterable<Provider> getProviders() {
78          return PROVIDERS;
79      }
80  
81      public static boolean hasProviders() {
82          return !PROVIDERS.isEmpty();
83      }
84  
85      public static ClassLoader findClassLoader() {
86          ClassLoader cl;
87          if (System.getSecurityManager() == null) {
88              cl = Thread.currentThread().getContextClassLoader();
89          } else {
90              cl = java.security.AccessController.doPrivileged(
91                  new java.security.PrivilegedAction<ClassLoader>() {
92                      @Override
93                      public ClassLoader run() {
94                          return Thread.currentThread().getContextClassLoader();
95                      }
96                  }
97              );
98          }
99          if (cl == null) {
100             cl = ProviderUtil.class.getClassLoader();
101         }
102 
103         return cl;
104     }
105 
106     private static boolean validVersion(final String version) {
107         for (final String v : COMPATIBLE_API_VERSIONS) {
108             if (version.startsWith(v)) {
109                 return true;
110             }
111         }
112         return false;
113     }
114 }