Created
March 21, 2026 18:35
-
-
Save epugh/beaf36329593aa879af2d26eaa9030fd to your computer and use it in GitHub Desktop.
fix for external paths...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCase.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCase.java | |
| index a29e3d0da43..7a321671c35 100644 | |
| --- a/solr/test-framework/src/java/org/apache/solr/SolrTestCase.java | |
| +++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCase.java | |
| @@ -130,7 +130,7 @@ public class SolrTestCase extends LuceneTestCase { | |
| return; | |
| } | |
| final Path extPath = ExternalPaths.DEFAULT_CONFIGSET; | |
| - if (Files.isReadable(extPath /* implies exists() */) && Files.isDirectory(extPath)) { | |
| + if (extPath != null && Files.isReadable(extPath /* implies exists() */) && Files.isDirectory(extPath)) { | |
| log.info( | |
| "Setting '{}' system property to test-framework derived value of '{}'", | |
| SolrDispatchFilter.SOLR_CONFIGSET_DEFAULT_CONFDIR_ATTRIBUTE, | |
| diff --git a/solr/test-framework/src/java/org/apache/solr/util/ExternalPaths.java b/solr/test-framework/src/java/org/apache/solr/util/ExternalPaths.java | |
| index 940ec58b9e9..445d97bf848 100644 | |
| --- a/solr/test-framework/src/java/org/apache/solr/util/ExternalPaths.java | |
| +++ b/solr/test-framework/src/java/org/apache/solr/util/ExternalPaths.java | |
| @@ -16,19 +16,28 @@ | |
| */ | |
| package org.apache.solr.util; | |
| +import java.lang.invoke.MethodHandles; | |
| import java.net.URL; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import org.apache.solr.common.SolrException; | |
| +import org.slf4j.Logger; | |
| +import org.slf4j.LoggerFactory; | |
| /** | |
| * Some tests need to reach outside the classpath to get certain resources (e.g. the example | |
| * configuration). This class provides some paths to allow them to do this. | |
| * | |
| + * <p>When running in external plugin projects (outside the Solr source tree), {@link #SOURCE_HOME} | |
| + * will be null and the path getter methods will also return null. External projects can set the | |
| + * system property {@code solr.test.source.home} to provide an explicit source home directory. | |
| + * | |
| * @lucene.internal | |
| */ | |
| public class ExternalPaths { | |
| + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); | |
| + | |
| /** | |
| * The main directory path for the solr source being built if it can be determined. If it can not | |
| * be determined -- possibly because the current context is a client code base using the test | |
| @@ -39,29 +48,116 @@ public class ExternalPaths { | |
| */ | |
| public static final Path SOURCE_HOME = determineSourceHome(); | |
| + // Lazy-initialized paths to avoid NPE during class loading | |
| + private static volatile Path webappHome; | |
| + private static volatile Path defaultConfigSet; | |
| + private static volatile Path techproductsConfigSet; | |
| + private static volatile Path serverHome; | |
| + | |
| + /** | |
| + * Returns the path to the webapp directory, or null if SOURCE_HOME is not available. This is | |
| + * typically used when running tests within the Solr source tree. | |
| + * | |
| + * @return Path to webapp/web directory, or null if not running in Solr source tree | |
| + */ | |
| + public static Path getWebappHome() { | |
| + if (webappHome == null && SOURCE_HOME != null) { | |
| + synchronized (ExternalPaths.class) { | |
| + if (webappHome == null) { | |
| + webappHome = SOURCE_HOME.resolve("webapp/web").toAbsolutePath(); | |
| + } | |
| + } | |
| + } | |
| + return webappHome; | |
| + } | |
| + | |
| + /** | |
| + * Returns the path to the default configset, or null if SOURCE_HOME is not available. | |
| + * | |
| + * @return Path to default configset, or null if not running in Solr source tree | |
| + */ | |
| + public static Path getDefaultConfigSet() { | |
| + if (defaultConfigSet == null && SOURCE_HOME != null) { | |
| + synchronized (ExternalPaths.class) { | |
| + if (defaultConfigSet == null) { | |
| + defaultConfigSet = | |
| + SOURCE_HOME.resolve("server/solr/configsets/_default/conf").toAbsolutePath(); | |
| + } | |
| + } | |
| + } | |
| + return defaultConfigSet; | |
| + } | |
| + | |
| + /** | |
| + * Returns the path to the techproducts configset, or null if SOURCE_HOME is not available. | |
| + * | |
| + * @return Path to techproducts configset, or null if not running in Solr source tree | |
| + */ | |
| + public static Path getTechproductsConfigSet() { | |
| + if (techproductsConfigSet == null && SOURCE_HOME != null) { | |
| + synchronized (ExternalPaths.class) { | |
| + if (techproductsConfigSet == null) { | |
| + techproductsConfigSet = | |
| + SOURCE_HOME | |
| + .resolve("server/solr/configsets/sample_techproducts_configs/conf") | |
| + .toAbsolutePath(); | |
| + } | |
| + } | |
| + } | |
| + return techproductsConfigSet; | |
| + } | |
| + | |
| /** | |
| - * @see #SOURCE_HOME | |
| + * Returns the path to the server home directory, or null if SOURCE_HOME is not available. | |
| + * | |
| + * @return Path to server/solr directory, or null if not running in Solr source tree | |
| */ | |
| - public static Path WEBAPP_HOME = SOURCE_HOME.resolve("webapp/web").toAbsolutePath(); | |
| + public static Path getServerHome() { | |
| + if (serverHome == null && SOURCE_HOME != null) { | |
| + synchronized (ExternalPaths.class) { | |
| + if (serverHome == null) { | |
| + serverHome = SOURCE_HOME.resolve("server/solr").toAbsolutePath(); | |
| + } | |
| + } | |
| + } | |
| + return serverHome; | |
| + } | |
| /** | |
| - * @see #SOURCE_HOME | |
| + * Backward compatibility - deprecated in favor of getWebappHome() | |
| + * | |
| + * @deprecated Use {@link #getWebappHome()} instead. This field may be null when running in | |
| + * external plugin projects. | |
| */ | |
| - public static Path DEFAULT_CONFIGSET = | |
| - SOURCE_HOME.resolve("server/solr/configsets/_default/conf").toAbsolutePath(); | |
| + @Deprecated | |
| + public static final Path WEBAPP_HOME = getWebappHome(); | |
| /** | |
| - * @see #SOURCE_HOME | |
| + * Backward compatibility - deprecated in favor of getDefaultConfigSet() | |
| + * | |
| + * @deprecated Use {@link #getDefaultConfigSet()} instead. This field may be null when running in | |
| + * external plugin projects. | |
| */ | |
| - public static Path TECHPRODUCTS_CONFIGSET = | |
| - SOURCE_HOME | |
| - .resolve("server/solr/configsets/sample_techproducts_configs/conf") | |
| - .toAbsolutePath(); | |
| + @Deprecated | |
| + public static final Path DEFAULT_CONFIGSET = getDefaultConfigSet(); | |
| /** | |
| - * @see #SOURCE_HOME | |
| + * Backward compatibility - deprecated in favor of getTechproductsConfigSet() | |
| + * | |
| + * @deprecated Use {@link #getTechproductsConfigSet()} instead. This field may be null when | |
| + * running in external plugin projects. | |
| */ | |
| - public static Path SERVER_HOME = SOURCE_HOME.resolve("server/solr").toAbsolutePath(); | |
| + @Deprecated | |
| + public static final Path TECHPRODUCTS_CONFIGSET = getTechproductsConfigSet(); | |
| + | |
| + /** | |
| + * Backward compatibility - deprecated in favor of getServerHome() | |
| + * | |
| + * @deprecated Use {@link #getServerHome()} instead. This field may be null when running in | |
| + * external plugin projects. | |
| + */ | |
| + @Deprecated | |
| + public static final Path SERVER_HOME = getServerHome(); | |
| /** | |
| * Ugly, ugly hack to determine the example home without depending on the CWD this is needed for | |
| @@ -69,9 +165,24 @@ public class ExternalPaths { | |
| * determined, this method returns null. | |
| */ | |
| static Path determineSourceHome() { | |
| + // Allow explicit override for external plugin projects via system property | |
| + String explicitSourceHome = System.getProperty("solr.test.source.home"); | |
| + if (explicitSourceHome != null && !explicitSourceHome.isEmpty()) { | |
| + Path explicitPath = Path.of(explicitSourceHome); | |
| + if (Files.isDirectory(explicitPath)) { | |
| + log.info("Using explicit Solr test source home: {}", explicitPath); | |
| + return explicitPath.toAbsolutePath(); | |
| + } else { | |
| + log.warn("Explicit solr.test.source.home is not a directory: {}", explicitPath); | |
| + } | |
| + } | |
| + | |
| try { | |
| + // Try to find solr/conf in the filesystem first | |
| Path file = Path.of("solr/conf"); | |
| + | |
| if (!Files.exists(file)) { | |
| + // Try to find it in the classpath | |
| URL resourceUrl = ExternalPaths.class.getClassLoader().getResource("solr/conf"); | |
| if (resourceUrl != null) { | |
| file = Path.of(resourceUrl.toURI()); | |
| @@ -82,15 +193,30 @@ public class ExternalPaths { | |
| } | |
| } | |
| + // Walk up the directory tree looking for the Solr source marker file | |
| Path base = file.toAbsolutePath(); | |
| - while (!Files.exists(base.resolve("solr/test-framework/build.gradle")) && null != base) { | |
| + while (base != null && !Files.exists(base.resolve("solr/test-framework/build.gradle"))) { | |
| base = base.getParent(); | |
| } | |
| - return (null == base) ? null : base.resolve("solr/").toAbsolutePath(); | |
| + | |
| + if (base == null) { | |
| + log.info( | |
| + "Could not determine Solr source home - not running in Solr source tree. " | |
| + + "This is expected for external plugin projects. " | |
| + + "Set -Dsolr.test.source.home=/path/to/solr if you need ExternalPaths."); | |
| + return null; | |
| + } | |
| + | |
| + Path sourceHome = base.resolve("solr/").toAbsolutePath(); | |
| + log.debug("Determined Solr source home: {}", sourceHome); | |
| + return sourceHome; | |
| } catch (Exception e) { | |
| - // all bets are off | |
| - throw new SolrException( | |
| - SolrException.ErrorCode.SERVER_ERROR, "Failed to determine source home", e); | |
| + // Gracefully return null for external plugin projects instead of throwing | |
| + log.warn( | |
| + "Failed to determine Solr source home - returning null. " | |
| + + "This is expected for external plugin projects: {}", | |
| + e.toString()); | |
| + return null; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment