/**
   * Sets the Configuration to be used.
   *
   * @param config The new Configuration.
   * @return The previous Configuration.
   */
  private Configuration setConfiguration(final Configuration config) {
    Objects.requireNonNull(config, "No Configuration was provided");
    configLock.lock();
    try {
      final Configuration prev = this.configuration;
      config.addListener(this);
      final ConcurrentMap<String, String> map =
          config.getComponent(Configuration.CONTEXT_PROPERTIES);

      try { // LOG4J2-719 network access may throw android.os.NetworkOnMainThreadException
        map.putIfAbsent("hostName", NetUtils.getLocalHostname());
      } catch (final Exception ex) {
        LOGGER.debug("Ignoring {}, setting hostName to 'unknown'", ex.toString());
        map.putIfAbsent("hostName", "unknown");
      }
      map.putIfAbsent("contextName", contextName);
      config.start();
      this.configuration = config;
      updateLoggers();
      if (prev != null) {
        prev.removeListener(this);
        prev.stop();
      }

      firePropertyChangeEvent(new PropertyChangeEvent(this, PROPERTY_CONFIG, prev, config));

      try {
        Server.reregisterMBeansAfterReconfigure();
      } catch (final Throwable t) {
        // LOG4J2-716: Android has no java.lang.management
        LOGGER.error("Could not reconfigure JMX", t);
      }
      Log4jLogEvent.setNanoClock(NanoClockFactory.createNanoClock());
      AsyncLogger.setNanoClock(NanoClockFactory.createNanoClock());
      return prev;
    } finally {
      configLock.unlock();
    }
  }
  private Rfc5424Layout(
      final Configuration config,
      final Facility facility,
      final String id,
      final int ein,
      final boolean includeMDC,
      final boolean includeNL,
      final String escapeNL,
      final String mdcId,
      final String mdcPrefix,
      final String eventPrefix,
      final String appName,
      final String messageId,
      final String excludes,
      final String includes,
      final String required,
      final Charset charset,
      final String exceptionPattern,
      final boolean useTLSMessageFormat,
      final LoggerFields[] loggerFields) {
    super(charset);
    final PatternParser exceptionParser =
        createPatternParser(config, ThrowablePatternConverter.class);
    exceptionFormatters =
        exceptionPattern == null ? null : exceptionParser.parse(exceptionPattern, false, false);
    this.facility = facility;
    this.defaultId = id == null ? DEFAULT_ID : id;
    this.enterpriseNumber = ein;
    this.includeMdc = includeMDC;
    this.includeNewLine = includeNL;
    this.escapeNewLine = escapeNL == null ? null : Matcher.quoteReplacement(escapeNL);
    this.mdcId = mdcId;
    this.mdcSdId = new StructuredDataId(mdcId, enterpriseNumber, null, null);
    this.mdcPrefix = mdcPrefix;
    this.eventPrefix = eventPrefix;
    this.appName = appName;
    this.messageId = messageId;
    this.useTlsMessageFormat = useTLSMessageFormat;
    this.localHostName = NetUtils.getLocalHostname();
    ListChecker c = null;
    if (excludes != null) {
      final String[] array = excludes.split(Patterns.COMMA_SEPARATOR);
      if (array.length > 0) {
        c = new ExcludeChecker();
        mdcExcludes = new ArrayList<String>(array.length);
        for (final String str : array) {
          mdcExcludes.add(str.trim());
        }
      } else {
        mdcExcludes = null;
      }
    } else {
      mdcExcludes = null;
    }
    if (includes != null) {
      final String[] array = includes.split(Patterns.COMMA_SEPARATOR);
      if (array.length > 0) {
        c = new IncludeChecker();
        mdcIncludes = new ArrayList<String>(array.length);
        for (final String str : array) {
          mdcIncludes.add(str.trim());
        }
      } else {
        mdcIncludes = null;
      }
    } else {
      mdcIncludes = null;
    }
    if (required != null) {
      final String[] array = required.split(Patterns.COMMA_SEPARATOR);
      if (array.length > 0) {
        mdcRequired = new ArrayList<String>(array.length);
        for (final String str : array) {
          mdcRequired.add(str.trim());
        }
      } else {
        mdcRequired = null;
      }

    } else {
      mdcRequired = null;
    }
    this.checker = c != null ? c : noopChecker;
    final String name = config == null ? null : config.getName();
    configName = name != null && name.length() > 0 ? name : null;
    this.fieldFormatters = createFieldFormatters(loggerFields, config);
  }