package org.nutz.conf; import java.io.File; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.nutz.el.opt.custom.CustomMake; import org.nutz.json.Json; import org.nutz.lang.Files; import org.nutz.lang.util.NutType; import org.nutz.log.Log; import org.nutz.log.Logs; import org.nutz.mapl.Mapl; import org.nutz.resource.NutResource; import org.nutz.resource.Scans; import org.nutz.resource.impl.FileResource; /** * 配置加载器<br> * 一个通用的配置加载器, 全局的加载配置文件, 这样, 在所有地方都可以使用这些配置信息了. 规则:<<br>* <ul> * <li>配置文件使用JSON格式. * <li>JSON第一层为配置项键值对, KEY 为配置项名称, 值为配置信息. * <li>使用文件数组, 或者文件目录的形式, 可以加载多个配置文件 * <li>可以使用 include 关键字来引用其它配置文件, 值以数组形式. * <li>多配置文件的情况下后加载的配置会覆盖之前加载的配置,include引用的配置会覆盖引用前的配置. * <li>与JSON 相同, 配置项的值你可以转换成任意你想要的类型. 包括泛型, 可以使用 {@link NutType} * </ul> * * @author juqkai(juqkai@gmail.com) * */ public class NutConf { private static final Log log = Logs.get(); private static final String DEFAULT_CONFIG = "org/nutz/conf/NutzDefaultConfig.js"; // 所有的配置信息 private Map<String, Object> map = new HashMap<String, Object>(); // zozoh 单利的话,没必要用这个吧 ... // private static final Lock lock = new ReentrantLock(); private volatile static NutConf conf; private static NutConf me() { if (null == conf) { synchronized (NutConf.class) { if (null == conf) conf = new NutConf(); } } return conf; } private NutConf() { // 加载框架自己的一些配置 loadResource(DEFAULT_CONFIG); } public static void load(String... paths) { me().loadResource(paths); CustomMake.init(); } /** * 加载资源 */ @SuppressWarnings({"unchecked", "rawtypes"}) private void loadResource(String... paths) { for (String path : paths) { List<NutResource> resources; if (path.endsWith(".js")) { File f = Files.findFile(path); resources = new ArrayList<NutResource>(); resources.add(new FileResource(f)); } else { resources = Scans.me().scan(path, "\\.js$"); } for (NutResource nr : resources) { try { Object obj = Json.fromJson(nr.getReader()); if (obj instanceof Map) { Map m = (Map) obj; map = (Map) Mapl.merge(map, m); for (Object key : m.keySet()) { if (key.equals("include")) { map.remove("include"); List<String> include = (List) m.get("include"); loadResource(include.toArray(new String[include.size()])); } } } } catch (Throwable e) { if (log.isWarnEnabled()) log.warn("Fail to load config?! for " + nr.getName(), e); } } } } /** * 读取一个配置项, 并转换成相应的类型. */ public static Object get(String key, Type type) { return me().getItem(key, type); } /** * 读取配置项, 返回Map, List或者 Object. 具体返回什么, 请参考 JSON 规则 */ public static Object get(String key) { return me().getItem(key, null); } /** * 读取一个配置项, 并转换成相应的类型. * * @param key * @param type * @return */ private Object getItem(String key, Type type) { if (null == map) { return null; } if (null == type) { return map.get(key); } return Mapl.maplistToObj(map.get(key), type); } /** * 清理所有配置信息 */ public static void clear() { conf = null; } }