package org.apache.logging.log4j.core.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
import org.apache.logging.log4j.core.config.plugins.util.PluginType;
import org.apache.logging.log4j.core.lookup.Interpolator;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;
import org.apache.logging.log4j.core.util.FileUtils;
import org.apache.logging.log4j.core.util.Loader;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.PropertiesUtil;

public abstract class ConfigurationFactory {
   public static final String CONFIGURATION_FACTORY_PROPERTY = "log4j.configurationFactory";
   public static final String CONFIGURATION_FILE_PROPERTY = "log4j.configurationFile";
   protected static final Logger LOGGER = StatusLogger.getLogger();
   protected static final String TEST_PREFIX = "log4j2-test";
   protected static final String DEFAULT_PREFIX = "log4j2";
   private static final String CLASS_LOADER_SCHEME = "classloader";
   private static final String CLASS_PATH_SCHEME = "classpath";
   private static volatile List<ConfigurationFactory> factories = null;
   private static ConfigurationFactory configFactory = new ConfigurationFactory.Factory();
   protected final StrSubstitutor substitutor = new StrSubstitutor(new Interpolator());
   private static final Lock LOCK = new ReentrantLock();

   public static ConfigurationFactory getInstance() {
      if (factories == null) {
         LOCK.lock();

         try {
            if (factories == null) {
               List<ConfigurationFactory> list = new ArrayList();
               String factoryClass = PropertiesUtil.getProperties().getStringProperty("log4j.configurationFactory");
               if (factoryClass != null) {
                  addFactory(list, (String)factoryClass);
               }

               PluginManager manager = new PluginManager("ConfigurationFactory");
               manager.collectPlugins();
               Map<String, PluginType<?>> plugins = manager.getPlugins();
               Collection<ConfigurationFactory.WeightedFactory> ordered = new TreeSet();
               Iterator i$ = plugins.values().iterator();

               while(i$.hasNext()) {
                  PluginType type = (PluginType)i$.next();

                  try {
                     Class<ConfigurationFactory> clazz = type.getPluginClass();
                     Order order = (Order)clazz.getAnnotation(Order.class);
                     if (order != null) {
                        int weight = order.value();
                        ordered.add(new ConfigurationFactory.WeightedFactory(weight, clazz));
                     }
                  } catch (Exception var13) {
                     LOGGER.warn("Unable to add class {}", type.getPluginClass(), var13);
                  }
               }

               i$ = ordered.iterator();

               while(i$.hasNext()) {
                  ConfigurationFactory.WeightedFactory wf = (ConfigurationFactory.WeightedFactory)i$.next();
                  addFactory(list, (Class)wf.factoryClass);
               }

               factories = Collections.unmodifiableList(list);
            }
         } finally {
            LOCK.unlock();
         }
      }

      LOGGER.debug("Using configurationFactory {}", configFactory);
      return configFactory;
   }

   private static void addFactory(Collection<ConfigurationFactory> list, String factoryClass) {
      try {
         addFactory(list, Loader.loadClass(factoryClass));
      } catch (Exception var3) {
         LOGGER.error("Unable to load class {}", factoryClass, var3);
      }

   }

   private static void addFactory(Collection<ConfigurationFactory> list, Class<ConfigurationFactory> factoryClass) {
      try {
         list.add(factoryClass.getConstructor().newInstance());
      } catch (Exception var3) {
         LOGGER.error("Unable to create instance of {}", factoryClass.getName(), var3);
      }

   }

   public static void setConfigurationFactory(ConfigurationFactory factory) {
      configFactory = factory;
   }

   public static void resetConfigurationFactory() {
      configFactory = new ConfigurationFactory.Factory();
   }

   public static void removeConfigurationFactory(ConfigurationFactory factory) {
      if (configFactory == factory) {
         configFactory = new ConfigurationFactory.Factory();
      }

   }

   protected abstract String[] getSupportedTypes();

   protected boolean isActive() {
      return true;
   }

   public abstract Configuration getConfiguration(ConfigurationSource var1);

   public Configuration getConfiguration(String name, URI configLocation) {
      if (!this.isActive()) {
         return null;
      } else {
         if (configLocation != null) {
            ConfigurationSource source = this.getInputFromUri(configLocation);
            if (source != null) {
               return this.getConfiguration(source);
            }
         }

         return null;
      }
   }

