/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.globalconfig.api;
import static com.typesafe.config.ConfigFactory.invalidateCaches;
import static com.typesafe.config.ConfigSyntax.JSON;
import static java.lang.String.format;
import static org.mule.runtime.api.i18n.I18nMessageFactory.createStaticMessage;
import static org.mule.runtime.globalconfig.internal.MavenConfigBuilder.buildMavenConfig;
import static org.mule.runtime.globalconfig.internal.MavenConfigBuilder.buildNullMavenConfig;
import org.mule.maven.client.api.model.MavenConfiguration;
import org.mule.runtime.globalconfig.api.exception.RuntimeGlobalConfigException;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigParseOptions;
import com.typesafe.config.ConfigRenderOptions;
import com.typesafe.config.ConfigResolveOptions;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.locks.StampedLock;
import org.everit.json.schema.Schema;
import org.everit.json.schema.ValidationException;
import org.everit.json.schema.loader.SchemaLoader;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Mule Runtime global configuration loader.
*
* @since 4.0
*/
public class GlobalConfigLoader {
private static final String CONFIG_ROOT_ELEMENT_NAME = "muleRuntimeConfig";
private static Logger LOGGER = LoggerFactory.getLogger(GlobalConfigLoader.class);
private static MavenConfiguration mavenConfig;
private static StampedLock lock = new StampedLock();
private static final String MULE_SCHEMA_JSON_LOCATION = "mule-schema.json";
/**
* Initialise the global config if not yet initialised.
* <p>
* Validates the provided configuration against a JSON schema
*/
private static void initialiseGlobalConfig() {
Config config =
ConfigFactory.load(GlobalConfigLoader.class.getClassLoader(), "mule-config",
ConfigParseOptions.defaults().setSyntax(JSON), ConfigResolveOptions.defaults());
Config muleRuntimeConfig = config.hasPath(CONFIG_ROOT_ELEMENT_NAME) ? config.getConfig(CONFIG_ROOT_ELEMENT_NAME) : null;
if (muleRuntimeConfig == null) {
mavenConfig = buildNullMavenConfig();
} else {
String effectiveConfigAsJson =
muleRuntimeConfig.root().render(ConfigRenderOptions.concise().setJson(true).setComments(false));
String prettyPrintConfig = muleRuntimeConfig.root()
.render(ConfigRenderOptions.defaults().setComments(true).setJson(true).setFormatted(true));
try (
InputStream schemaStream = GlobalConfigLoader.class.getClassLoader().getResourceAsStream(MULE_SCHEMA_JSON_LOCATION)) {
JSONObject rawSchema = new JSONObject(new JSONTokener(schemaStream));
Schema schema = SchemaLoader.load(rawSchema);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Using effective mule-config.json configuration: \n"
+ prettyPrintConfig);
}
schema.validate(new JSONObject(effectiveConfigAsJson));
Config mavenConfig = muleRuntimeConfig.getConfig("maven");
if (mavenConfig != null) {
GlobalConfigLoader.mavenConfig = buildMavenConfig(mavenConfig);
} else {
GlobalConfigLoader.mavenConfig = buildNullMavenConfig();
}
} catch (ValidationException e) {
LOGGER
.info("Mule global config exception. Effective configuration is (config is a merge of MULE_HOME/conf/mule-config.json and system properties): \n "
+ prettyPrintConfig);
throw new RuntimeGlobalConfigException(e);
} catch (IOException e) {
throw new RuntimeGlobalConfigException(
createStaticMessage(format("resources %s missing from the runtime classpath",
MULE_SCHEMA_JSON_LOCATION)),
e);
}
}
}
/**
* Resets the maven configuration. If new system properties were added, those will be taken into account after reloading the
* config.
*/
public static void reset() {
long stamp = lock.writeLock();
try {
mavenConfig = null;
invalidateCaches();
initialiseGlobalConfig();
} finally {
lock.unlockWrite(stamp);
}
}
/**
* @return the maven configuration to use for the runtime.
*/
public static MavenConfiguration getMavenConfig() {
long stamp = lock.readLock();
try {
if (mavenConfig == null) {
stamp = lock.tryConvertToWriteLock(stamp);
if (stamp == 0L) {
stamp = lock.writeLock();
}
initialiseGlobalConfig();
}
return mavenConfig;
} finally {
lock.unlock(stamp);
}
}
}