package org.minimalj.application;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.minimalj.util.LoggingRuntimeException;

/**
 * Properties are considered in the following order:
 * 
 * <OL>
 * <LI>Properties set from outside, for example servlets init parameters</LI>
 * <LI>System properties</LI>
 * <LI>Properties loaded with the config file specified with <code>MjConfig</code></LI>
 * </OL>
 *
 */
public class Configuration {
	private static final Logger logger = Logger.getLogger(Configuration.class.getName());
	private static final Properties configFileProperties = new Properties();
	private static final Properties externalProperties = new Properties();
	
	static {
		String configFileName = System.getProperty("MjConfig");
		if (configFileName != null) {
			try (FileInputStream fis = new FileInputStream(configFileName)) {
				configFileProperties.load(fis);
			} catch (FileNotFoundException e) {
				logger.log(Level.SEVERE, "Config file not found: " + configFileName, e);
			} catch (IOException e) {
				logger.log(Level.SEVERE, "Unable to read Config file: " + configFileName, e);
			}
		}
	}
	
	public static void set(String key, String value) {
		externalProperties.setProperty(key, value);
	}
	
	public static String get(String key, String defaultValue) {
		if (externalProperties.containsKey(key)) {
			return externalProperties.getProperty(key);
		} else if (System.getProperties().containsKey(key)) {
			return System.getProperty(key);
		} else if (configFileProperties.containsKey(key)) {
			return configFileProperties.getProperty(key);
		} else {
			return defaultValue;
		}
	}
	
	public static String get(String key) {
		return get(key, null);
	}
	
	public static boolean available(String key) {
		return get(key) != null;
	}
	
	public static <T> T getClazz(String key, Class<T> clazz) {
		String className = get(key);
		try {
			@SuppressWarnings("unchecked")
			Class<? extends T> configuredClass = (Class<? extends T>) Class.forName(className);
			return configuredClass.newInstance();
		} catch (ClassNotFoundException e) {
			throw new LoggingRuntimeException(e, logger, className + " not found / " + key + " configuration failed");
		} catch (ClassCastException cce) {
			throw new LoggingRuntimeException(cce, logger, className + " is not a " + clazz.getName() + ". " + key + " configuration failed");
		} catch (Exception x) {
			throw new LoggingRuntimeException(x, logger, className + " / " + key + " configuration failed");
		}
	}
}
@@ -118,32 +118,70 @@
 io.IOException;%0A
+import java.lang.reflect.Constructor;%0A
 import java.util
@@ -2000,20 +2000,42 @@
 T%3E clazz
+, Object... parameters
 ) %7B%0A
-
 %09%09String
@@ -2186,16 +2186,46 @@
 sName);%0A
+%09%09%09if (parameters == null) %7B%0A%09
 %09%09%09retur
@@ -2257,16 +2257,339 @@
 ance();%0A
+%09%09%09%7D else %7B%0A%09%09%09%09Class%3C?%3E%5B%5D parameterTypes = new Class%5Bparameters.length%5D;%0A%09%09%09%09for (int i = 0; i%3Cparameters.length; i++) %7B%0A%09%09%09%09%09parameterTypes%5Bi%5D = parameters%5Bi%5D.getClass();%0A%09%09%09%09%7D%0A%09%09%09%09Constructor%3C? extends T%3E constructor = configuredClass.getConstructor(parameterTypes);%0A%09%09%09%09return constructor.newInstance(parameters);%0A%09%09%09%7D%0A
 %09%09%7D catc

support (not null) parameters