package net.sf.gazpachoquest.bootstrap;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.servlet.ServletContext;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
public class EnviromentDiscovery implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
private static final Logger logger = LoggerFactory.getLogger(EnviromentDiscovery.class);
private static final String CONFIG_FILE_NAME = "config.properties";
private static final String GAZPACHO_QUEST_ENGINE_NAME = "gazpachoQuestEngineName";
@Override
public void initialize(ConfigurableWebApplicationContext ctx) {
ConfigurableEnvironment environment = ctx.getEnvironment();
ServletContext servletContext = ctx.getServletContext();
String contextPath = servletContext.getContextPath();
// This variable has the same meaning as host, but i can be redefined in
// case of cluster deployment.
String engineName = resolveEngineName(environment);
logger.info("Application deployed int host {} using context path: {}", engineName, contextPath);
InputStream configurationSource = getResourceAsStream(servletContext, engineName, contextPath, CONFIG_FILE_NAME);
Properties config = new Properties();
try {
config.load(configurationSource);
} catch (IOException | NullPointerException | IllegalArgumentException e) {
throw new IllegalStateException("Initilizatition Error. Couldn't load " + CONFIG_FILE_NAME);
}
InputStream logbackSource = getResourceAsStream(servletContext, engineName, contextPath, "logback.xml");
try {
if (logbackSource != null) {
reconfigureLogback(logbackSource);
}
} catch (JoranException e) {
// At this point logback has crashed.
throw new IllegalStateException("Errors when reconfiguring logback", e);
}
String dbEngine = config.getProperty("db.engine.name");
String managedBy = config.getProperty("dbpool.managedBy");
String port = config.getProperty("http.port");
String schema = config.getProperty("http.schema");
String hostAlias = config.getProperty("http.host.alias");
logger.info("Database engine {}", dbEngine);
logger.info("DBPool Managed By: {}", managedBy);
logger.info("Default port: {}", port);
logger.info("Host Alias: {}", hostAlias);
logger.info("Schema: {}", schema);
// Define baseURI
String basePath = createBasePath(schema, hostAlias, port, contextPath);
servletContext.setAttribute("basePath", basePath);
environment.addActiveProfile(managedBy);
logger.info("Application running using {} profiles: {}", environment.getActiveProfiles().length,
Arrays.toString(environment.getActiveProfiles()));
try {
Map<String, Object> props = new HashMap<>();
for (String key : config.stringPropertyNames()) {
props.put(key, config.getProperty(key));
}
props.put("basePath", basePath);
MapPropertySource mapSource = new MapPropertySource("props", props);
environment.getPropertySources().addLast(mapSource);
environment.getPropertySources().addLast(
new ResourcePropertySource(String.format("classpath:/database/%s.properties", dbEngine)));
} catch (IOException e) {
throw new IllegalStateException(dbEngine + ".properties not found in classpath", e);
}
// Register hook to close application context on JVM shutdown
ctx.registerShutdownHook();
}
private String resolveEngineName(ConfigurableEnvironment environment) {
String engineName = environment.getProperty(GAZPACHO_QUEST_ENGINE_NAME);
if (StringUtils.isNotBlank(engineName)) {
return engineName;
}
try {
engineName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e1) {
logger.warn("Impossible to get host name.");
}
return engineName;
}
private String createBasePath(String schema, String host, String port, String contextPath) {
StringBuilder builder = new StringBuilder();
builder.append(schema).append("://");
builder.append(host);
if (!port.equals("80")) {
builder.append(":").append(port);
}
builder.append(contextPath);
return builder.toString();
}
public void reconfigureLogback(InputStream source) throws JoranException {
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator jc = new JoranConfigurator();
jc.setContext(context);
context.reset(); // override default configuration // inject the name of
// the current application as "application-name" //
// property of the LoggerContext
// context.putProperty("application-name",
// NAME_OF_CURRENT_APPLICATION);
// jc.doConfigure("/path/to/the/above/configuration/file.xml")
jc.doConfigure(source);
}
private InputStream getResourceAsStream(ServletContext servletContext, String host, String contextPath,
String fileName) {
String paths[] = { String.format("/WEB-INF/config/%s/%s", host, fileName),
String.format("/WEB-INF/config/%s%s/%s", host, contextPath, fileName),
String.format("/WEB-INF/config/default/%s", fileName) };
InputStream is = null;
int idx = 0;
do {
is = servletContext.getResourceAsStream(paths[idx]);
idx++;
} while (is == null && idx < paths.length);
if (is != null) {
logger.info("Loading {} file from path {}", fileName, paths[--idx]);
}
return is;
}
}