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    package org.apache.logging.log4j.util;
018    
019    import org.apache.logging.log4j.Logger;
020    import org.apache.logging.log4j.spi.Provider;
021    import org.apache.logging.log4j.status.StatusLogger;
022    
023    import java.io.IOException;
024    import java.net.URL;
025    import java.util.ArrayList;
026    import java.util.Enumeration;
027    import java.util.Iterator;
028    import java.util.List;
029    import java.util.Properties;
030    
031    /**
032     *
033     */
034    public final class ProviderUtil {
035    
036        private static final String PROVIDER_RESOURCE = "META-INF/log4j-provider.properties";
037        private static final String API_VERSION = "Log4jAPIVersion";
038    
039        private static final String[] COMPATIBLE_API_VERSIONS = {
040            "2.0.0"
041        };
042    
043        private static final Logger LOGGER = StatusLogger.getLogger();
044    
045        private static final List<Provider> PROVIDERS = new ArrayList<Provider>();
046    
047        private ProviderUtil() {
048        }
049    
050        static {
051            final ClassLoader cl = findClassLoader();
052            Enumeration<URL> enumResources = null;
053            try {
054                enumResources = cl.getResources(PROVIDER_RESOURCE);
055            } catch (final IOException e) {
056                LOGGER.fatal("Unable to locate " + PROVIDER_RESOURCE, e);
057            }
058    
059            if (enumResources != null) {
060                while (enumResources.hasMoreElements()) {
061                    final Properties props = new Properties();
062                    final URL url = enumResources.nextElement();
063                    try {
064                        props.load(url.openStream());
065                    } catch (final IOException ioe) {
066                        LOGGER.error("Unable to read " + url.toString(), ioe);
067                    }
068                    if (!validVersion(props.getProperty(API_VERSION))) {
069                        continue;
070                    }
071                    PROVIDERS.add(new Provider(props, url));
072                }
073            }
074        }
075    
076        public static Iterator<Provider> getProviders() {
077            return PROVIDERS.iterator();
078        }
079    
080        public static boolean hasProviders() {
081            return PROVIDERS.size() > 0;
082        }
083    
084        public static ClassLoader findClassLoader() {
085            ClassLoader cl;
086            if (System.getSecurityManager() == null) {
087                cl = Thread.currentThread().getContextClassLoader();
088            } else {
089                cl = java.security.AccessController.doPrivileged(
090                    new java.security.PrivilegedAction<ClassLoader>() {
091                        public ClassLoader run() {
092                            return Thread.currentThread().getContextClassLoader();
093                        }
094                    }
095                );
096            }
097            if (cl == null) {
098                cl = ProviderUtil.class.getClassLoader();
099            }
100    
101            return cl;
102        }
103    
104        private static boolean validVersion(final String version) {
105            for (final String v : COMPATIBLE_API_VERSIONS) {
106                if (version.startsWith(v)) {
107                    return true;
108                }
109            }
110            return false;
111        }
112    }