You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@solr.apache.org by GitBox <gi...@apache.org> on 2021/10/29 05:04:53 UTC

[GitHub] [solr] sonatype-lift[bot] commented on a change in pull request #160: SOLR-15337: Avoid XPath in solrconfig.xml parsing

sonatype-lift[bot] commented on a change in pull request #160:
URL: https://github.com/apache/solr/pull/160#discussion_r738934602



##########
File path: solr/core/src/java/org/apache/solr/core/SolrConfig.java
##########
@@ -168,140 +197,180 @@ public static SolrConfig readFromResourceLoader(SolrResourceLoader loader, Strin
    * @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 ParserConfigurationException, IOException, SAXException {
-    // insist we have non-null substituteProperties; it might get overlayed
-    super(loader, name, null, "/config/", substitutableProperties == null ? new Properties() : substitutableProperties);
+      throws IOException {
+    this.resourceLoader = loader;
+    this.resourceName = name;
+    this.substituteProperties = substitutableProperties;
     getOverlay();//just in case it is not initialized
-    getRequestParams();
-    initLibs(loader, isConfigsetTrusted);
-    luceneMatchVersion = SolrConfig.parseLuceneVersionString(getVal(IndexSchema.LUCENE_MATCH_VERSION_PARAM, true));
-    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 = (getNode("indexDefaults", false) != null) || (getNode("mainIndex", false) != null);
-    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.", getNode(indexConfigPrefix + "/nrtMode", false) == null,
-        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.",
-                     null == getNode(indexConfigPrefix + "/unlockOnStartup", false),
-                     true // 'fail' in trunk
-                     );
-                     
-    // Parse indexConfig section, using mainIndex as backup in case old config is used
-    indexConfig = new SolrIndexConfig(this, "indexConfig", null);
-
-    booleanQueryMaxClauseCount = getInt("query/maxBooleanClauses", IndexSearcher.getMaxClauseCount());
-    if (IndexSearcher.getMaxClauseCount() < booleanQueryMaxClauseCount) {
-      log.warn("solrconfig.xml: <maxBooleanClauses> of {} is greater than global limit of {} {}"
-          , booleanQueryMaxClauseCount, IndexSearcher.getMaxClauseCount()
-          , "and will have no effect 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/boolTofilterOptimizer", null) != null)
-      log.warn("solrconfig.xml: <boolTofilterOptimizer> is currently not implemented and has no effect.");
-    if (get("query/HashDocSet", null) != null)
-      log.warn("solrconfig.xml: <HashDocSet> is deprecated and no longer used.");
+    // 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)) {
+        return substitutableProperties.getProperty(key);
+      } else {
+        Object o = overlay.getUserProps().get(key);
+        return o == null ? null : o.toString();
+      }
+    });
+    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 (IndexSearcher.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 = getBool("query/useFilterForSortedQuery", false);
-    queryResultWindowSize = Math.max(1, getInt("query/queryResultWindowSize", 1));
-    queryResultMaxDocsCached = getInt("query/queryResultMaxDocsCached", Integer.MAX_VALUE);
-    enableLazyFieldLoading = getBool("query/enableLazyFieldLoading", false);
-    
-    filterCacheConfig = CacheConfig.getConfig(this, "query/filterCache");
-    queryResultCacheConfig = CacheConfig.getConfig(this, "query/queryResultCache");
-    documentCacheConfig = CacheConfig.getConfig(this, "query/documentCache");
-    CacheConfig conf = CacheConfig.getConfig(this, "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(CaffeineCache.class, args, null);
-    }
-    fieldValueCacheConfig = conf;
-    useColdSearcher = getBool("query/useColdSearcher", false);
-    dataDir = get("dataDir", null);
-    if (dataDir != null && dataDir.length() == 0) dataDir = null;
-
-
-    org.apache.solr.search.SolrIndexSearcher.initRegenerators(this);
-
-    if (get("jmx", null) != null) {
-      log.warn("solrconfig.xml: <jmx> is no longer supported, use solr.xml:/metrics/reporter section instead");
-    }
-
-    httpCachingConfig = new HttpCachingConfig(this);
-
-    maxWarmingSearchers = getInt("query/maxWarmingSearchers", 1);
-    slowQueryThresholdMillis = getInt("query/slowQueryThresholdMillis", -1);
-    for (SolrPluginInfo plugin : plugins) loadPluginInfo(plugin);
-
-    Map<String, CacheConfig> userCacheConfigs = CacheConfig.getMultipleConfigs(this, "query/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));
+      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(CaffeineCache.class, args, null);
       }
-    }
-    this.userCacheConfigs = Collections.unmodifiableMap(userCacheConfigs);
+      fieldValueCacheConfig = conf;
+      useColdSearcher = get("query").get("useColdSearcher").boolVal(false);
+      dataDir = get("dataDir").txt();
+      if (dataDir != null && dataDir.length() == 0) dataDir = null;
+
 
