/*
* Copyright 2011 Alibaba.com All right reserved. This software is the
* confidential and proprietary information of Alibaba.com ("Confidential
* Information"). You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement you entered
* into with Alibaba.com.
*/
package com.alibaba.dubbo.governance.web.governance.module.screen;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.governance.service.ProviderService;
import com.alibaba.dubbo.governance.service.RouteService;
import com.alibaba.dubbo.governance.web.common.module.screen.Restful;
import com.alibaba.dubbo.registry.common.domain.Access;
import com.alibaba.dubbo.registry.common.domain.Route;
import com.alibaba.dubbo.registry.common.route.RouteRule;
import com.alibaba.dubbo.registry.common.route.RouteRule.MatchPair;
import com.alibaba.dubbo.registry.common.util.Tool;
/**
* Providers. URI: /services/$service/accesses
*
* @author william.liangf
* @author ding.lid
* @author tony.chenl
*/
public class Accesses extends Restful {
@Autowired
private RouteService routeService;
@Autowired
private ProviderService providerService;
public void index(Map<String, Object> context) throws Exception {
String service = (String) context.get("service");
String address = (String) context.get("address");
address = Tool.getIP(address);
List<Route> routes;
if (service != null && service.length() > 0) {
routes = routeService.findForceRouteByService(service);
} else if (address != null && address.length() > 0) {
routes = routeService.findForceRouteByAddress(address);
} else {
routes = routeService.findAllForceRoute();
}
List<Access> accesses = new ArrayList<Access>();
if(routes == null){
context.put("accesses", accesses);
return;
}
for(Route route :routes){
Map<String, MatchPair> rule = RouteRule.parseRule(route.getMatchRule());
MatchPair pair = rule.get("consumer.host");
if(pair != null){
for(String host : pair.getMatches()){
Access access = new Access();
access.setAddress(host);
access.setService(route.getService());
access.setAllow(false);
accesses.add(access);
}
for(String host : pair.getUnmatches()){
Access access = new Access();
access.setAddress(host);
access.setService(route.getService());
access.setAllow(true);
accesses.add(access);
}
}
}
context.put("accesses", accesses);
}
public void add(Map<String, Object> context) {
List<String> serviceList = Tool.sortSimpleName(providerService.findServices());
context.put("serviceList", serviceList);
}
private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3}$");
private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$");
private static final Pattern ALL_IP_PATTERN = Pattern.compile("0{1,3}(\\.0{1,3}){3}$");
public boolean create(Map<String, Object> context) throws Exception {
String addr = (String) context.get("consumerAddress");
String services = (String) context.get("service");
Set<String> consumerAddresses = toAddr(addr);
Set<String> aimServices = toService(services);
for(String aimService : aimServices) {
boolean isFirst = false;
List<Route> routes = routeService.findForceRouteByService(aimService);
Route route = null;
if(routes==null||routes.size()==0){
isFirst = true;
route = new Route();
route.setService(aimService);
route.setForce(true);
route.setName(aimService+" blackwhitelist");
route.setFilterRule("false");
route.setEnabled(true);
}else{
route = routes.get(0);
}
Map<String, MatchPair> when = null;
MatchPair matchPair = null;
if(isFirst){
when = new HashMap<String, MatchPair>();
matchPair = new MatchPair(new HashSet<String>(),new HashSet<String>());
when.put("consumer.host", matchPair);
}else{
when = RouteRule.parseRule(route.getMatchRule());
matchPair = when.get("consumer.host");
}
for (String consumerAddress : consumerAddresses) {
if(Boolean.valueOf((String) context.get("allow"))){
matchPair.getUnmatches().add(Tool.getIP(consumerAddress));
}else{
matchPair.getMatches().add(Tool.getIP(consumerAddress));
}
}
StringBuilder sb = new StringBuilder();
RouteRule.contidionToString(sb,when);
route.setMatchRule(sb.toString());
route.setUsername(operator);
if(isFirst){
routeService.createRoute(route);
}else{
routeService.updateRoute(route);
}
}
return true;
}
private Set<String> toAddr(String addr) throws IOException{
Set<String> consumerAddresses = new HashSet<String>();
BufferedReader reader = new BufferedReader(new StringReader(addr));
while (true) {
String line = reader.readLine();
if (null == line)
break;
String[] split = line.split("[\\s,;]+");
for (String s : split) {
if (s.length() == 0)
continue;
if (!IP_PATTERN.matcher(s).matches()) {
throw new IllegalStateException("illegal IP: " + s);
}
if (LOCAL_IP_PATTERN.matcher(s).matches() || ALL_IP_PATTERN.matcher(s).matches()) {
throw new IllegalStateException("local IP or any host ip is illegal: " + s);
}
consumerAddresses.add(s);
}
}
return consumerAddresses;
}
private Set<String> toService(String services) throws IOException{
Set<String> aimServices = new HashSet<String>();
BufferedReader reader = new BufferedReader(new StringReader(services));
while (true) {
String line = reader.readLine();
if (null == line)
break;
String[] split = line.split("[\\s,;]+");
for (String s : split) {
if (s.length() == 0)
continue;
aimServices.add(s);
}
}
return aimServices;
}
/**
* 删除动作
* @throws ParseException
*/
public boolean delete(Map<String, Object> context) throws ParseException {
String accesses = (String) context.get("accesses");
String[] temp = accesses.split(" ");
Map<String,Set<String>> prepareToDeleate = new HashMap<String,Set<String>>();
for(String s : temp){
String service = s.split("=")[0];
String address = s.split("=")[1];
Set<String> addresses = prepareToDeleate.get(service);
if(addresses == null){
prepareToDeleate.put(service, new HashSet<String>());
addresses = prepareToDeleate.get(service);
}
addresses.add(address);
}
for(Entry<String, Set<String>> entry : prepareToDeleate.entrySet()){
String service = entry.getKey();
List<Route> routes = routeService.findForceRouteByService(service);
if(routes == null || routes.size() == 0){
continue;
}
for(Route blackwhitelist : routes){
MatchPair pairs = RouteRule.parseRule(blackwhitelist.getMatchRule()).get("consumer.host");
Set<String> matches = new HashSet<String>();
matches.addAll(pairs.getMatches());
Set<String> unmatches = new HashSet<String>();
unmatches.addAll(pairs.getUnmatches());
for(String pair : pairs.getMatches()){
for(String address : entry.getValue()){
if(pair.equals(address)){
matches.remove(pair);
break;
}
}
}
for(String pair : pairs.getUnmatches()){
for(String address : entry.getValue()){
if(pair.equals(address)){
unmatches.remove(pair);
break;
}
}
}
if(matches.size()==0 && unmatches.size()==0){
routeService.deleteRoute(blackwhitelist.getId());
}else{
Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
condition.put("consumer.host", new MatchPair(matches,unmatches));
StringBuilder sb = new StringBuilder();
RouteRule.contidionToString(sb,condition);
blackwhitelist.setMatchRule(sb.toString());
routeService.updateRoute(blackwhitelist);
}
}
}
return true;
}
public void show(Map<String, Object> context) {
}
public void edit(Map<String, Object> context) {
}
public String update(Map<String, Object> context) {
return null;
}
}