/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.solr.core;


import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.invoke.MethodHandles;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.common.collect.ImmutableList;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.index.IndexDeletionPolicy;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.util.Version;
import org.apache.solr.client.solrj.io.stream.expr.Expressible;
import org.apache.solr.cloud.RecoveryStrategy;
import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.ConfigNode;
import org.apache.solr.common.MapSerializable;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.IOUtils;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.pkg.PackageListeners;
import org.apache.solr.pkg.PackageLoader;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.transform.TransformerFactory;
import org.apache.solr.rest.RestManager;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.IndexSchemaFactory;
import org.apache.solr.search.CacheConfig;
import org.apache.solr.search.FastLRUCache;
import org.apache.solr.search.QParserPlugin;
import org.apache.solr.search.SolrCache;
import org.apache.solr.search.ValueSourceParser;
import org.apache.solr.search.stats.StatsCache;
import org.apache.solr.servlet.SolrRequestParsers;
import org.apache.solr.spelling.QueryConverter;
import org.apache.solr.update.SolrIndexConfig;
import org.apache.solr.update.UpdateLog;
import org.apache.solr.update.processor.UpdateRequestProcessorChain;
import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
import org.apache.solr.util.DOMConfigNode;
import org.apache.solr.util.DataConfigNode;
import org.apache.solr.util.circuitbreaker.CircuitBreakerManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.solr.common.params.CommonParams.NAME;
import static org.apache.solr.common.params.CommonParams.PATH;
import static org.apache.solr.common.util.Utils.fromJSON;
import static org.apache.solr.common.util.Utils.makeMap;
import static org.apache.solr.core.ConfigOverlay.ZNODEVER;
import static org.apache.solr.core.SolrConfig.PluginOpts.LAZY;
import static org.apache.solr.core.SolrConfig.PluginOpts.MULTI_OK;
import static org.apache.solr.core.SolrConfig.PluginOpts.NOOP;
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS;
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME;
import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME_IN_OVERLAY;
import static org.apache.solr.core.XmlConfigFile.assertWarnOrFail;


/**
 * Provides a static reference to a Config object modeling the main
 * configuration data for a a Solr instance -- typically found in
 * "solrconfig.xml".
 */
public class SolrConfig implements MapSerializable {

  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

  public static final String DEFAULT_CONF_FILE = "solrconfig.xml";
  private final String resourceName;

  private int znodeVersion;
  ConfigNode root;
  private final SolrResourceLoader resourceLoader;
  private Properties substituteProperties;

  private RequestParams requestParams;

  public enum PluginOpts {
    MULTI_OK,
    REQUIRE_NAME,
    REQUIRE_NAME_IN_OVERLAY,
    REQUIRE_CLASS,
    LAZY,
    // EnumSet.of and/or EnumSet.copyOf(Collection) are annoying
    // because of type determination
    NOOP
  }

  private int multipartUploadLimitKB;

  private int formUploadLimitKB;

  private boolean enableRemoteStreams;
  private boolean enableStreamBody;

  private boolean handleSelect;

  private boolean addHttpRequestToContext;

  private final SolrRequestParsers solrRequestParsers;

  /**
   * TEST-ONLY: Creates a configuration instance from an instance directory and file name
   * @param instanceDir the directory used to create the resource loader
   * @param name        the configuration name used by the loader if the stream is null
   */
  public SolrConfig(Path instanceDir, String name)
      throws IOException {
    this(new SolrResourceLoader(instanceDir), name, true, null);
  }

  public static SolrConfig readFromResourceLoader(SolrResourceLoader loader, String name, boolean isConfigsetTrusted, Properties substitutableProperties) {
    try {
      return new SolrConfig(loader, name, isConfigsetTrusted, substitutableProperties);
    } catch (Exception e) {
      String resource;
      if (loader instanceof ZkSolrResourceLoader) {
        resource = name;
      } else {
        resource = Paths.get(loader.getConfigDir()).resolve(name).toString();
      }
      throw new SolrException(ErrorCode.SERVER_ERROR, "Error loading solr config from " + resource, e);
    }
  }
  private class ResourceProvider implements Function<String, InputStream> {
    int zkVersion;
    int hash = -1;
    InputStream in;
    String fileName;

    ResourceProvider(InputStream in) {
      this.in = in;
      if (in instanceof ZkSolrResourceLoader.ZkByteArrayInputStream) {
        ZkSolrResourceLoader.ZkByteArrayInputStream zkin = (ZkSolrResourceLoader.ZkByteArrayInputStream) in;
        zkVersion = zkin.getStat().getVersion();
        hash = Objects.hash(zkVersion, overlay.getZnodeVersion());
        this.fileName = zkin.fileName;
      }
    }

    @Override
    public InputStream apply(String s) {
      return in;
    }
  }