   protected ConfigurationSource getInputFromUri(URI configLocation) {
      File configFile = FileUtils.fileFromUri(configLocation);
      if (configFile != null && configFile.exists() && configFile.canRead()) {
         try {
            return new ConfigurationSource(new FileInputStream(configFile), configFile);
         } catch (FileNotFoundException var11) {
            LOGGER.error("Cannot locate file {}", configLocation.getPath(), var11);
         }
      }

      String scheme = configLocation.getScheme();
      boolean isClassLoaderScheme = scheme != null && scheme.equals("classloader");
      boolean isClassPathScheme = scheme != null && !isClassLoaderScheme && scheme.equals("classpath");
      if (scheme == null || isClassLoaderScheme || isClassPathScheme) {
         ClassLoader loader = Loader.getThreadContextClassLoader();
         String path;
         if (!isClassLoaderScheme && !isClassPathScheme) {
            path = configLocation.getPath();
         } else {
            path = configLocation.getSchemeSpecificPart();
         }

         ConfigurationSource source = this.getInputFromResource(path, loader);
         if (source != null) {
            return source;
         }
      }

      if (!configLocation.isAbsolute()) {
         LOGGER.error("File not found in file system or classpath: {}", configLocation.toString());
         return null;
      } else {
         try {
            return new ConfigurationSource(configLocation.toURL().openStream(), configLocation.toURL());
         } catch (MalformedURLException var9) {
            LOGGER.error("Invalid URL {}", configLocation.toString(), var9);
         } catch (Exception var10) {
            LOGGER.error("Unable to access {}", configLocation.toString(), var10);
         }

         return null;
      }
   }

   protected ConfigurationSource getInputFromString(String config, ClassLoader loader) {
      try {
         URL url = new URL(config);
         return new ConfigurationSource(url.openStream(), FileUtils.fileFromUri(url.toURI()));
      } catch (Exception var7) {
         ConfigurationSource source = this.getInputFromResource(config, loader);
         if (source == null) {
            try {
               File file = new File(config);
               return new ConfigurationSource(new FileInputStream(file), file);
            } catch (FileNotFoundException var6) {
               LOGGER.catching(Level.DEBUG, var6);
            }
         }

         return source;
      }
   }

   protected ConfigurationSource getInputFromResource(String resource, ClassLoader loader) {
      URL url = Loader.getResource(resource, loader);
      if (url == null) {
         return null;
      } else {
         InputStream is = null;

         try {
            is = url.openStream();
         } catch (IOException var6) {
            LOGGER.catching(Level.DEBUG, var6);
            return null;
         }

         if (is == null) {
            return null;
         } else {
            if (FileUtils.isFile(url)) {
               try {
                  return new ConfigurationSource(is, FileUtils.fileFromUri(url.toURI()));
               } catch (URISyntaxException var7) {
                  LOGGER.catching(Level.DEBUG, var7);
               }
            }

            return new ConfigurationSource(is, url);
         }
      }
   }

   private static class Factory extends ConfigurationFactory {
      private Factory() {
      }

