/*
* Copyright (c) 2010-2016 Evolveum
*
* 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
*
* http://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 com.evolveum.midpoint.init;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;
import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration;
import com.evolveum.midpoint.util.ClassPathUtil;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import org.apache.commons.configuration.*;
import org.apache.wss4j.dom.engine.WSSConfig;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Iterator;
public class StartupConfiguration implements MidpointConfiguration {
private static final Trace LOGGER = TraceManager.getTrace(StartupConfiguration.class);
private static final String USER_HOME = "user.home";
private static final String MIDPOINT_HOME = "midpoint.home";
private static final String MIDPOINT_SECTION = "midpoint";
private static final String SAFE_MODE = "safeMode";
private static final String PROFILING_ENABLED = "profilingEnabled";
private static final String DEFAULT_CONFIG_FILE_NAME = "config.xml";
private static final String LOGBACK_CONFIG_FILENAME = "logback.xml";
private CompositeConfiguration config = null;
private Document xmlConfigAsDocument = null; // just in case when we need to access original XML document
private String configFilename = null;
/**
* Default constructor
*/
public StartupConfiguration() {
this.configFilename = DEFAULT_CONFIG_FILE_NAME;
}
/**
* Constructor
*
* @param configFilename alternative configuration file
*/
public StartupConfiguration(String configFilename) {
this.configFilename = configFilename;
}
/**
* Get current configuration file name
*
* @return
*/
public String getConfigFilename() {
return this.configFilename;
}
/**
* Set configuration filename
*
* @param configFilename
*/
public void setConfigFilename(String configFilename) {
this.configFilename = configFilename;
}
@Override
public String getMidpointHome() {
return System.getProperty(MIDPOINT_HOME);
}
@Override
public Configuration getConfiguration(String componentName) {
if (null == componentName) {
throw new IllegalArgumentException("NULL argument");
}
Configuration sub = config.subset(componentName);
// Insert replacement for relative path to midpoint.home else clean
// replace
if (getMidpointHome() != null) {
sub.addProperty(MIDPOINT_HOME, getMidpointHome());
} else {
@SuppressWarnings("unchecked")
Iterator<String> i = sub.getKeys();
while (i.hasNext()) {
String key = i.next();
sub.setProperty(key, sub.getString(key).replace("${" + MIDPOINT_HOME + "}/", ""));
sub.setProperty(key, sub.getString(key).replace("${" + MIDPOINT_HOME + "}", ""));
}
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Configuration for {} :", componentName);
@SuppressWarnings("unchecked")
Iterator<String> i = sub.getKeys();
while (i.hasNext()) {
String key = i.next();
LOGGER.debug(" {} = {}", key, sub.getString(key));
}
}
return sub;
}
/**
* Initialize system configuration
*/
public void init() {
welcome();
if (System.getProperty(MIDPOINT_HOME) == null || System.getProperty(MIDPOINT_HOME).isEmpty()) {
LOGGER.warn("*****************************************************************************************");
LOGGER.warn(MIDPOINT_HOME
+ " is not set ! Using default configuration, for more information see http://wiki.evolveum.com/display/midPoint/");
LOGGER.warn("*****************************************************************************************");
System.out.println("*******************************************************************************");
System.out.println(MIDPOINT_HOME + " is not set ! Using default configuration, for more information");
System.out.println(" see http://wiki.evolveum.com/display/midPoint/");
System.out.println("*******************************************************************************");
if (getConfigFilename().startsWith("test")) {
String midpointHome = "./target/midpoint-home";
System.setProperty(MIDPOINT_HOME, midpointHome);
System.out.println("Using " + MIDPOINT_HOME + " for test runs: '" + midpointHome + "'.");
} else {
String userHome = System.getProperty(USER_HOME);
if (!userHome.endsWith("/")) {
userHome += "/";
}
userHome += "midpoint";
System.setProperty(MIDPOINT_HOME, userHome);
LOGGER.warn("Setting {} to '{}'.", new Object[] { MIDPOINT_HOME, userHome });
System.out.println("Setting " + MIDPOINT_HOME + " to '" + userHome + "'.");
}
}
String midpointHomeString = System.getProperty(MIDPOINT_HOME);
if (midpointHomeString != null) {
//Fix missing last slash in path
if (!midpointHomeString.endsWith("/")) {
midpointHomeString = midpointHomeString + "/";
System.setProperty(MIDPOINT_HOME, midpointHomeString);
}
}
File midpointHome = new File(midpointHomeString);
setupInitialLogging(midpointHome);
loadConfiguration(midpointHome);
if (isSafeMode()) {
LOGGER.info("Safe mode is ON; setting tolerateUndeclaredPrefixes to TRUE");
QNameUtil.setTolerateUndeclaredPrefixes(true);
}
// Make sure that this is called very early in the startup sequence.
// This is needed to properly initialize the resources
// (the "org/apache/xml/security/resource/xmlsecurity" resource bundle error)
WSSConfig.init();
}
/**
* Loading logic
*/
private void loadConfiguration(File midpointHome) {
if (config != null) {
config.clear();
} else {
config = new CompositeConfiguration();
}
DocumentBuilder documentBuilder = DOMUtil.createDocumentBuilder(); // we need namespace-aware document builder (see GeneralChangeProcessor.java)
if (midpointHome != null) {
ApplicationHomeSetup ah = new ApplicationHomeSetup();
ah.init(MIDPOINT_HOME);
File configFile = new File(midpointHome, this.getConfigFilename());
System.out.println("Loading midPoint configuration from file "+configFile);
LOGGER.info("Loading midPoint configuration from file {}", configFile);
try {
if (!configFile.exists()) {
LOGGER.warn("Configuration file {} does not exists. Need to do extraction ...", configFile);
ClassPathUtil.extractFileFromClassPath(this.getConfigFilename(), configFile.getPath());
}
//Load and parse properties
config.addProperty(MIDPOINT_HOME, System.getProperty(MIDPOINT_HOME));
createXmlConfiguration(documentBuilder, configFile.getPath());
} catch (ConfigurationException e) {
String message = "Unable to read configuration file [" + configFile + "]: " + e.getMessage();
LOGGER.error(message);
System.out.println(message);
throw new SystemException(message, e); // there's no point in continuing with midpoint initialization
}
} else {
// Load from current directory
try {
createXmlConfiguration(documentBuilder, this.getConfigFilename());
} catch (ConfigurationException e) {
String message = "Unable to read configuration file [" + this.getConfigFilename() + "]: " + e.getMessage();
LOGGER.error(message);
System.out.println(message);
throw new SystemException(message, e);
}
}
}
private void setupInitialLogging(File midpointHome) {
File logbackConfigFile = new File(midpointHome, LOGBACK_CONFIG_FILENAME);
if (!logbackConfigFile.exists()) {
return;
}
LOGGER.info("Loading additional logging configuration from {}", logbackConfigFile);
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
try {
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(context);
configurator.doConfigure(logbackConfigFile);
} catch (JoranException je) {
// StatusPrinter will handle this
} catch (Exception ex) {
ex.printStackTrace();
}
StatusPrinter.printInCaseOfErrorsOrWarnings(context);
}
private void createXmlConfiguration(DocumentBuilder documentBuilder, String filename) throws ConfigurationException {
XMLConfiguration xmlConfig = new XMLConfiguration();
xmlConfig.setDocumentBuilder(documentBuilder);
xmlConfig.setFileName(filename);
xmlConfig.load();
config.addConfiguration(xmlConfig);
xmlConfigAsDocument = DOMUtil.parseFile(filename);
}
@Override
public Document getXmlConfigAsDocument() {
return xmlConfigAsDocument;
}
@Override
public boolean isSafeMode() {
Configuration c = getConfiguration(MIDPOINT_SECTION);
if (c == null) {
return false; // should not occur
}
return c.getBoolean(SAFE_MODE, false);
}
@Override
public boolean isProfilingEnabled() {
Configuration c = getConfiguration(MIDPOINT_SECTION);
if (c == null) {
return false; // should not occur
}
return c.getBoolean(PROFILING_ENABLED, false);
}
@Override
public String toString() {
@SuppressWarnings("unchecked")
Iterator<String> i = config.getKeys();
StringBuilder sb = new StringBuilder();
while (i.hasNext()) {
String key = i.next();
sb.append(key);
sb.append(" = ");
sb.append(config.getString(key));
sb.append("; ");
}
return sb.toString();
}
private void welcome() {
try {
Configuration info = new PropertiesConfiguration("midpoint.info");
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");
LOGGER.info("+--------------------------------------------------------------------------------------------+");
LOGGER.info("| _ | | _ \\ _ _| |_");
LOGGER.info("| ___ ____ (_) __| | |_) |___ (_)___|_ _|");
LOGGER.info("| | _ ` _ `| |/ _ | __/ _ \\| | _` | |");
LOGGER.info("| | | | | | | | (_| | | | (_) | | | | | |_");
LOGGER.info("| |_| |_| |_|_|\\____|_| \\____/|_|_| |_|\\__| by Evolveum and partners");
LOGGER.info("|");
LOGGER.info("| Licensed under the Apache License, Version 2.0 see: http://www.apache.org/licenses/LICENSE-2.0");
LOGGER.info("| Version : " + info.getString("midpoint.version"));
// try {
// LOGGER.info("| Build : " + info.getString("midpoint.build") + " at "
// + formatter.format(new Date(info.getLong("midpoint.timestamp"))));
// } catch (NumberFormatException ex) {
// LOGGER.info("| Build : " + info.getString("midpoint.build"));
// }
LOGGER.info("| Sources : " + info.getString("midpoint.scm") + " branch: " + info.getString("midpoint.branch"));
LOGGER.info("| Bug reporting system : " + info.getString("midpoint.jira"));
LOGGER.info("| Product information : http://wiki.evolveum.com/display/midPoint");
LOGGER.info("+---------------------------------------------------------------------------------------------+");
} catch (ConfigurationException e) {
//NOTHING just skip
}
}
}