  /**
   * Creates a configuration instance from a resource loader, a configuration name and a stream.
   * If the stream is null, the resource loader will open the configuration stream.
   * If the stream is not null, no attempt to load the resource will occur (the name is not used).
   * @param loader              the resource loader
   * @param name                the configuration name
   * @param isConfigsetTrusted  false if configset was uploaded using unsecured configset upload API, true otherwise
   * @param substitutableProperties optional properties to substitute into the XML
   */
  @SuppressWarnings("unchecked")
  private SolrConfig(SolrResourceLoader loader, String name, boolean isConfigsetTrusted, Properties substitutableProperties)
      throws IOException {
    this.resourceLoader = loader;
    this.resourceName = name;
    this.substituteProperties = substitutableProperties;
    getOverlay();//just in case it is not initialized
    // insist we have non-null substituteProperties; it might get overlaid
    Map<String, IndexSchemaFactory.VersionedConfig> configCache =null;
    if (loader.getCoreContainer() != null && loader.getCoreContainer().getObjectCache() != null) {
      configCache = (Map<String, IndexSchemaFactory.VersionedConfig>) loader.getCoreContainer().getObjectCache()
          .computeIfAbsent(ConfigSetService.ConfigResource.class.getName(), s -> new ConcurrentHashMap<>());
      ResourceProvider rp = new ResourceProvider(loader.openResource(name));
      IndexSchemaFactory.VersionedConfig cfg = rp.fileName == null ? null : configCache.get(rp.fileName);
      if (cfg != null) {
        if (rp.hash != -1) {
          if (rp.hash == cfg.version) {
            log.debug("LOADED_FROM_CACHE");
            root = cfg.data;
          } else {
            readXml(loader, name, configCache, rp);
          }
        }
      }
    }
    if(root == null) {
      readXml(loader, name, configCache,new ResourceProvider(loader.openResource(name)) );
    }
    ConfigNode.SUBSTITUTES.set(key -> {
      if(substitutableProperties== null || !substitutableProperties.containsKey(key)) {
        Object o = overlay.getUserProps().get(key);
        return o ==null? null: o.toString();
      } else {
        return substitutableProperties.getProperty(key);
      }
    });
    try {
      getRequestParams();
      initLibs(loader, isConfigsetTrusted);
      String val = root.child(IndexSchema.LUCENE_MATCH_VERSION_PARAM,
          () -> new RuntimeException("Missing: " + IndexSchema.LUCENE_MATCH_VERSION_PARAM)).txt();

      luceneMatchVersion = SolrConfig.parseLuceneVersionString(val);
      log.info("Using Lucene MatchVersion: {}", luceneMatchVersion);

      String indexConfigPrefix;

      // Old indexDefaults and mainIndex sections are deprecated and fails fast for luceneMatchVersion=>LUCENE_4_0_0.
      // For older solrconfig.xml's we allow the old sections, but never mixed with the new <indexConfig>
      boolean hasDeprecatedIndexConfig = get("indexDefaults").exists() || get("mainIndex").exists();
      if (hasDeprecatedIndexConfig) {
        throw new SolrException(ErrorCode.FORBIDDEN, "<indexDefaults> and <mainIndex> configuration sections are discontinued. Use <indexConfig> instead.");
      } else {
        indexConfigPrefix = "indexConfig";
      }
      assertWarnOrFail("The <nrtMode> config has been discontinued and NRT mode is always used by Solr." +
              " This config will be removed in future versions.", get(indexConfigPrefix).get("nrtMode").isNull(),
          true
      );
      assertWarnOrFail("Solr no longer supports forceful unlocking via the 'unlockOnStartup' option.  " +
              "This is no longer necessary for the default lockType except in situations where " +
              "it would be dangerous and should not be done.  For other lockTypes and/or " +
              "directoryFactory options it may also be dangerous and users must resolve " +
              "problematic locks manually.",
          !get(indexConfigPrefix).get("unlockOnStartup").exists(),
          true // 'fail' in trunk
      );

      // Parse indexConfig section, using mainIndex as backup in case old config is used
      indexConfig = new SolrIndexConfig(get("indexConfig"), null);

      booleanQueryMaxClauseCount = get("query").get("maxBooleanClauses").intVal(BooleanQuery.getMaxClauseCount());
      if (BooleanQuery.getMaxClauseCount() < booleanQueryMaxClauseCount) {
        log.warn("solrconfig.xml: <maxBooleanClauses> of {} is greater than global limit of {} and will have no effect {}"
            , booleanQueryMaxClauseCount, BooleanQuery.getMaxClauseCount()
            , "set 'maxBooleanClauses' in solr.xml to increase global limit");
      }

      // Warn about deprecated / discontinued parameters
      // boolToFilterOptimizer has had no effect since 3.1
      if (get("query").get("boolTofilterOptimizer").exists())
        log.warn("solrconfig.xml: <boolTofilterOptimizer> is currently not implemented and has no effect.");
      if (get("query").get("HashDocSet").exists())
        log.warn("solrconfig.xml: <HashDocSet> is deprecated and no longer used.");

// TODO: Old code - in case somebody wants to re-enable. Also see SolrIndexSearcher#search()
//    filtOptEnabled = getBool("query/boolTofilterOptimizer/@enabled", false);
//    filtOptCacheSize = getInt("query/boolTofilterOptimizer/@cacheSize",32);
//    filtOptThreshold = getFloat("query/boolTofilterOptimizer/@threshold",.05f);

      useFilterForSortedQuery = get("query").get("useFilterForSortedQuery").boolVal(false);
      queryResultWindowSize = Math.max(1, get("query").get("queryResultWindowSize").intVal(1));
      queryResultMaxDocsCached = get("query").get("queryResultMaxDocsCached").intVal(Integer.MAX_VALUE);
      enableLazyFieldLoading = get("query").get("enableLazyFieldLoading").boolVal(false);

      filterCacheConfig = CacheConfig.getConfig(this, get("query").get("filterCache"), "query/filterCache");
      queryResultCacheConfig = CacheConfig.getConfig(this, get("query").get("queryResultCache"), "query/queryResultCache");
      documentCacheConfig = CacheConfig.getConfig(this, get("query").get("documentCache"), "query/documentCache");
      CacheConfig conf = CacheConfig.getConfig(this, get("query").get("fieldValueCache"), "query/fieldValueCache");
      if (conf == null) {
        Map<String, String> args = new HashMap<>();
        args.put(NAME, "fieldValueCache");
        args.put("size", "10000");
        args.put("initialSize", "10");
        args.put("showItems", "-1");
        conf = new CacheConfig(FastLRUCache.class, args, null);
      }
      fieldValueCacheConfig = conf;
      useColdSearcher = get("query").get("useColdSearcher").boolVal(false);
      dataDir = get("dataDir").txt();
      if (dataDir != null && dataDir.length() == 0) dataDir = null;


      org.apache.solr.search.SolrIndexSearcher.initRegenerators(this);

      if (get("jmx").exists()) {
        log.warn("solrconfig.xml: <jmx> is no longer supported, use solr.xml:/metrics/reporter section instead");
      }

      httpCachingConfig = new HttpCachingConfig(this);

      maxWarmingSearchers = get("query").get("maxWarmingSearchers").intVal(1);
      slowQueryThresholdMillis = get("query").get("slowQueryThresholdMillis").intVal(-1);
      for (SolrPluginInfo plugin : plugins) loadPluginInfo(plugin);

      Map<String, CacheConfig> userCacheConfigs = CacheConfig.getMultipleConfigs(this, "query/cache",
          get("query").getAll("cache"));
      List<PluginInfo> caches = getPluginInfos(SolrCache.class.getName());
      if (!caches.isEmpty()) {
        for (PluginInfo c : caches) {
          userCacheConfigs.put(c.name, CacheConfig.getConfig(this, "cache", c.attributes, null));
        }
      }
      this.userCacheConfigs = Collections.unmodifiableMap(userCacheConfigs);

      updateHandlerInfo = loadUpdatehandlerInfo();

      multipartUploadLimitKB = get("requestDispatcher").get("requestParsers").intAttr("multipartUploadLimitInKB", Integer.MAX_VALUE);
      if (multipartUploadLimitKB == -1) multipartUploadLimitKB = Integer.MAX_VALUE;

      formUploadLimitKB = get("requestDispatcher").get("requestParsers").intAttr("formdataUploadLimitInKB", Integer.MAX_VALUE);
      if (formUploadLimitKB == -1) formUploadLimitKB = Integer.MAX_VALUE;

      enableRemoteStreams = get("requestDispatcher").get("requestParsers").boolAttr("enableRemoteStreaming", false);

      enableStreamBody = get("requestDispatcher").get("requestParsers").boolAttr("enableStreamBody", false);

      handleSelect = get("requestDispatcher").boolAttr("handleSelect", !luceneMatchVersion.onOrAfter(Version.LUCENE_7_0_0));
      addHttpRequestToContext = get("requestDispatcher").get("requestParsers").boolAttr("addHttpRequestToContext", false);

      List<PluginInfo> argsInfos = getPluginInfos(InitParams.class.getName());
      if (argsInfos != null) {
        Map<String, InitParams> argsMap = new HashMap<>();
        for (PluginInfo p : argsInfos) {
          InitParams args = new InitParams(p);
          argsMap.put(args.name == null ? String.valueOf(args.hashCode()) : args.name, args);
        }
        this.initParams = Collections.unmodifiableMap(argsMap);
      }

      solrRequestParsers = new SolrRequestParsers(this);
      log.debug("Loaded SolrConfig: {}", name);
    } finally {
      ConfigNode.SUBSTITUTES.remove();
    }
  }

  private void readXml(SolrResourceLoader loader, String name, Map<String, IndexSchemaFactory.VersionedConfig> configCache, ResourceProvider rp) throws IOException {
    XmlConfigFile xml = new XmlConfigFile(loader,rp, name, null, "/config/", null);
    root = new DataConfigNode(new DOMConfigNode(xml.getDocument().getDocumentElement()));
    this.znodeVersion = rp.zkVersion;
    if(configCache != null && rp.fileName !=null) {
      configCache.put(rp.fileName, new IndexSchemaFactory.VersionedConfig(rp.hash, root));
    }
  }

  private static final AtomicBoolean versionWarningAlreadyLogged = new AtomicBoolean(false);

  public static final Version parseLuceneVersionString(final String matchVersion) {
    final Version version;
    try {
      version = Version.parseLeniently(matchVersion);
    } catch (ParseException pe) {
      throw new SolrException(ErrorCode.SERVER_ERROR,
          "Invalid luceneMatchVersion.  Should be of the form 'V.V.V' (e.g. 4.8.0)", pe);
    }

    if (version == Version.LATEST && !versionWarningAlreadyLogged.getAndSet(true)) {
      log.warn("You should not use LATEST as luceneMatchVersion property: "
          + "if you use this setting, and then Solr upgrades to a newer release of Lucene, "
          + "sizable changes may happen. If precise back compatibility is important "
          + "then you should instead explicitly specify an actual Lucene version.");
    }

    return version;
  }