      public Configuration getConfiguration(String name, URI configLocation) {
         if (configLocation == null) {
            String config = this.substitutor.replace(PropertiesUtil.getProperties().getStringProperty("log4j.configurationFile"));
            if (config != null) {
               ConfigurationSource source = null;

               try {
                  source = this.getInputFromUri(FileUtils.getCorrectedFilePathUri(config));
               } catch (Exception var13) {
                  LOGGER.catching(Level.DEBUG, var13);
               }

               if (source == null) {
                  ClassLoader loader = this.getClass().getClassLoader();
                  source = this.getInputFromString(config, loader);
               }

               if (source != null) {
                  Iterator i$ = ConfigurationFactory.factories.iterator();

                  label94:
                  while(true) {
                     ConfigurationFactory factory;
                     String[] types;
                     do {
                        if (!i$.hasNext()) {
                           break label94;
                        }

                        factory = (ConfigurationFactory)i$.next();
                        types = factory.getSupportedTypes();
                     } while(types == null);

                     String[] arr$ = types;
                     int len$ = types.length;

                     for(int i$ = 0; i$ < len$; ++i$) {
                        String type = arr$[i$];
                        if (type.equals("*") || config.endsWith(type)) {
                           Configuration c = factory.getConfiguration(source);
                           if (c != null) {
                              return c;
                           }
                        }
                     }
                  }
               }
            }
         } else {
            Iterator i$ = ConfigurationFactory.factories.iterator();

            label75:
            while(true) {
               ConfigurationFactory factory;
               String[] types;
               do {
                  if (!i$.hasNext()) {
                     break label75;
                  }

                  factory = (ConfigurationFactory)i$.next();
                  types = factory.getSupportedTypes();
               } while(types == null);

               String[] arr$ = types;
               int len$ = types.length;

               for(int i$ = 0; i$ < len$; ++i$) {
                  String type = arr$[i$];
                  if (type.equals("*") || configLocation.toString().endsWith(type)) {
                     Configuration config = factory.getConfiguration(name, configLocation);
                     if (config != null) {
                        return config;
                     }
                  }
               }
            }
         }

         Configuration config = this.getConfiguration(true, name);
         if (config == null) {
            config = this.getConfiguration(true, (String)null);
            if (config == null) {
               config = this.getConfiguration(false, name);
               if (config == null) {
                  config = this.getConfiguration(false, (String)null);
               }
            }
         }

         return (Configuration)(config != null ? config : new DefaultConfiguration());
      }

      private Configuration getConfiguration(boolean isTest, String name) {
         boolean named = name != null && name.length() > 0;
         ClassLoader loader = this.getClass().getClassLoader();
         Iterator i$ = ConfigurationFactory.factories.iterator();

         while(true) {
            ConfigurationFactory factory;
            String prefix;
            String[] types;
            do {
               if (!i$.hasNext()) {
                  return null;
               }

               factory = (ConfigurationFactory)i$.next();
               prefix = isTest ? "log4j2-test" : "log4j2";
               types = factory.getSupportedTypes();
            } while(types == null);

            String[] arr$ = types;
            int len$ = types.length;

            for(int i$ = 0; i$ < len$; ++i$) {
               String suffix = arr$[i$];
               if (!suffix.equals("*")) {
                  String configName = named ? prefix + name + suffix : prefix + suffix;
                  ConfigurationSource source = this.getInputFromResource(configName, loader);
                  if (source != null) {
                     return factory.getConfiguration(source);
                  }
               }
            }
         }
      }

      public String[] getSupportedTypes() {
         return null;
      }

      public Configuration getConfiguration(ConfigurationSource source) {
         if (source != null) {
            String config = source.getLocation();
            Iterator i$ = ConfigurationFactory.factories.iterator();

            label41:
            while(true) {
               ConfigurationFactory factory;
               String[] types;
               do {
                  if (!i$.hasNext()) {
                     break label41;
                  }

                  factory = (ConfigurationFactory)i$.next();
                  types = factory.getSupportedTypes();
               } while(types == null);

               String[] arr$ = types;
               int len$ = types.length;

               for(int i$ = 0; i$ < len$; ++i$) {
                  String type = arr$[i$];
                  if (type.equals("*") || config != null && config.endsWith(type)) {
                     Configuration c = factory.getConfiguration(source);
                     if (c != null) {
                        LOGGER.debug("Loaded configuration from {}", source);
                        return c;
                     } else {
                        LOGGER.error("Cannot determine the ConfigurationFactory to use for {}", config);
                        return null;
                     }
                  }
               }
            }
         }

         LOGGER.error("Cannot process configuration, input source is null");
         return null;
      }

      // $FF: synthetic method
      Factory(Object x0) {
         this();
      }
   }

   private static class WeightedFactory implements Comparable<ConfigurationFactory.WeightedFactory> {
      private final int weight;
      private final Class<ConfigurationFactory> factoryClass;

      public WeightedFactory(int weight, Class<ConfigurationFactory> clazz) {
         this.weight = weight;
         this.factoryClass = clazz;
      }

      public int compareTo(ConfigurationFactory.WeightedFactory wf) {
         int w = wf.weight;
         if (this.weight == w) {
            return 0;
         } else {
            return this.weight > w ? -1 : 1;
         }
      }
   }
}
