package com.excloud.platform.util.test;
import com.alibaba.fastjson.JSON;
import com.excloud.platform.storage.entity.purview.live.LiveDomainConf;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.wnameless.json.flattener.FlattenMode;
import com.github.wnameless.json.flattener.KeyTransformer;
import com.github.wnameless.json.unflattener.JsonUnflattener;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import mousio.client.retry.RetryWithExponentialBackOff;
import mousio.etcd4j.EtcdClient;
import mousio.etcd4j.EtcdUtil;
import mousio.etcd4j.requests.EtcdKeyGetRequest;
import mousio.etcd4j.responses.EtcdAuthenticationException;
import mousio.etcd4j.responses.EtcdException;
import mousio.etcd4j.responses.EtcdKeysResponse;
import mousio.etcd4j.transport.EtcdNettyClient;
import mousio.etcd4j.transport.EtcdNettyConfig;
import org.apache.commons.lang3.math.NumberUtils;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeoutException;
@Slf4j
public class ETCDUtil {
private static volatile ETCDUtil instance;
private ETCDUtil(){
}
public static ETCDUtil getInstance(){
if (null == instance){
synchronized (ETCDUtil.class){
if (null == instance){
instance = new ETCDUtil();
// instance.init();
}
}
}
return instance;
}
@Getter
private String etcdRoot = "/xxxx";
private String hosts = "http://ip:port,http://ip:port,http://ip:port";
private void init(){
try {
Properties properties = new Properties();
ClassLoader cls = getClass().getClassLoader();
URL url = cls.getResource("etcd.properties");
properties.load(url.openStream());
this.etcdRoot = properties.getProperty("etcd_root");
this.hosts = properties.getProperty("etcd_hosts");
} catch (IOException e) {
log.error("", e);
}
}
private EtcdClient etcdClient;
public EtcdClient getETCDClient(){
if (null == etcdClient){
String[] hostArray = hosts.split(",");
URI[] uris = new URI[hostArray.length];
for (int i = 0; i < hostArray.length; i++) {
uris[i] = URI.create(hostArray[i]);
}
NioEventLoopGroup evl = new NioEventLoopGroup();
EtcdNettyConfig config = new EtcdNettyConfig().setConnectTimeout(1000).setSocketChannelClass(NioSocketChannel.class).setMaxFrameSize(1024 * 1024).setEventLoopGroup(evl);
EtcdNettyClient nettyClient = new EtcdNettyClient(config, uris);
etcdClient = new EtcdClient(nettyClient);
// retry策略
etcdClient.setRetryHandler(new RetryWithExponentialBackOff(20, 4, 10000));
}
return etcdClient;
}
public void closeETCDClient() {
try{
if (null != etcdClient){
etcdClient.close();
etcdClient = null;
}
} catch (Throwable e){
log.error("", e);
}
}
public static JsonNode getAsJson(String path, EtcdClient etcdClient) throws IOException, EtcdAuthenticationException, TimeoutException, EtcdException {
EtcdKeyGetRequest etcdKeyGetRequest = etcdClient.get(path).recursive();
EtcdKeysResponse dataTree = etcdKeyGetRequest.send().get();
ObjectNode jNode = JsonNodeFactory.instance.objectNode();
iterateOverNodes(jNode, dataTree.getNode());
return dotNotationToStandardJson(jNode);
}
private static void iterateOverNodes(ObjectNode json, EtcdKeysResponse.EtcdNode node){
if (node.isDir()) {
for (EtcdKeysResponse.EtcdNode n : node.getNodes())
iterateOverNodes(json, n);
} else {
List<String> keyPath = new ArrayList<>();
for (String key : node.getKey().split("/")) {
if (!key.isEmpty())
keyPath.add(key);
}
ObjectNode jsonNodes = json;
Iterator<String> iterator = keyPath.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
key = key.replaceAll("\\.", "__DOT__");
if (jsonNodes.get(key) == null) {
if (iterator.hasNext()) {
jsonNodes = jsonNodes.putObject(key);
} else {
jsonNodes = jsonNodes.put(key, node.getValue());
}
} else {
jsonNodes = (ObjectNode) jsonNodes.get(key);
}
}
}
}
private static final ObjectMapper mapper = new ObjectMapper();
static {
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
}
private static JsonNode dotNotationToStandardJson(JsonNode etcdJson) throws IOException {
if (!etcdJson.isValueNode()) {
String unflattened = new JsonUnflattener(EtcdUtil.jsonToString(flattenJson(etcdJson, ""))).withFlattenMode(FlattenMode.MONGODB).withKeyTransformer(new KeyTransformer() {
@Override
public String transform(String s) {
return s.replaceAll("__DOT__", "\\.");
}
}).unflatten();
return mapper.readTree(unflattened);
} else {
return etcdJson;
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static ObjectNode flattenJson(JsonNode node, String currentPath) {
ObjectNode transformed = JsonNodeFactory.instance.objectNode();
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> next = fields.next();
if (next.getValue().isValueNode()) {
String path = currentPath + "." + next.getKey();
String strValue = next.getValue().asText();
if (NumberUtils.isCreatable(strValue)) {
Class numberType = numberType(strValue);
if (numberType.isAssignableFrom(Integer.class)) {
transformed.put(path.substring(1), Integer.valueOf(strValue));
} else if (numberType.isAssignableFrom(Long.class)) {
transformed.put(path.substring(1), Long.valueOf(strValue));
} else if (numberType.isAssignableFrom(Float.class)) {
transformed.put(path.substring(1), Float.valueOf(strValue));
} else if (numberType.isAssignableFrom(Double.class)) {
transformed.put(path.substring(1), Double.valueOf(strValue));
}
} else if (booleanType(strValue)) {
transformed.put(path.substring(1), Boolean.valueOf(strValue));
} else if (arrayType(strValue)) {
transformed.putArray(path.substring(1));
} else {
transformed.set(path.substring(1), next.getValue());
}
} else {
transformed.setAll(flattenJson(next.getValue(), currentPath + "." + next.getKey()));
}
}
return transformed;
}
@SuppressWarnings("rawtypes")
private static Class numberType(String value) throws NumberFormatException {
try {
Integer.valueOf(value);
return Integer.class;
} catch (NumberFormatException e) {
}
try {
Long.valueOf(value);
return Long.class;
} catch (NumberFormatException e) {
}
try {
Float.valueOf(value);
return Float.class;
} catch (NumberFormatException e) {
}
try {
Double.valueOf(value);
return Double.class;
} catch (NumberFormatException e) {
}
// no compatible number
throw new NumberFormatException();
}
private static boolean booleanType(String value) {
return ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value));
}
private static boolean arrayType(String value) {
return "[]".equalsIgnoreCase(value);
}
public static void main(String[] args) {
try {
String path = ETCDUtil.getInstance().getEtcdRoot();
String savePath = path + "/tmp/8/hudong201910251425.pptv.com";
ObjectMapper objectMapper = new ObjectMapper();
String mapJson = "{\"id\":591,\"cusId\":167,\"ptiId\":8,\"domain\":\"hudong201910251425.pptv.com\",\"mainUt\":\"\",\"backUt\":\"\",\"mainUc\":\"\",\"backUc\":\"\",\"mainUm\":\"\",\"backUm\":\"\",\"sourceConf\":1,\"sourceType\":1,\"checkUrl\":\"\",\"certId\":0,\"httpsConf\":0,\"status\":null,\"cname\":\"\",\"isDelete\":0,\"createdTime\":1571984194113,\"lastModifiedTime\":1571984194113,\"appNameLst\":[],\"pushFlow\":{\"edgePushFlowUrlLst\":[]},\"transCoding\":{\"transCodingLst\":[]},\"recording\":{\"recordingLst\":[]},\"screenShot\":{\"screenShotLst\":[]}}";
JsonNode node = objectMapper.readTree(mapJson);
// 保存
EtcdUtil.putAsJson(savePath, node, ETCDUtil.getInstance().getETCDClient());
String dir = "/tmp";
String plat = "/8";
String domain = "hudong201910251425.pptv.com";
// 查询
node = ETCDUtil.getAsJson(path + dir + plat + "/" + domain, ETCDUtil.getInstance().getETCDClient()).at(path).at(dir).at(plat).get(domain);
LiveDomainConf liveDomainConf = JSON.parseObject(EtcdUtil.jsonToString(node), LiveDomainConf.class);
System.out.println(liveDomainConf.getDomain());
// 删除
ETCDUtil.getInstance().getETCDClient().deleteDir(savePath).recursive().send().get();
node = ETCDUtil.getAsJson(path + dir + plat + "/" + domain, ETCDUtil.getInstance().getETCDClient()).at(path).at(dir).at(plat).get(domain);
liveDomainConf = JSON.parseObject(EtcdUtil.jsonToString(node), LiveDomainConf.class);
System.out.println(liveDomainConf.getDomain());
} catch (Exception e) {
log.error("", e);
} finally {
ETCDUtil.getInstance().closeETCDClient();
}
}
}