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.util;
018
019import java.io.IOException;
020import java.net.URL;
021import java.util.ArrayList;
022import java.util.Enumeration;
023import java.util.Iterator;
024import java.util.List;
025import java.util.Properties;
026
027import org.apache.logging.log4j.Logger;
028import org.apache.logging.log4j.spi.Provider;
029import org.apache.logging.log4j.status.StatusLogger;
030
031/**
032 *
033 */
034public 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 URL url = enumResources.nextElement();
062                Properties props;
063                try {
064                    props = PropertiesUtil.loadClose(url.openStream(), url);
065                    if (!validVersion(props.getProperty(API_VERSION))) {
066                        continue;
067                    }
068                    PROVIDERS.add(new Provider(props, url));
069                } catch (final IOException ioe) {
070                    LOGGER.error("Unable to open " + url.toString(), ioe);
071                }
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                    @Override
092                    public ClassLoader run() {
093                        return Thread.currentThread().getContextClassLoader();
094                    }
095                }
096            );
097        }
098        if (cl == null) {
099            cl = ProviderUtil.class.getClassLoader();
100        }
101
102        return cl;
103    }
104
105    private static boolean validVersion(final String version) {
106        for (final String v : COMPATIBLE_API_VERSIONS) {
107            if (version.startsWith(v)) {
108                return true;
109            }
110        }
111        return false;
112    }
113}