/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.configuration;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletContext;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.configuration.ModuleLifeCycle;
import org.olat.core.configuration.OLATModule;
import org.olat.core.extensions.ExtensionManager;
import org.olat.core.logging.OLog;
import org.olat.core.logging.StartupException;
import org.olat.core.logging.Tracing;
import org.olat.properties.Property;
import org.olat.properties.PropertyManager;
import org.olat.upgrade.UpgradeManager;
import com.anthonyeden.lib.config.Configuration;
import com.anthonyeden.lib.config.ConfigurationException;
import com.anthonyeden.lib.config.XMLConfiguration;
/**
* Initial Date: 24.04.2004
*
* @author Mike Stock
* @author guido
*/
public class ConfigurationManager implements ModuleLifeCycle {
OLog log = Tracing.createLoggerFor(this.getClass());
private static final String CONFIG_FILE = "olat_config.xml";
private static final String PROPERTY_CATEGORY = "classConfig";
private Configuration configuration;
private List<OLATModule> modules;
private UpgradeManager upgradeManager;
/**
* Initializes all modules.
* @param servletContext
*/
public void init(ServletContext servletContext) {
try {
String rootDir = servletContext.getRealPath("/");
File fContextRoot = new File(rootDir);
File configurationFile = new File(fContextRoot, "/WEB-INF/" + CONFIG_FILE);
if (!configurationFile.canRead()) {
// AMO: the above hack means that we cannot deploy instances in non-Eclipse environments :(
// pls review and change appropriately - here for the time being is a "workback" solution
// inlined to try the original setting (based on a cvs diff -r1.35 -r1.36)
configurationFile = new File(new File(servletContext.getRealPath("/")), "WEB-INF/" + CONFIG_FILE);
// ...and if this does not work then we really cannot find the file :) so new semantics are preserved
if(!configurationFile.canRead()) {
throw new StartupException("cannot read file! file = "+configurationFile.getAbsolutePath());
}
} else {
log.info("parsing configuration file now: "+configurationFile.getAbsolutePath());
}
try {
configuration = new XMLConfiguration(configurationFile);
} catch (ConfigurationException ce) {
log.warn("Error loading config file: '" + CONFIG_FILE + "'.");
abort(ce);
}
upgradeManager.init();
//alter DB if necessary
upgradeManager.runAlterDbStatements();
// do pre system upgrades
upgradeManager.doPreSystemInitUpgrades();
// initialize modules
modules = new ArrayList<OLATModule>(10);
for (Iterator<Configuration> iter = configuration.getChildren("module").iterator(); iter.hasNext();) {
Configuration moduleConfig = iter.next();
String className = moduleConfig.getAttribute("classname");
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
OLATModule olatmodule = (OLATModule) cl.loadClass(className).newInstance();
log.info("*** INIT: Initializing module '" + olatmodule.getClass().getName() + "'.");
olatmodule.init(moduleConfig);
modules.add(olatmodule);
} catch (Throwable e) {
log.error("Error loading module '" + className + "'", e);
abort(e);
}
}
// initialize extensions
ExtensionManager.getInstance().init(); // will also deploy extensions
ExtensionManager.getInstance().doPostStartupTasks();
// do post system upgrades
upgradeManager.doPostSystemInitUpgrades();
} finally {
DBFactory.getInstance().commitAndCloseSession();
}
log.info("*** STARTUP COMPLETED.");
}
/**
* Called by OLATServlet upon shutdown. Shuts down all modules.
*/
public void destroy() {
// de-register modules
ExtensionManager.getInstance().doPreShutdownTasks();
// destroy any available modules
if (modules != null) {
// destroy modules in the reverse load order to solve dependencies
for (int i = modules.size()-1; i>-1; i--) {
OLATModule olatmodule = modules.get(i);
log.info("*** DESTORY: Destroying module '" + olatmodule.getClass().getName() + "'.");
try {
olatmodule.destroy();
} catch (Exception e) {
// don't propagate any exceptions
log.error("Exception destroying module '" + olatmodule.getClass().getName() + "'.", e);
}
}
}
}
/**
* On any RuntimeExceptions during init. Abort loading of application.
* Modules should throw RuntimeExceptions if they can't live with a the
* given state of configuration.
*
* @param e
*/
private void abort(Throwable e) {
if (e instanceof StartupException) {
StartupException se = (StartupException) e;
log.error("Startup Exception! ", se);
}
//DB.getInstance().rollback();
log.error("*** CRITICAL ERROR. Loading aborted.",e);
throw new RuntimeException(e);
}
/**
* Find the configuration value for the given class and name or create a
* configuration with the given default value
* @param clazz class for which this configuration is stored
* @param propertyName Name of the property
* @param defaultValue value that is used when no value exists so far
* @return String value of this property or default value when no value exists
*/
public String findOrCreateProperty(Class clazz, String propertyName, String defaultValue) {
PropertyManager pm = PropertyManager.getInstance();
Property property = pm.findProperty(null, null, null, PROPERTY_CATEGORY, createPropertyName(clazz, propertyName));
if (property == null) {
property = pm.createPropertyInstance(null, null, null, PROPERTY_CATEGORY, createPropertyName(clazz, propertyName), null, null, defaultValue, null);
pm.saveProperty(property);
}
return property.getStringValue();
}
/**
* Set an class configuration value. If a previous configuration exists, it will be
* overwritten by the new configuration value.
* @param clazz class for thich this configuration is stored
* @param propertyName Name of the property
* @param updateValue value that is used when no value exists so far
*/
public void setProperty(Class clazz, String propertyName, String updateValue) {
PropertyManager pm = PropertyManager.getInstance();
Property property = pm.findProperty(null, null, null, PROPERTY_CATEGORY, createPropertyName(clazz, propertyName));
if (property == null) {
property = pm.createPropertyInstance(null, null, null, PROPERTY_CATEGORY, createPropertyName(clazz, propertyName), null, null, updateValue, null);
pm.saveProperty(property);
} else {
property.setStringValue(updateValue);
pm.updateProperty(property);
}
}
/**
* Find the configuration value for the given class and name or create a
* configuration with the given default value
* @param clazz class for which this configuration is stored
* @param propertyName Name of the property
* @param defaultValue value that is used when no value exists so far
* @return boolean value of this property or default value when no value exists
*/
public boolean findOrCreateBooleanProperty(Class clazz, String propertyName, boolean defaultValue) {
return Boolean.valueOf(findOrCreateProperty(clazz, propertyName, Boolean.toString(defaultValue))).booleanValue();
}
/**
* Set an class configuration value. If a previous configuration exists, it will be
* overwritten by the new configuration value.
* @param clazz class for which this configuration is stored
* @param propertyName Name of the property
* @param updateValue value that is used when no value exists so far
*/
public void setBooleanProperty(Class clazz, String propertyName, boolean updateValue) {
setProperty(clazz, propertyName, Boolean.toString(updateValue));
}
/**
* Internal helper to create a property name for a class configuration property
* @param clazz
* @param configurationName
* @return String
*/
private String createPropertyName(Class clazz, String configurationName) {
return clazz.getName() + "::" + configurationName;
}
/**
* used by [spring]
* @param upgradeManager
*/
public void setUpgradeManager(UpgradeManager upgradeManager) {
this.upgradeManager = upgradeManager;
}
}