package com.taobao.tddl.config.impl;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import com.taobao.tddl.common.model.lifecycle.AbstractLifecycle;
import com.taobao.tddl.common.utils.GeneralUtil;
import com.taobao.tddl.config.ConfigDataHandler;
import com.taobao.tddl.config.ConfigDataListener;
import com.taobao.tddl.common.utils.logger.Logger;
import com.taobao.tddl.common.utils.logger.LoggerFactory;
public class FileConfigDataHandler extends AbstractLifecycle implements ConfigDataHandler {
private static final Logger logger = LoggerFactory.getLogger(FileConfigDataHandler.class);
private final AtomicReference<String> data = new AtomicReference<String>();
private String pattern;
private String directory;
private String dataId;
private String appName;
private List<ConfigDataListener> configDataListeners = new ArrayList<ConfigDataListener>();
private Executor executor;
public FileConfigDataHandler(String appName, Executor executor, String pattern, String directory, String dataId,
ConfigDataListener configDataListener){
super();
this.pattern = pattern;
this.directory = directory;
this.dataId = dataId;
this.appName = appName;
this.executor = executor;
if (configDataListener != null) {
this.configDataListeners.add(configDataListener);
}
if (executor == null) {
throw new IllegalArgumentException("executor is null");
}
this.executor.execute(new CheckerTask(data, pattern, directory, dataId, configDataListeners, appName));
}
// TODO shenxun :这个不知道被谁注释掉了。目前不支持文件的重载了
public static class CheckerTask implements Runnable {
private AtomicReference<String> data;
private String pattern;
private String directory;
private List<ConfigDataListener> configDataListeners;
private String appName;
private String dataId;
public CheckerTask(AtomicReference<String> data, String pattern, String directory, String dataId,
List<ConfigDataListener> configDataListeners, String appName){
super();
this.dataId = dataId;
this.data = data;
this.pattern = pattern;
this.directory = directory;
this.dataId = dataId;
this.appName = appName;
this.configDataListeners = configDataListeners;
}
@Override
public void run() {
while (true) {
try {
StringBuilder dataNew = getNewProperties(directory, dataId, pattern, appName);
if (!dataNew.toString().equalsIgnoreCase(data.get())) {// 配置变更啦
this.data.set(dataNew.toString());
for (ConfigDataListener cdl : configDataListeners) {
cdl.onDataRecieved(dataId, data.get());
}
}
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// ignore
}
} catch (IOException e) {
logger.error(e);
}
}
}
}
@Override
public String getData(long timeout, String strategy) {
try {
StringBuilder dataNew = getNewProperties(directory, dataId, pattern, appName);
this.data.set(dataNew.toString());
return data.get();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static StringBuilder getNewProperties(String directory, String key, String pattern, String appName)
throws IOException {
StringBuilder dataNew = new StringBuilder();
StringBuilder url = getUrlWithoutDiamondPattern(directory, key);
InputStream in = null;
try {
in = GeneralUtil.getInputStream(url.toString());
} catch (Exception e) {
logger.error("", e);
}
if (in == null) {
try {
in = GeneralUtil.getInputStream(getUrlWithDiamondPattern(directory, key, pattern, appName).toString());
} catch (Exception e) {
logger.error("", e);
}
}
if (in == null) {
throw new IllegalArgumentException("can't find file on " + url + " . or on "
+ getUrlWithDiamondPattern(directory, key, pattern, appName).toString());
}
BufferedReader bf = new BufferedReader(new InputStreamReader(in));
String temp;
while ((temp = bf.readLine()) != null) {
dataNew.append(temp).append(System.getProperty("line.separator"));
}
return dataNew;
}
private static StringBuilder getUrlWithoutDiamondPattern(String directory, String key) {
StringBuilder url = new StringBuilder();
if (directory != null) {
url.append(directory);
}
url.append(key);
return url;
}
private static StringBuilder getUrlWithDiamondPattern(String directory, String key, String pattern, String appName) {
StringBuilder url = new StringBuilder();
if (directory != null) {
url.append(directory);
}
if (pattern != null) {
url.append(pattern);
}
if (appName != null) {
url.append(appName);
}
url.append(key);
return url;
}
@Override
public String getNullableData(long timeout, String strategy) {
return this.getData(timeout, strategy);
}
@Override
public void addListener(ConfigDataListener configDataListener, Executor executor) {
if (!configDataListeners.contains(configDataListener)) {
configDataListeners.add(configDataListener);
}
}
@Override
public void addListeners(List<ConfigDataListener> configDataListenerList, Executor executor) {
for (ConfigDataListener l : configDataListenerList) {
this.addListener(l, executor);
}
}
}