SolrAutoConfigurationDisabler.java

/*******************************************************************************
 * Copyright (c) 2025 Eclipse RDF4J contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Distribution License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *******************************************************************************/
// Some portions generated by Codex
package org.eclipse.rdf4j.tools.serverboot.config;

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;

/**
 * Disables Spring Boot's automatic Solr client setup unless explicitly enabled through the {@code rdf4j.solr.enabled}
 * property. This prevents accidental attempts to talk to a local Solr instance when {@code rdf4j-sail-solr} happens to
 * be on the classpath as a transitive dependency.
 */
public class SolrAutoConfigurationDisabler
		implements ApplicationContextInitializer<ConfigurableApplicationContext>, EnvironmentPostProcessor, Ordered {

	static final String RDF4J_SOLR_ENABLED_PROPERTY = "rdf4j.solr.enabled";
	private static final String SPRING_AUTOCONFIG_EXCLUDE = "spring.autoconfigure.exclude";
	private static final String PROPERTY_SOURCE_NAME = "rdf4jSolrAutoConfiguration";

	private static final Set<String> SOLR_AUTOCONFIG_CLASSES = Set.of(
			"org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration",
			"org.springframework.boot.actuate.autoconfigure.solr.SolrHealthContributorAutoConfiguration");

	@Override
	public void initialize(ConfigurableApplicationContext applicationContext) {
		updateEnvironment(applicationContext.getEnvironment());
	}

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
		updateEnvironment(environment);
	}

	private void updateEnvironment(ConfigurableEnvironment environment) {
		boolean solrEnabled = environment.getProperty(RDF4J_SOLR_ENABLED_PROPERTY, Boolean.class, Boolean.FALSE);
		if (solrEnabled) {
			return;
		}

		LinkedHashSet<String> excludes = new LinkedHashSet<>();
		String existingExcludes = environment.getProperty(SPRING_AUTOCONFIG_EXCLUDE);
		if (existingExcludes != null) {
			excludes.addAll(Arrays.stream(existingExcludes.split(","))
					.map(String::trim)
					.filter(entry -> !entry.isEmpty())
					.collect(Collectors.toCollection(LinkedHashSet::new)));
		}

		if (!excludes.addAll(SOLR_AUTOCONFIG_CLASSES)) {
			// All entries were already present - nothing to do.
			return;
		}

		Map<String, Object> properties = Map.of(SPRING_AUTOCONFIG_EXCLUDE, String.join(",", excludes));
		environment.getPropertySources().addFirst(new MapPropertySource(PROPERTY_SOURCE_NAME, properties));
	}

	@Override
	public int getOrder() {
		return 0;
	}
}