/** * Dianping.com Inc. * Copyright (c) 2003-2013 All Rights Reserved. */ package com.dianping.pigeon.config; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.lang.StringUtils; import com.dianping.pigeon.log.Logger; import com.dianping.pigeon.log.LoggerLoader; import com.dianping.pigeon.util.AppUtils; import com.dianping.pigeon.util.NetUtils; /** * @author xiangwu * @Sep 22, 2013 * */ public abstract class AbstractConfigManager implements ConfigManager { private static Logger logger = LoggerLoader.getLogger(AbstractConfigManager.class); public static final String KEY_GROUP = "swimlane"; public static final String KEY_LOCAL_IP = "host.ip"; public static final String KEY_APP_NAME = "app.name"; public static final String KEY_ENV = "environment"; public static final String DEFAULT_GROUP = ""; public static final int DEFAULT_WEIGHT = 1; private static final Object NULL = new Object(); private static List<ConfigChangeListener> configChangeListeners = new ArrayList<ConfigChangeListener>(); protected Map<String, Object> localCache = new ConcurrentHashMap<String, Object>(); public abstract String doGetProperty(String key) throws Exception; public abstract String doGetLocalProperty(String key) throws Exception; public abstract String doGetEnv() throws Exception; public abstract String doGetLocalIp() throws Exception; public abstract String doGetGroup() throws Exception; public abstract void doSetStringValue(String key, String value) throws Exception; public abstract void doDeleteKey(String key) throws Exception; public AbstractConfigManager() { Map<String, Object> properties = LocalConfigLoader.load(this); localCache.putAll(properties); } public boolean getBooleanValue(String key, boolean defaultValue) { Boolean value = getBooleanValue(key); return value != null ? value : defaultValue; } public Boolean getBooleanValue(String key) { return getProperty(key, Boolean.class); } public long getLongValue(String key, long defaultValue) { Long value = getLongValue(key); return value != null ? value : defaultValue; } public Long getLongValue(String key) { return getProperty(key, Long.class); } public int getIntValue(String key, int defaultValue) { Integer value = getIntValue(key); return value != null ? value : defaultValue; } public Integer getIntValue(String key) { return getProperty(key, Integer.class); } public float getFloatValue(String key, float defaultValue) { Float value = getFloatValue(key); return value != null ? value : defaultValue; } public Float getFloatValue(String key) { return getProperty(key, Float.class); } public double getDoubleValue(String key, double defaultValue) { Double value = getDoubleValue(key); return value != null ? value : defaultValue; } public Double getDoubleValue(String key) { return getProperty(key, Double.class); } @Override public String getStringValue(String key, String defaultValue) { String value = getStringValue(key); return value != null ? value : defaultValue; } public String getLocalStringValue(String key) { return getPropertyFromLocal(key, String.class); } private <T> T getPropertyFromLocal(String key, Class<T> type) { String strValue = null; if (localCache.containsKey(key)) { Object value = localCache.get(key); if (value == NULL) { return null; } if (value.getClass() == type) { return (T) value; } else { strValue = value + ""; } } if (strValue == null) { strValue = System.getProperty(key); } if (strValue == null) { strValue = System.getenv(key); } if (strValue == null) { try { strValue = doGetLocalProperty(key); } catch (Throwable e) { logger.error("error while reading local config[" + key + "]:" + e.getMessage()); } } Object value = null; if (strValue != null) { if (String.class == type) { value = strValue; } else if (!StringUtils.isBlank(strValue)) { if (Integer.class == type) { value = Integer.valueOf(strValue); } else if (Long.class == type) { value = Long.valueOf(strValue); } else if (Float.class == type) { value = Float.valueOf(strValue); } else if (Boolean.class == type) { value = Boolean.valueOf(strValue); } } } setLocalValue(key, value); return (T) value; } @Override public String getStringValue(String key) { return getProperty(key, String.class); } private <T> T getProperty(String key, Class<T> type) { String strValue = null; if (localCache.containsKey(key)) { Object value = localCache.get(key); if (value == NULL) { return null; } if (value.getClass() == type) { return (T) value; } else { strValue = value + ""; } } if (strValue == null) { strValue = System.getProperty(key); } if (strValue == null) { strValue = System.getenv(key); } if (strValue == null) { try { strValue = doGetLocalProperty(key); } catch (Throwable e) { logger.error("error while reading local config[" + key + "]:" + e.getMessage()); } } if (strValue == null && StringUtils.isNotBlank(getAppName())) { if (!key.startsWith(getAppName())) { try { strValue = doGetProperty(getAppName() + "." + key); if (strValue != null && logger.isInfoEnabled()) { logger.info("read from config server with key[" + getAppName() + "." + key + "]:" + strValue); } } catch (Throwable e) { logger.error("error while reading property[" + getAppName() + "." + key + "]:" + e.getMessage()); } } } if (strValue == null) { try { strValue = doGetProperty(key); if (strValue != null && logger.isInfoEnabled()) { logger.info("read from config server with key[" + key + "]:" + strValue); } } catch (Throwable e) { logger.error("error while reading property[" + key + "]:" + e.getMessage()); } } Object value = null; if (strValue != null) { if (String.class == type) { value = strValue; } else if (!StringUtils.isBlank(strValue)) { if (Integer.class == type) { value = Integer.valueOf(strValue); } else if (Long.class == type) { value = Long.valueOf(strValue); } else if (Float.class == type) { value = Float.valueOf(strValue); } else if (Boolean.class == type) { value = Boolean.valueOf(strValue); } else if (Double.class == type) { value = Double.valueOf(strValue); } } } setLocalValue(key, value); return (T) value; } public int getLocalIntValue(String key, int defaultValue) { String strValue = getLocalProperty(key); if (!StringUtils.isBlank(strValue)) { return Integer.valueOf(strValue); } return defaultValue; } public long getLocalLongValue(String key, long defaultValue) { String strValue = getLocalProperty(key); if (!StringUtils.isBlank(strValue)) { return Long.valueOf(strValue); } return defaultValue; } public boolean getLocalBooleanValue(String key, boolean defaultValue) { String strValue = getLocalProperty(key); if (!StringUtils.isBlank(strValue)) { return Boolean.valueOf(strValue); } return defaultValue; } public String getLocalStringValue(String key, String defaultValue) { String value = getLocalProperty(key); return value != null ? value : defaultValue; } public String getLocalProperty(String key) { if (localCache.containsKey(key)) { Object v = localCache.get(key); if (v == NULL) { return ""; } else { return "" + v; } } try { String value = doGetLocalProperty(key); setLocalValue(key, value); if (value != null) { if (logger.isInfoEnabled()) { logger.info("read from config server with key[" + key + "]:" + value); } return value; } } catch (Throwable e) { logger.error("error while reading property[" + key + "]:" + e.getMessage()); } return null; } @Override public void init(Properties properties) { for (Iterator ir = properties.keySet().iterator(); ir.hasNext();) { String key = ir.next().toString(); String value = properties.getProperty(key); setLocalValue(key, value); } } public String getEnv() { String value = getLocalProperty(KEY_ENV); if (value == null) { try { value = doGetEnv(); } catch (Throwable e) { logger.error("error while reading env:" + e.getMessage()); } if (value != null) { setLocalValue(KEY_ENV, value); logger.info("environment:" + value); } } return value; } public String getAppName() { String value = getLocalProperty(KEY_APP_NAME); if (value == null) { try { value = AppUtils.getAppName(); } catch (Throwable e) { logger.error("error while reading app name:" + e.getMessage()); } if (value != null) { setLocalValue(KEY_APP_NAME, value); } if (StringUtils.isNotBlank(value)) { logger.info("app name:" + value); } } return value; } public String getLocalIp() { String value = null; try { value = doGetLocalIp(); } catch (Throwable e) { logger.error("error while reading local ip:" + e.getMessage()); } if (StringUtils.isBlank(value)) { value = NetUtils.getFirstLocalIp(); } if (value != null) { setLocalValue(KEY_LOCAL_IP, value); } return value; } public String getGroup() { String value = null; try { value = doGetGroup(); } catch (Throwable e) { logger.error("error while reading group:" + e.getMessage()); } if (value == null) { return DEFAULT_GROUP; } return value; } public void registerConfigChangeListener(ConfigChangeListener configChangeListener) { configChangeListeners.add(configChangeListener); try { doRegisterConfigChangeListener(configChangeListener); } catch (Exception e) { logger.error("", e); } } public abstract void doRegisterConfigChangeListener(ConfigChangeListener configChangeListener) throws Exception; @Override public void setStringValue(String key, String value) { try { doSetStringValue(key, value); setLocalStringValue(key, value); } catch (Throwable e) { throw new ConfigException("error while setting key:" + key, e); } } @Override public void deleteKey(String key) { try { doDeleteKey(key); localCache.remove(key); } catch (Throwable e) { throw new ConfigException("error while deleting key:" + key, e); } } @Override public void setLocalStringValue(String key, String value) { setLocalValue(key, value); } public void setLocalValue(String key, Object value) { if (key != null) { if (value != null) { localCache.put(key, value); } else { localCache.put(key, NULL); } } } public Map<String, Object> getLocalConfig() { return localCache; } public List<ConfigChangeListener> getConfigChangeListeners() { return configChangeListeners; } public void onConfigUpdated(String key, String value) { List<ConfigChangeListener> listeners = getConfigChangeListeners(); for (ConfigChangeListener listener : listeners) { listener.onKeyUpdated(key, value); } if (localCache.containsKey(key)) { setLocalValue(key, value); } } public void onConfigAdded(String key, String value) { List<ConfigChangeListener> listeners = getConfigChangeListeners(); for (ConfigChangeListener listener : listeners) { listener.onKeyAdded(key, value); } } public void onConfigRemoved(String key, String value) { List<ConfigChangeListener> listeners = getConfigChangeListeners(); for (ConfigChangeListener listener : listeners) { listener.onKeyRemoved(key); } } }