  public static final List<SolrPluginInfo> plugins = ImmutableList.<SolrPluginInfo>builder()
      .add(new SolrPluginInfo(SolrRequestHandler.class, SolrRequestHandler.TYPE, REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK, LAZY))
      .add(new SolrPluginInfo(QParserPlugin.class, "queryParser", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
      .add(new SolrPluginInfo(Expressible.class, "expressible", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
      .add(new SolrPluginInfo(QueryResponseWriter.class, "queryResponseWriter", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK, LAZY))
      .add(new SolrPluginInfo(ValueSourceParser.class, "valueSourceParser", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
      .add(new SolrPluginInfo(TransformerFactory.class, "transformer", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
      .add(new SolrPluginInfo(SearchComponent.class, "searchComponent", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
      .add(new SolrPluginInfo(UpdateRequestProcessorFactory.class, "updateProcessor", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
      .add(new SolrPluginInfo(SolrCache.class, "cache", REQUIRE_NAME, MULTI_OK))
          // TODO: WTF is up with queryConverter???
          // it apparently *only* works as a singleton? - SOLR-4304
          // and even then -- only if there is a single SpellCheckComponent
          // because of queryConverter.setIndexAnalyzer
      .add(new SolrPluginInfo(QueryConverter.class, "queryConverter", REQUIRE_NAME, REQUIRE_CLASS))
      .add(new SolrPluginInfo(PluginBag.RuntimeLib.class, "runtimeLib", REQUIRE_NAME, MULTI_OK))
          // this is hackish, since it picks up all SolrEventListeners,
          // regardless of when/how/why they are used (or even if they are
          // declared outside of the appropriate context) but there's no nice
          // way around that in the PluginInfo framework
      .add(new SolrPluginInfo(InitParams.class, InitParams.TYPE, MULTI_OK, REQUIRE_NAME_IN_OVERLAY))
      .add(new SolrPluginInfo(it -> {
        List<ConfigNode> result = new ArrayList<>();
        result.addAll(it.get("query").getAll("listener"));
        result.addAll( it.get("updateHandler").getAll("listener"));
        return result;
      }, SolrEventListener.class, "//listener", REQUIRE_CLASS, MULTI_OK, REQUIRE_NAME_IN_OVERLAY))

      .add(new SolrPluginInfo(DirectoryFactory.class, "directoryFactory", REQUIRE_CLASS))
      .add(new SolrPluginInfo(RecoveryStrategy.Builder.class, "recoveryStrategy"))
      .add(new SolrPluginInfo(it -> it.get("indexConfig").getAll("deletionPolicy"), IndexDeletionPolicy.class, "indexConfig/deletionPolicy", REQUIRE_CLASS))
      .add(new SolrPluginInfo(CodecFactory.class, "codecFactory", REQUIRE_CLASS))
      .add(new SolrPluginInfo(IndexReaderFactory.class, "indexReaderFactory", REQUIRE_CLASS))
      .add(new SolrPluginInfo(UpdateRequestProcessorChain.class, "updateRequestProcessorChain", MULTI_OK))
      .add(new SolrPluginInfo(it -> it.get("updateHandler").getAll("updateLog"), UpdateLog.class, "updateHandler/updateLog"))
      .add(new SolrPluginInfo(IndexSchemaFactory.class, "schemaFactory", REQUIRE_CLASS))
      .add(new SolrPluginInfo(RestManager.class, "restManager"))
      .add(new SolrPluginInfo(StatsCache.class, "statsCache", REQUIRE_CLASS))
      .add(new SolrPluginInfo(CircuitBreakerManager.class, "circuitBreaker"))
      .build();
  public static final Map<String, SolrPluginInfo> classVsSolrPluginInfo;

  static {
    Map<String, SolrPluginInfo> map = new HashMap<>();
    for (SolrPluginInfo plugin : plugins) map.put(plugin.clazz.getName(), plugin);
    classVsSolrPluginInfo = Collections.unmodifiableMap(map);
  }

  public static class SolrPluginInfo {

    @SuppressWarnings({"rawtypes"})
    public final Class clazz;
    public final String tag;
    public final Set<PluginOpts> options;
    final Function<SolrConfig, List<ConfigNode>> configReader;

    private SolrPluginInfo(Class clz, String tag, PluginOpts... opts) {
      this(solrConfig -> solrConfig.root.getAll(null, tag), clz, tag, opts);

    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private SolrPluginInfo(Function<SolrConfig, List<ConfigNode>> configReader, Class clz, String tag, PluginOpts... opts) {
      this.configReader = configReader;
      this.clazz = clz;
      this.tag = tag;
      this.options = opts == null ? Collections.EMPTY_SET : EnumSet.of(NOOP, opts);
    }

    public String getCleanTag() {
      return tag.replaceAll("/", "");
    }

    public String getTagCleanLower() {
      return getCleanTag().toLowerCase(Locale.ROOT);

    }
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  public static ConfigOverlay getConfigOverlay(SolrResourceLoader loader) {
    InputStream in = null;
    InputStreamReader isr = null;
    try {
      try {
        in = loader.openResource(ConfigOverlay.RESOURCE_NAME);
      } catch (IOException e) {
        // TODO: we should be explicitly looking for file not found exceptions
        // and logging if it's not the expected IOException
        // hopefully no problem, assume no overlay.json file
        return new ConfigOverlay(Collections.EMPTY_MAP, -1);
      }
      
      int version = 0; // will be always 0 for file based resourceLoader
      if (in instanceof ZkSolrResourceLoader.ZkByteArrayInputStream) {
        version = ((ZkSolrResourceLoader.ZkByteArrayInputStream) in).getStat().getVersion();
        log.debug("Config overlay loaded. version : {} ", version);
      }
      Map m = (Map) fromJSON(in);
      return new ConfigOverlay(m, version);
    } catch (Exception e) {
      throw new SolrException(ErrorCode.SERVER_ERROR, "Error reading config overlay", e);
    } finally {
      IOUtils.closeQuietly(isr);
      IOUtils.closeQuietly(in);
    }
  }

  private Map<String, InitParams> initParams = Collections.emptyMap();

  public Map<String, InitParams> getInitParams() {
    return initParams;
  }

  protected UpdateHandlerInfo loadUpdatehandlerInfo() {
    return new UpdateHandlerInfo( get("updateHandler").attr("class"),
        get("updateHandler").get("autoCommit").get("maxDocs").intVal( -1),
        get("updateHandler").get("autoCommit").get("maxTime").intVal( -1),
        convertHeapOptionStyleConfigStringToBytes(get("updateHandler").get("autoCommit").get("maxSize").txt()),
       get("updateHandler").get("indexWriter").get("closeWaitsForMerges").boolVal(true),
        get("updateHandler").get("autoCommit").get("openSearcher").boolVal(true),
        get("updateHandler").get("autoSoftCommit").get("maxDocs").intVal(-1),
        get("updateHandler").get("autoSoftCommit").get("maxTime").intVal(-1),
        get("updateHandler").get("commitWithin").get("softCommit").boolVal(true));
  }

  /**
   * Converts a Java heap option-like config string to bytes. Valid suffixes are: 'k', 'm', 'g'
   * (case insensitive). If there is no suffix, the default unit is bytes.
   * For example, 50k = 50KB, 20m = 20MB, 4g = 4GB, 300 = 300 bytes
   * @param configStr the config setting to parse
   * @return the size, in bytes. -1 if the given config string is empty
   */
  protected static long convertHeapOptionStyleConfigStringToBytes(String configStr) {
    if (configStr== null || configStr.isEmpty()) {
      return -1;
    }
    long multiplier = 1;
    String numericValueStr = configStr;
    char suffix = Character.toLowerCase(configStr.charAt(configStr.length() - 1));
    if (Character.isLetter(suffix)) {
      if (suffix == 'k') {
        multiplier = FileUtils.ONE_KB;
      }
      else if (suffix == 'm') {
        multiplier = FileUtils.ONE_MB;
      }
      else if (suffix == 'g') {
        multiplier = FileUtils.ONE_GB;
      } else {
        throw new RuntimeException("Invalid suffix. Valid suffixes are 'k' (KB), 'm' (MB), 'g' (G). "
            + "No suffix means the amount is in bytes. ");
      }
      numericValueStr = configStr.substring(0, configStr.length() - 1);
    }
    try {
      return Long.parseLong(numericValueStr) * multiplier;
    } catch (NumberFormatException e) {
      throw new RuntimeException("Invalid format. The config setting should be a long with an "
          + "optional letter suffix. Valid suffixes are 'k' (KB), 'm' (MB), 'g' (G). "
          + "No suffix means the amount is in bytes.");
    }
  }

  private void loadPluginInfo(SolrPluginInfo pluginInfo) {
    boolean requireName = pluginInfo.options.contains(REQUIRE_NAME);
    boolean requireClass = pluginInfo.options.contains(REQUIRE_CLASS);

    List<PluginInfo> result = readPluginInfos(pluginInfo, requireName, requireClass);

    if (1 < result.size() && !pluginInfo.options.contains(MULTI_OK)) {
      throw new SolrException
          (SolrException.ErrorCode.SERVER_ERROR,
              "Found " + result.size() + " configuration sections when at most "
                  + "1 is allowed matching expression: " + pluginInfo.getCleanTag());
    }
    if (!result.isEmpty()) pluginStore.put(pluginInfo.clazz.getName(), result);
  }

  public List<PluginInfo> readPluginInfos(SolrPluginInfo info, boolean requireName, boolean requireClass) {
    ArrayList<PluginInfo> result = new ArrayList<>();
    for (ConfigNode node : info.configReader.apply(this)) {
      PluginInfo pluginInfo = new PluginInfo(node, "[solrconfig.xml] " + info.tag, requireName, requireClass);
      if (pluginInfo.isEnabled()) result.add(pluginInfo);
    }
    return result;
  }

  public SolrRequestParsers getRequestParsers() {
    return solrRequestParsers;
  }

  /* The set of materialized parameters: */
  public final int booleanQueryMaxClauseCount;
  // SolrIndexSearcher - nutch optimizer -- Disabled since 3.1
//  public final boolean filtOptEnabled;
//  public final int filtOptCacheSize;
//  public final float filtOptThreshold;
  // SolrIndexSearcher - caches configurations
  public final CacheConfig filterCacheConfig;
  public final CacheConfig queryResultCacheConfig;
  public final CacheConfig documentCacheConfig;
  public final CacheConfig fieldValueCacheConfig;
  public final Map<String, CacheConfig> userCacheConfigs;
  // SolrIndexSearcher - more...
  public final boolean useFilterForSortedQuery;
  public final int queryResultWindowSize;
  public final int queryResultMaxDocsCached;
  public final boolean enableLazyFieldLoading;

  // IndexConfig settings
  public final SolrIndexConfig indexConfig;

  protected UpdateHandlerInfo updateHandlerInfo;

  private Map<String, List<PluginInfo>> pluginStore = new LinkedHashMap<>();

  public final int maxWarmingSearchers;
  public final boolean useColdSearcher;
  public final Version luceneMatchVersion;
  protected String dataDir;
  public final int slowQueryThresholdMillis;  // threshold above which a query is considered slow

  private final HttpCachingConfig httpCachingConfig;

  public HttpCachingConfig getHttpCachingConfig() {
    return httpCachingConfig;
  }

  public static class HttpCachingConfig implements MapSerializable {

    /**
     * For extracting Expires "ttl" from <cacheControl> config
     */
    private final static Pattern MAX_AGE
        = Pattern.compile("\\bmax-age=(\\d+)");

    @Override
    public Map<String, Object> toMap(Map<String, Object> map) {
      return makeMap("never304", never304,
          "etagSeed", etagSeed,
          "lastModFrom", lastModFrom.name().toLowerCase(Locale.ROOT),
          "cacheControl", cacheControlHeader);
    }

    public enum LastModFrom {
      OPENTIME, DIRLASTMOD, BOGUS;

      /**
       * Input must not be null
       */
      public static LastModFrom parse(final String s) {
        try {
          return valueOf(s.toUpperCase(Locale.ROOT));
        } catch (Exception e) {
          log.warn("Unrecognized value for lastModFrom: {}", s, e);
          return BOGUS;
        }
      }
    }

    private final boolean never304;
    private final String etagSeed;
    private final String cacheControlHeader;
    private final Long maxAge;
    private final LastModFrom lastModFrom;
    private ConfigNode configNode;

    private HttpCachingConfig(SolrConfig conf) {
      configNode = conf.root;

      //"requestDispatcher/httpCaching/";
      never304 = get("requestDispatcher").get("httpCaching").boolAttr("never304", false);

      etagSeed = get("requestDispatcher").get("httpCaching").attr("etagSeed", "Solr");


      lastModFrom = LastModFrom.parse(get("requestDispatcher").get("httpCaching").attr("lastModFrom","openTime"));

      cacheControlHeader = get("requestDispatcher").get("httpCaching").get("cacheControl").txt();

      Long tmp = null; // maxAge
      if (null != cacheControlHeader) {
        try {
          final Matcher ttlMatcher = MAX_AGE.matcher(cacheControlHeader);
          final String ttlStr = ttlMatcher.find() ? ttlMatcher.group(1) : null;
          tmp = (null != ttlStr && !"".equals(ttlStr))
              ? Long.valueOf(ttlStr)
              : null;
        } catch (Exception e) {
          log.warn("Ignoring exception while attempting to extract max-age from cacheControl config: {}"
              , cacheControlHeader, e);
        }
      }
      maxAge = tmp;

    }
    private ConfigNode get(String name){
      return configNode.get(name);
    }

    public boolean isNever304() {
      return never304;
    }

    public String getEtagSeed() {
      return etagSeed;
    }

    /**
     * null if no Cache-Control header
     */
    public String getCacheControlHeader() {
      return cacheControlHeader;
    }

    /**
     * null if no max age limitation
     */
    public Long getMaxAge() {
      return maxAge;
    }

    public LastModFrom getLastModFrom() {
      return lastModFrom;
    }
  }

  public static class UpdateHandlerInfo implements MapSerializable {
    public final String className;
    public final int autoCommmitMaxDocs, autoCommmitMaxTime,
        autoSoftCommmitMaxDocs, autoSoftCommmitMaxTime;
    public final long autoCommitMaxSizeBytes;
    public final boolean indexWriterCloseWaitsForMerges;
    public final boolean openSearcher;  // is opening a new searcher part of hard autocommit?
    public final boolean commitWithinSoftCommit;

    /**
     * @param autoCommmitMaxDocs       set -1 as default
     * @param autoCommmitMaxTime       set -1 as default
     * @param autoCommitMaxSize        set -1 as default
     */
    public UpdateHandlerInfo(String className, int autoCommmitMaxDocs, int autoCommmitMaxTime, long autoCommitMaxSize, boolean indexWriterCloseWaitsForMerges, boolean openSearcher,
                             int autoSoftCommmitMaxDocs, int autoSoftCommmitMaxTime, boolean commitWithinSoftCommit) {
      this.className = className;
      this.autoCommmitMaxDocs = autoCommmitMaxDocs;
      this.autoCommmitMaxTime = autoCommmitMaxTime;
      this.autoCommitMaxSizeBytes = autoCommitMaxSize;
      this.indexWriterCloseWaitsForMerges = indexWriterCloseWaitsForMerges;
      this.openSearcher = openSearcher;

      this.autoSoftCommmitMaxDocs = autoSoftCommmitMaxDocs;
      this.autoSoftCommmitMaxTime = autoSoftCommmitMaxTime;

      this.commitWithinSoftCommit = commitWithinSoftCommit;
    }


    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public Map<String, Object> toMap(Map<String, Object> map) {
      LinkedHashMap result = new LinkedHashMap();
      result.put("indexWriter", makeMap("closeWaitsForMerges", indexWriterCloseWaitsForMerges));
      result.put("commitWithin", makeMap("softCommit", commitWithinSoftCommit));
      result.put("autoCommit", makeMap(
          "maxDocs", autoCommmitMaxDocs,
          "maxTime", autoCommmitMaxTime,
          "openSearcher", openSearcher
      ));
      result.put("autoSoftCommit",
          makeMap("maxDocs", autoSoftCommmitMaxDocs,
              "maxTime", autoSoftCommmitMaxTime));
      return result;
    }
  }

//  public Map<String, List<PluginInfo>> getUpdateProcessorChainInfo() { return updateProcessorChainInfo; }

  public UpdateHandlerInfo getUpdateHandlerInfo() {
    return updateHandlerInfo;
  }

  public String getDataDir() {
    return dataDir;
  }

  /**
   * SolrConfig keeps a repository of plugins by the type. The known interfaces are the types.
   *
   * @param type The key is FQN of the plugin class there are a few  known types : SolrFormatter, SolrFragmenter
   *             SolrRequestHandler,QParserPlugin, QueryResponseWriter,ValueSourceParser,
   *             SearchComponent, QueryConverter, SolrEventListener, DirectoryFactory,
   *             IndexDeletionPolicy, IndexReaderFactory, {@link TransformerFactory}
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  public List<PluginInfo> getPluginInfos(String type) {
    List<PluginInfo> result = pluginStore.get(type);
    SolrPluginInfo info = classVsSolrPluginInfo.get(type);
    if (info != null &&
        (info.options.contains(REQUIRE_NAME) || info.options.contains(REQUIRE_NAME_IN_OVERLAY))) {
      Map<String, Map> infos = overlay.getNamedPlugins(info.getCleanTag());
      if (!infos.isEmpty()) {
        LinkedHashMap<String, PluginInfo> map = new LinkedHashMap<>();
        if (result != null) for (PluginInfo pluginInfo : result) {
          //just create a UUID for the time being so that map key is not null
          String name = pluginInfo.name == null ?
              UUID.randomUUID().toString().toLowerCase(Locale.ROOT) :
              pluginInfo.name;
          map.put(name, pluginInfo);
        }
        for (Map.Entry<String, Map> e : infos.entrySet()) {
          map.put(e.getKey(), new PluginInfo(info.getCleanTag(), e.getValue()));
        }
        result = new ArrayList<>(map.values());
      }
    }
    return result == null ? Collections.<PluginInfo>emptyList() : result;
  }

  public PluginInfo getPluginInfo(String type) {
    List<PluginInfo> result = pluginStore.get(type);
    if (result == null || result.isEmpty()) {
      return null;
    }
    if (1 == result.size()) {
      return result.get(0);
    }

    throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
        "Multiple plugins configured for type: " + type);
  }

  private void initLibs(SolrResourceLoader loader, boolean isConfigsetTrusted) {
    // TODO Want to remove SolrResourceLoader.getInstancePath; it can be on a Standalone subclass.
    //  For Zk subclass, it's needed for the time being as well.  We could remove that one if we remove two things
    //  in SolrCloud: (1) instancePath/lib  and (2) solrconfig lib directives with relative paths.  Can wait till 9.0.
    Path instancePath = loader.getInstancePath();
    List<URL> urls = new ArrayList<>();

    Path libPath = instancePath.resolve("lib");
    if (Files.exists(libPath)) {
      try {
        urls.addAll(SolrResourceLoader.getURLs(libPath));
      } catch (IOException e) {
        log.warn("Couldn't add files from {} to classpath: {}", libPath, e);
      }
    }

    List<ConfigNode> nodes = root.getAll("lib");
    if (nodes != null && nodes.size() > 0) {
      if (!isConfigsetTrusted) {
        throw new SolrException(ErrorCode.UNAUTHORIZED,
          "The configset for this collection was uploaded without any authentication in place,"
            + " and use of <lib> is not available for collections with untrusted configsets. To use this component, re-upload the configset"
            + " after enabling authentication and authorization.");
      }

      for (int i = 0; i < nodes.size(); i++) {
        ConfigNode node = nodes.get(i);
        String baseDir = node.attr("dir");
        String path = node.attr(PATH);
        if (null != baseDir) {
          // :TODO: add support for a simpler 'glob' mutually exclusive of regex
          Path dir = instancePath.resolve(baseDir);
          String regex = node.attr("regex");
          try {
            if (regex == null)
              urls.addAll(SolrResourceLoader.getURLs(dir));
            else
              urls.addAll(SolrResourceLoader.getFilteredURLs(dir, regex));
          } catch (IOException e) {
            log.warn("Couldn't add files from {} filtered by {} to classpath: {}", dir, regex, e);
          }
        } else if (null != path) {
          final Path dir = instancePath.resolve(path);
          try {
            urls.add(dir.toUri().toURL());
          } catch (MalformedURLException e) {
            log.warn("Couldn't add file {} to classpath: {}", dir, e);
          }
        } else {
          throw new RuntimeException("lib: missing mandatory attributes: 'dir' or 'path'");
        }
      }
    }

    if (!urls.isEmpty()) {
      loader.addToClassLoader(urls);
      loader.reloadLuceneSPI();
    }
  }

  public int getMultipartUploadLimitKB() {
    return multipartUploadLimitKB;
  }

  public int getFormUploadLimitKB() {
    return formUploadLimitKB;
  }

  public boolean isHandleSelect() {
    return handleSelect;
  }

  public boolean isAddHttpRequestToContext() {
    return addHttpRequestToContext;
  }

  public boolean isEnableRemoteStreams() {
    return enableRemoteStreams;
  }

  public boolean isEnableStreamBody() {
    return enableStreamBody;
  }


  @Override
  @SuppressWarnings({"unchecked", "rawtypes"})
  public Map<String, Object> toMap(Map<String, Object> result) {
    if (znodeVersion > -1) result.put(ZNODEVER, znodeVersion);
    if(luceneMatchVersion != null) result.put(IndexSchema.LUCENE_MATCH_VERSION_PARAM, luceneMatchVersion.toString());
    result.put("updateHandler", getUpdateHandlerInfo());
    Map m = new LinkedHashMap();
    result.put("query", m);
    m.put("useFilterForSortedQuery", useFilterForSortedQuery);
    m.put("queryResultWindowSize", queryResultWindowSize);
    m.put("queryResultMaxDocsCached", queryResultMaxDocsCached);
    m.put("enableLazyFieldLoading", enableLazyFieldLoading);
    m.put("maxBooleanClauses", booleanQueryMaxClauseCount);

    for (SolrPluginInfo plugin : plugins) {
      List<PluginInfo> infos = getPluginInfos(plugin.clazz.getName());
      if (infos == null || infos.isEmpty()) continue;
      String tag = plugin.getCleanTag();
      tag = tag.replace("/", "");
      if (plugin.options.contains(PluginOpts.REQUIRE_NAME)) {
        LinkedHashMap items = new LinkedHashMap();
        for (PluginInfo info : infos) {
          //TODO remove after fixing https://issues.apache.org/jira/browse/SOLR-13706
          if (info.type.equals("searchComponent") && info.name.equals("highlight")) continue;
          items.put(info.name, info);
        }
        for (Map.Entry e : overlay.getNamedPlugins(plugin.tag).entrySet()) items.put(e.getKey(), e.getValue());
        result.put(tag, items);
      } else {
        if (plugin.options.contains(MULTI_OK)) {
          ArrayList<MapSerializable> l = new ArrayList<>();
          for (PluginInfo info : infos) l.add(info);
          result.put(tag, l);
        } else {
          result.put(tag, infos.get(0));
        }

      }

    }


    addCacheConfig(m, filterCacheConfig, queryResultCacheConfig, documentCacheConfig, fieldValueCacheConfig);
    m = new LinkedHashMap();
    result.put("requestDispatcher", m);
    m.put("handleSelect", handleSelect);
    if (httpCachingConfig != null) m.put("httpCaching", httpCachingConfig);
    m.put("requestParsers", makeMap("multipartUploadLimitKB", multipartUploadLimitKB,
        "formUploadLimitKB", formUploadLimitKB,
        "addHttpRequestToContext", addHttpRequestToContext));
    if (indexConfig != null) result.put("indexConfig", indexConfig);

    //TODO there is more to add

    return result;
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  private void addCacheConfig(Map queryMap, CacheConfig... cache) {
    if (cache == null) return;
    for (CacheConfig config : cache) if (config != null) queryMap.put(config.getNodeName(), config);

  }

  public Properties getSubstituteProperties() {
    Map<String, Object> p = getOverlay().getUserProps();
    if (p == null || p.isEmpty()) return substituteProperties;
    Properties result = new Properties(substituteProperties);
    result.putAll(p);
    return result;
  }

  private ConfigOverlay overlay;

  public ConfigOverlay getOverlay() {
    if (overlay == null) {
      overlay = getConfigOverlay(resourceLoader);
    }
    return overlay;
  }

  public RequestParams getRequestParams() {
    if (requestParams == null) {
      return refreshRequestParams();
    }
    return requestParams;
  }

  /**
   * The version of package that should be loaded for a given package name
   * This information is stored in the params.json in the same configset
   * If params.json is absent or there is no corresponding version specified for a given package,
   * this returns a null and the latest is used by the caller
   */
  public String maxPackageVersion(String pkg) {
    RequestParams.ParamSet p = getRequestParams().getParams(PackageListeners.PACKAGE_VERSIONS);
    if (p == null) {
      return null;
    }
    Object o = p.get().get(pkg);
    if (o == null || PackageLoader.LATEST.equals(o)) return null;
    return o.toString();
  }

  public RequestParams refreshRequestParams() {
    requestParams = RequestParams.getFreshRequestParams(resourceLoader, requestParams);
    if (log.isDebugEnabled()) {
      log.debug("current version of requestparams : {}", requestParams.getZnodeVersion());
    }
    return requestParams;
  }

  public SolrResourceLoader getResourceLoader() {
    return resourceLoader;
  }

  public int getZnodeVersion() {
    return znodeVersion;
  }

  public String getName() {
    return resourceName;
  }

  public String getResourceName() {
    return resourceName;
  }

  /**fetches a child node by name. An "empty node" is returned if the child does not exist
   * This never returns a null
   *
   *
   */
  public ConfigNode get(String name) {
    if (!overlay.hasKey(name)) {
      //there is no overlay
      return root.get(name);
    }
    return new OverlaidConfigNode(overlay, name, null,root.get(name));
  }

  public ConfigNode get(String name, Predicate<ConfigNode> test) {
    return root.get(name, test);
  }
}