-    updateHandlerInfo = loadUpdatehandlerInfo();
+      org.apache.solr.search.SolrIndexSearcher.initRegenerators(this);
 
-    multipartUploadLimitKB = getInt(
-        "requestDispatcher/requestParsers/@multipartUploadLimitInKB", Integer.MAX_VALUE);
-    if (multipartUploadLimitKB == -1) multipartUploadLimitKB = Integer.MAX_VALUE;
+      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);
 
-    formUploadLimitKB = getInt(
-        "requestDispatcher/requestParsers/@formdataUploadLimitInKB", Integer.MAX_VALUE);
-    if (formUploadLimitKB == -1) formUploadLimitKB = Integer.MAX_VALUE;
+      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);
 
-    enableRemoteStreams = getBool(
-        "requestDispatcher/requestParsers/@enableRemoteStreaming", false);
+      updateHandlerInfo = loadUpdatehandlerInfo();
 
-    enableStreamBody = getBool(
-        "requestDispatcher/requestParsers/@enableStreamBody", false);
+      multipartUploadLimitKB = get("requestDispatcher").get("requestParsers").intAttr("multipartUploadLimitInKB", Integer.MAX_VALUE);
+      if (multipartUploadLimitKB == -1) multipartUploadLimitKB = Integer.MAX_VALUE;
 
-    handleSelect = getBool(
-        "requestDispatcher/@handleSelect", false);
+      formUploadLimitKB = get("requestDispatcher").get("requestParsers").intAttr("formdataUploadLimitInKB", Integer.MAX_VALUE);
+      if (formUploadLimitKB == -1) formUploadLimitKB = Integer.MAX_VALUE;
 
-    addHttpRequestToContext = getBool(
-        "requestDispatcher/requestParsers/@addHttpRequestToContext", false);
+      enableRemoteStreams = get("requestDispatcher").get("requestParsers").boolAttr("enableRemoteStreaming", 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);
+      enableStreamBody = get("requestDispatcher").get("requestParsers").boolAttr("enableStreamBody", false);
+
+      handleSelect = get("requestDispatcher").boolAttr("handleSelect", false);
+      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);
       }
-      this.initParams = Collections.unmodifiableMap(argsMap);
 
+      solrRequestParsers = new SolrRequestParsers(this);
+      log.debug("Loaded SolrConfig: {}", name);
+    } finally {
+      ConfigNode.SUBSTITUTES.remove();
     }
+  }
 
-    solrRequestParsers = new SolrRequestParsers(this);
-    log.debug("Loaded SolrConfig: {}", name);
+  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()));

Review comment:
       *NULL_DEREFERENCE:*  object returned by `getDocument(xml)` could be null and is dereferenced at line 369.
   (at-me [in a reply](https://help.sonatype.com/lift/talking-to-lift) with `help` or `ignore`)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org