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

org.omnifaces.utils.properties.PropertiesUtils Maven / Gradle / Ivy

There is a newer version: 0.14
Show newest version
/*
 * Copyright 2021 OmniFaces
 *
 * Licensed 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
 *
 *     https://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.omnifaces.utils.properties;

import static java.lang.System.getProperty;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableMap;
import static java.util.logging.Level.SEVERE;
import static org.omnifaces.utils.properties.PropertiesUtils.PropertiesFormat.LIST;
import static org.omnifaces.utils.properties.PropertiesUtils.PropertiesFormat.XML;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Properties;
import java.util.function.BiConsumer;
import java.util.logging.Logger;

public final class PropertiesUtils {

	private static final Logger logger = Logger.getLogger(PropertiesUtils.class.getName());
	private static final String CONFIGURATION_BASE_DIR = "/conf/";
	private static final String META_INF_CONFIGURATION_BASE_DIR = "META-INF/conf/";

	public static enum PropertiesFormat {XML, LIST}

	private PropertiesUtils() {
	}

	public static Map loadPropertiesFromClasspath(String baseName) {

		Map properties = new HashMap<>();

		getResource(baseName + ".xml").ifPresent(url -> loadPropertiesFromUrl(url, properties, XML));
		getResource(baseName + ".properties").ifPresent(url -> loadPropertiesFromUrl(url, properties, LIST));

		return unmodifiableMap(properties);
	}

	/**
	 * Loads the properties file in properties list format with the given name from the configuration directory of META-INF with support for staging.
	 *
	 * The properties will loaded from the default properties file and the properties file from the given stage. If both files contain properties with
	 * the same key, the returned Map object will only contain the stage specific ones.
	 *
	 * @param fileName the file name of the properties file
	 * @param stageSystemPropertyName the name of the system property from which the stage is read
	 * @param defaultStage the default stage
	 * @return an immutable map instance containing the key/value pairs from the given file
	 */
	public static Map loadPropertiesListStagedFromClassPath(String fileName, String stageSystemPropertyName, String defaultStage) {
		return loadStagedFromClassPath(PropertiesUtils::loadListFromURL, fileName, stageSystemPropertyName, defaultStage);
	}

	/**
	 * Loads the properties file in XML format with the given name from the configuration directory of META-INF with support for staging.
	 *
	 * The properties will loaded from the default properties file and the  properties file from the given stage. If both files contain properties
	 * with the same key, the returned Map object will only contain the stage specific ones.
	 *
	 * @param fileName
	 * 		the file name of the properties file
	 * @param stageSystemPropertyName
	 * 		the name of the system property from which the stage is read
	 * @param defaultStage
	 * 		the default stage
	 * @return an immutable map instance containing the key/value pairs from the given file
	 */
	public static Map loadXMLPropertiesStagedFromClassPath(String fileName, String stageSystemPropertyName, String defaultStage) {
		return loadStagedFromClassPath(PropertiesUtils::loadXMLFromURL, fileName, stageSystemPropertyName, defaultStage);
	}

	public static Map loadStagedFromClassPath(BiConsumer> loadMethod, String fileName, String stageSystemPropertyName, String defaultStage) {

		String stage = getStage(stageSystemPropertyName, defaultStage);

		Map settings = new HashMap<>();

		asList(META_INF_CONFIGURATION_BASE_DIR + fileName, META_INF_CONFIGURATION_BASE_DIR + stage + "/" + fileName)
			.forEach(
				path -> getResource(path)
							.ifPresent(
								url -> loadMethod.accept(url, settings)));

		return unmodifiableMap(settings);
	}


	/**
	 * Loads the properties file in properties list format with the given name from the configuration directory of an EAR with support for staging.
	 *
	 * The properties will loaded from the default properties file and the properties file from the given stage. If both files contain properties with
	 * the same key, the returned Map object will only contain the stage specific ones.
	 *
	 * @param fileName
	 * 		the file name of the properties file
	 * @param stageSystemPropertyName
	 * 		the name of the system property from which the stage is read
	 * @return an immutable map instance containing the key/value pairs from the given file
	 */
	public static Map loadPropertiesListStagedFromEar(String fileName, String stageSystemPropertyName) {
		return loadStagedFromEar(PropertiesUtils::loadListFromUrl, fileName, stageSystemPropertyName);
	}

	/**
	 * Loads the properties file in XML format with the given name from the configuration directory of an EAR with support for staging.
	 *
	 * The properties will loaded from the default properties file and the  properties file from the given stage. If both files contain properties
	 * with the same key, the returned Map object will only contain the stage specific ones.
	 *
	 * @param fileName
	 *            the file name of the properties file
	 * @param stageSystemPropertyName
	 *            the name of the system property from which the stage is read
	 * @return an immutable map instance containing the key/value pairs from the
	 *         given file
	 */
	public static Map loadXMLPropertiesStagedFromEar(String fileName, String stageSystemPropertyName) {
		return loadStagedFromEar(PropertiesUtils::loadXMLFromUrl, fileName, stageSystemPropertyName);
	}

	public static Map loadStagedFromEar(BiConsumer> loadMethod, String fileName, String stageSystemPropertyName) {

		String earBaseUrl = getEarBaseUrl();
		String stage = getProperty(stageSystemPropertyName);
		if (stage == null) {
			throw new IllegalStateException(stageSystemPropertyName + " property not found. Please add it to VM arguments, e.g. -D" + stageSystemPropertyName + "=some_stage");
		}

		Map settings = new HashMap<>();

		loadMethod.accept(earBaseUrl + CONFIGURATION_BASE_DIR + fileName, settings);
		loadMethod.accept(earBaseUrl + CONFIGURATION_BASE_DIR + stage + "/" + fileName, settings);

		return unmodifiableMap(settings);
	}

	public static String getEarBaseUrl() {
		Optional dummyUrl = getResource("META-INF/dummy.txt");

		if (dummyUrl.isPresent()) {
			String dummyExternalForm = dummyUrl.get().toExternalForm();

			// Exploded deployment JBoss example
			// vfs:/opt/jboss/standalone/deployments/someapp.ear/someapp.jar/META-INF/dummy.txt

			// Packaged deployment JBoss example
			// vfs:/content/someapp.ear/someapp.jar/META-INF/dummy.txt

			int jarPos = dummyExternalForm.lastIndexOf(".jar");
			if (jarPos != -1) {

				String withoutJar = dummyExternalForm.substring(0, jarPos);
				int lastSlash = withoutJar.lastIndexOf('/');

				withoutJar = withoutJar.substring(0, lastSlash);

				if (withoutJar.endsWith("/lib")) {
					withoutJar = withoutJar.substring(0, withoutJar.length() - 4);
				}

				if (withoutJar.endsWith("/WEB-INF")) {
					withoutJar += "/classes";
				}

				return withoutJar;
			}

			// TODO add support for other servers and JRebel

			throw new IllegalStateException("Can't derive EAR root from: " + dummyExternalForm);
		}

		throw new IllegalStateException("Can't find META-INF/dummy.txt on the classpath. This file should be present in a jar in the ear/lib folder");
	}

	public static void loadListFromUrl(String url, Map settings) {
		loadPropertiesFromUrl(url, settings, LIST);
	}

	public static void loadXMLFromUrl(String url, Map settings) {
		loadPropertiesFromUrl(url, settings, XML);
	}

	public static void loadListFromURL(URL url, Map settings) {
		loadPropertiesFromUrl(url, settings, LIST);
	}

	public static void loadXMLFromURL(URL url, Map settings) { // TODO name not ideal
		loadPropertiesFromUrl(url, settings, XML);
	}

	public static void loadPropertiesFromUrl(String url, Map settings, PropertiesFormat propertiesFormat) {
		try {
			loadPropertiesFromUrl(new URL(url), settings, propertiesFormat);
		} catch (MalformedURLException e) {
			logger.log(SEVERE, "Error while loading settings.", e);
		}
	}

	public static void loadPropertiesFromUrl(URL url, Map settings, PropertiesFormat propertiesFormat) {
		try {
			loadPropertiesFromStream(url.openStream(), url.toString(), settings, propertiesFormat);
		} catch (IOException e) {
			logger.log(SEVERE, "Error while loading settings.", e);
		}
	}
	
	public static void loadPropertiesFromStream(InputStream in, String locationDescription, Map settings, PropertiesFormat propertiesFormat) {
		Properties properties = new Properties();
		try {

			if (propertiesFormat == XML) {
				properties.loadFromXML(in);
			} else {
				properties.load(in);
			}

			logger.info(String.format("Loaded %d settings from %s.", properties.size(), locationDescription));

			for (Entry entry : properties.entrySet()) {
				settings.put((String) entry.getKey(), (String) entry.getValue());
			}

		} catch (IOException e) {
			logger.log(SEVERE, "Error while loading settings.", e);
		}
	}
	
	public static String getStage(String stageSystemPropertyName, String defaultStage) {
		String stage = getProperty(stageSystemPropertyName);
		if (stage == null) {
			if (defaultStage == null) {
				throw new IllegalStateException(stageSystemPropertyName + " property not found. Please add it to VM arguments, e.g. -D" + stageSystemPropertyName + "=some_stage");
			}

			stage = defaultStage;
		}

		return stage;
	}

	private static Optional getResource(String name) {
		URL url = Thread.currentThread().getContextClassLoader().getResource(name);
		if (url == null) {
			url = PropertiesUtils.class.getClassLoader().getResource(name);
		}
		return Optional.ofNullable(url);
	}



}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy