package com.virjar.dungproxy.client.ippool;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
/**
* Created by virjar on 17/1/14. <br/>
* 一个网站可能存在多个域名,但是实际上他们可以使用同一个代理规则,通过本类对其进行路由
*/
public class GroupBindRouter {
private Logger logger = LoggerFactory.getLogger(GroupBindRouter.class);
private Map<String, Optional<String>> routeData = Maps.newConcurrentMap();
private Map<String, String> routeRule = Maps.newConcurrentMap();
public GroupBindRouter() {
//buildRule("www.virjar.com:*");// 默认增加一个全部路由的策略,没有配置的
}
/**
* domain:similarDomain1,similarDomain2,similarDomain3,similarDomain4...<br/>
* 加载路由规则
*
* @param rule 规则文本
*/
public void buildRule(String rule) {
if (!StringUtils.contains(rule, ":")) {
throw new IllegalArgumentException(
"domain:similarDomain1,similarDomain2,similarDomain3,similarDomain4 \":\" is lost");
}
String[] split = rule.split(":");
String keyDomain = split[0];
String similarDomainList = split[1];
for (String similarDomain : Splitter.on(",").trimResults().split(similarDomainList)) {
if (similarDomain.equals(keyDomain)) {
continue;// 否则会打印一个无效日志,以及递归问题
}
routeRule.put(similarDomain, keyDomain);
}
}
public void buildCombinationRule(String combinationRule) {
if (StringUtils.isEmpty(combinationRule)) {
return;
}
for (String rule : Splitter.on(";").split(combinationRule)) {
buildRule(rule);
}
}
/**
* 支持通过正则的方式批量配置路由规则
*
* @param similarDomain 现在遇到的域名
* @return
*/
public String routeDomain(String similarDomain) {
Optional<String> s = routeData.get(similarDomain);// 从缓存中加载规则
if (s == null) {// 缓存没有命中,建立缓存数据
synchronized (GroupBindRouter.class) {
s = routeData.get(similarDomain);
if (s == null) {
matchSimilarDomain(similarDomain);
s = routeData.get(similarDomain);
}
}
}
if (s.isPresent()) {// 缓存有数据,且有路由规则
String routedDomain = s.get();
logger.info("域名:{} 的代理规则路由到:{}", similarDomain, routedDomain);
return routedDomain;
// return routeDomain(routedDomain);
}
return similarDomain;// 缓存有数据,但是没有找到路由规则
}
/**
* @param similarDomain 当前遇到的域名
*/
private void matchSimilarDomain(String similarDomain) {
for (String pattern : routeRule.keySet()) {
if (pattern.equals(similarDomain) || similarDomain.matches(pattern)) {
routeData.put(similarDomain, Optional.of(routeRule.get(pattern)));
return;
}
}
// 所有规则都检查过,没有找到对应的路由规则
routeData.put(similarDomain, Optional.<String> absent());
}
public int ruleSize(){
return routeRule.size();
}
}