All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.junitpioneer.jupiter.EnvironmentVariableExtension Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016-2023 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v2.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v20.html
 */

package org.junitpioneer.jupiter;

import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.toSet;

import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;

import org.junit.jupiter.api.extension.ExtensionContext;

class EnvironmentVariableExtension extends
		AbstractEntryBasedExtension {

	// package visible to make accessible for tests
	static final AtomicBoolean REPORTED_WARNING = new AtomicBoolean(false);
	static final String WARNING_KEY = EnvironmentVariableExtension.class.getSimpleName();
	static final String WARNING_VALUE = "This extension uses reflection to access and modify JDK internals, which is fragile."
			+ "Have a look at the documentation for further details:"
			+ "https://junit-pioneer.org/docs/environment-variables/#warnings-for-reflective-access";

	@Override
	protected Function clearKeyMapper() {
		return ClearEnvironmentVariable::key;
	}

	@Override
	protected Function setKeyMapper() {
		return SetEnvironmentVariable::key;
	}

	@Override
	protected Function setValueMapper() {
		return SetEnvironmentVariable::value;
	}

	@Override
	protected void reportWarning(ExtensionContext context) {
		boolean wasReported = REPORTED_WARNING.getAndSet(true);
		if (wasReported)
			return;

		// Log as report entry and to System.out - check docs for reasons, but why System.out?
		// Because report entries lack tool support and are easily lost and System.err is
		// too invasive (particularly since, with good configuration, the module system won't
		// print a warning and hence it's only Pioneer polluting System.err - not good).
		// System.out seemed like a good compromise.
		context.publishReportEntry(WARNING_KEY, WARNING_VALUE);
		System.out.println(WARNING_KEY + ": " + WARNING_VALUE); //NOSONAR
	}

	@Override
	protected void clearEntry(String key) {
		EnvironmentVariableUtils.clear(key);
	}

	@Override
	protected String getEntry(String key) {
		return System.getenv(key);
	}

	@Override
	protected void setEntry(String key, String value) {
		EnvironmentVariableUtils.set(key, value);
	}

	/**
	 * This implementation uses the "Post swap" strategy, returning a clone of the environment variables
	 * which will be restored in {@link AbstractEntryBasedExtension#prepareToExitRestorableContext}.
	 *
	 * 

See {@link AbstractEntryBasedExtension#prepareToEnterRestorableContext} for more details.

* * @return A clone of the current environment variables, as a {@code Properties} object. */ @Override protected Properties prepareToEnterRestorableContext() { Properties clone = new Properties(); clone.putAll(System.getenv()); return clone; } @Override protected void prepareToExitRestorableContext(Properties restoreMe) { Map existingEnv = System.getenv(); // Set all values, but only if different from actual value restoreMe .entrySet() .stream() .filter(e -> !e.getValue().equals(System.getenv(e.getKey().toString()))) .forEach(e -> setEntry(e.getKey().toString(), e.getValue().toString())); // Find entries to remove. // Cannot remove in stream b/c the stream is based on the collection that needs to be modified Set entriesToClear = existingEnv.keySet().stream().filter(not(restoreMe::containsKey)).collect(toSet()); entriesToClear.forEach(this::clearEntry); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy