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

import java.lang.management.ManagementFactory;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.QueryExp;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.AsyncAppender;
import org.apache.logging.log4j.core.async.AsyncLogger;
import org.apache.logging.log4j.core.async.AsyncLoggerConfig;
import org.apache.logging.log4j.core.async.AsyncLoggerContext;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.impl.Log4jContextFactory;
import org.apache.logging.log4j.core.selector.ContextSelector;
import org.apache.logging.log4j.spi.LoggerContextFactory;
import org.apache.logging.log4j.status.StatusLogger;

public final class Server {
   public static final String DOMAIN = "org.apache.logging.log4j2";
   private static final String PROPERTY_DISABLE_JMX = "log4j2.disable.jmx";
   private static final StatusLogger LOGGER = StatusLogger.getLogger();
   static final Executor executor = Executors.newFixedThreadPool(1);

   private Server() {
   }

   public static String escape(String name) {
      StringBuilder sb = new StringBuilder(name.length() * 2);
      boolean needsQuotes = false;

      for(int i = 0; i < name.length(); ++i) {
         char c = name.charAt(i);
         switch(c) {
         case '\n':
            sb.append("\\n");
            needsQuotes = true;
         case '\r':
            continue;
         case '"':
         case '*':
         case '?':
         case '\\':
            sb.append('\\');
            needsQuotes = true;
            break;
         case ',':
         case ':':
         case '=':
            needsQuotes = true;
         }

         sb.append(c);
      }

      if (needsQuotes) {
         sb.insert(0, '"');
         sb.append('"');
      }

      return sb.toString();
   }

   public static void reregisterMBeansAfterReconfigure() {
      if (Boolean.getBoolean("log4j2.disable.jmx")) {
         LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
      } else {
         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
         reregisterMBeansAfterReconfigure(mbs);
      }
   }

   public static void reregisterMBeansAfterReconfigure(MBeanServer mbs) {
      if (Boolean.getBoolean("log4j2.disable.jmx")) {
         LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
      } else {
         try {
            ContextSelector selector = getContextSelector();
            if (selector == null) {
               LOGGER.debug("Could not register MBeans: no ContextSelector found.");
               return;
            }

            List<LoggerContext> contexts = selector.getLoggerContexts();
            Iterator i$ = contexts.iterator();

            while(i$.hasNext()) {
               LoggerContext ctx = (LoggerContext)i$.next();
               unregisterLoggerContext(ctx.getName(), mbs);
               LoggerContextAdmin mbean = new LoggerContextAdmin(ctx, executor);
               register(mbs, mbean, mbean.getObjectName());
               if (ctx instanceof AsyncLoggerContext) {
                  RingBufferAdmin rbmbean = AsyncLogger.createRingBufferAdmin(ctx.getName());
                  register(mbs, rbmbean, rbmbean.getObjectName());
               }

               registerStatusLogger(ctx.getName(), mbs, executor);
               registerContextSelector(ctx.getName(), selector, mbs, executor);
               registerLoggerConfigs(ctx, mbs, executor);
               registerAppenders(ctx, mbs, executor);
            }
         } catch (Exception var7) {
            LOGGER.error("Could not register mbeans", var7);
         }

      }
   }

   public static void unregisterMBeans() {
      MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
      unregisterMBeans(mbs);
   }

   public static void unregisterMBeans(MBeanServer mbs) {
      unregisterStatusLogger("*", mbs);
      unregisterContextSelector("*", mbs);
      unregisterContexts(mbs);
      unregisterLoggerConfigs("*", mbs);
      unregisterAsyncLoggerRingBufferAdmins("*", mbs);
      unregisterAsyncLoggerConfigRingBufferAdmins("*", mbs);
      unregisterAppenders("*", mbs);
      unregisterAsyncAppenders("*", mbs);
   }

   private static ContextSelector getContextSelector() {
      LoggerContextFactory factory = LogManager.getFactory();
      if (factory instanceof Log4jContextFactory) {
         ContextSelector selector = ((Log4jContextFactory)factory).getSelector();
         return selector;
      } else {
         return null;
      }
   }

   public static void unregisterLoggerContext(String loggerContextName) {
      MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
      unregisterLoggerContext(loggerContextName, mbs);
   }

   public static void unregisterLoggerContext(String contextName, MBeanServer mbs) {
      String pattern = "org.apache.logging.log4j2:type=%s";
      String search = String.format("org.apache.logging.log4j2:type=%s", escape(contextName), "*");
      unregisterAllMatching(search, mbs);
      unregisterStatusLogger(contextName, mbs);
      unregisterContextSelector(contextName, mbs);
      unregisterLoggerConfigs(contextName, mbs);
      unregisterAppenders(contextName, mbs);
      unregisterAsyncAppenders(contextName, mbs);
      unregisterAsyncLoggerRingBufferAdmins(contextName, mbs);
      unregisterAsyncLoggerConfigRingBufferAdmins(contextName, mbs);
   }

   private static void registerStatusLogger(String contextName, MBeanServer mbs, Executor executor) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
      StatusLoggerAdmin mbean = new StatusLoggerAdmin(contextName, executor);
      register(mbs, mbean, mbean.getObjectName());
   }

   private static void registerContextSelector(String contextName, ContextSelector selector, MBeanServer mbs, Executor executor) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
      ContextSelectorAdmin mbean = new ContextSelectorAdmin(contextName, selector);
      register(mbs, mbean, mbean.getObjectName());
   }

   private static void unregisterStatusLogger(String contextName, MBeanServer mbs) {
      String pattern = "org.apache.logging.log4j2:type=%s,component=StatusLogger";
      String search = String.format("org.apache.logging.log4j2:type=%s,component=StatusLogger", escape(contextName), "*");
      unregisterAllMatching(search, mbs);
   }

   private static void unregisterContextSelector(String contextName, MBeanServer mbs) {
      String pattern = "org.apache.logging.log4j2:type=%s,component=ContextSelector";
      String search = String.format("org.apache.logging.log4j2:type=%s,component=ContextSelector", escape(contextName), "*");
      unregisterAllMatching(search, mbs);
   }

   private static void unregisterLoggerConfigs(String contextName, MBeanServer mbs) {
      String pattern = "org.apache.logging.log4j2:type=%s,component=Loggers,name=%s";
      String search = String.format("org.apache.logging.log4j2:type=%s,component=Loggers,name=%s", escape(contextName), "*");
      unregisterAllMatching(search, mbs);
   }

   private static void unregisterContexts(MBeanServer mbs) {
      String pattern = "org.apache.logging.log4j2:type=%s";
      String search = String.format("org.apache.logging.log4j2:type=%s", "*");
      unregisterAllMatching(search, mbs);
   }

   private static void unregisterAppenders(String contextName, MBeanServer mbs) {
      String pattern = "org.apache.logging.log4j2:type=%s,component=Appenders,name=%s";
      String search = String.format("org.apache.logging.log4j2:type=%s,component=Appenders,name=%s", escape(contextName), "*");
      unregisterAllMatching(search, mbs);
   }

   private static void unregisterAsyncAppenders(String contextName, MBeanServer mbs) {
      String pattern = "org.apache.logging.log4j2:type=%s,component=AsyncAppenders,name=%s";
      String search = String.format("org.apache.logging.log4j2:type=%s,component=AsyncAppenders,name=%s", escape(contextName), "*");
      unregisterAllMatching(search, mbs);
   }

   private static void unregisterAsyncLoggerRingBufferAdmins(String contextName, MBeanServer mbs) {
      String pattern1 = "org.apache.logging.log4j2:type=%s,component=AsyncLoggerRingBuffer";
      String search1 = String.format("org.apache.logging.log4j2:type=%s,component=AsyncLoggerRingBuffer", escape(contextName));
      unregisterAllMatching(search1, mbs);
   }

   private static void unregisterAsyncLoggerConfigRingBufferAdmins(String contextName, MBeanServer mbs) {
      String pattern2 = "org.apache.logging.log4j2:type=%s,component=Loggers,name=%s,subtype=RingBuffer";
      String search2 = String.format("org.apache.logging.log4j2:type=%s,component=Loggers,name=%s,subtype=RingBuffer", escape(contextName), "*");
      unregisterAllMatching(search2, mbs);
   }

   private static void unregisterAllMatching(String search, MBeanServer mbs) {
      try {
         ObjectName pattern = new ObjectName(search);
         Set<ObjectName> found = mbs.queryNames(pattern, (QueryExp)null);
         Iterator i$ = found.iterator();

         while(i$.hasNext()) {
            ObjectName objectName = (ObjectName)i$.next();
            LOGGER.debug("Unregistering MBean {}", new Object[]{objectName});
            mbs.unregisterMBean(objectName);
         }
      } catch (Exception var6) {
         LOGGER.error("Could not unregister MBeans for " + search, var6);
      }

   }

   private static void registerLoggerConfigs(LoggerContext ctx, MBeanServer mbs, Executor executor) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
      Map<String, LoggerConfig> map = ctx.getConfiguration().getLoggers();
      Iterator i$ = map.keySet().iterator();

      while(i$.hasNext()) {
         String name = (String)i$.next();
         LoggerConfig cfg = (LoggerConfig)map.get(name);
         LoggerConfigAdmin mbean = new LoggerConfigAdmin(ctx, cfg);
         register(mbs, mbean, mbean.getObjectName());
         if (cfg instanceof AsyncLoggerConfig) {
            AsyncLoggerConfig async = (AsyncLoggerConfig)cfg;
            RingBufferAdmin rbmbean = async.createRingBufferAdmin(ctx.getName());
            register(mbs, rbmbean, rbmbean.getObjectName());
         }
      }

   }

   private static void registerAppenders(LoggerContext ctx, MBeanServer mbs, Executor executor) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
      Map<String, Appender> map = ctx.getConfiguration().getAppenders();
      Iterator i$ = map.keySet().iterator();

      while(i$.hasNext()) {
         String name = (String)i$.next();
         Appender appender = (Appender)map.get(name);
         if (appender instanceof AsyncAppender) {
            AsyncAppender async = (AsyncAppender)appender;
            AsyncAppenderAdmin mbean = new AsyncAppenderAdmin(ctx.getName(), async);
            register(mbs, mbean, mbean.getObjectName());
         } else {
            AppenderAdmin mbean = new AppenderAdmin(ctx.getName(), appender);
            register(mbs, mbean, mbean.getObjectName());
         }
      }

   }

   private static void register(MBeanServer mbs, Object mbean, ObjectName objectName) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
      LOGGER.debug("Registering MBean {}", new Object[]{objectName});
      mbs.registerMBean(mbean, objectName);
   }
}
