/*
* 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.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.governance.service.ConsumerService;
import com.alibaba.dubbo.governance.service.OverrideService;
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.Consumer;
import com.alibaba.dubbo.registry.common.domain.Override;
import com.alibaba.dubbo.registry.common.domain.Provider;
import com.alibaba.dubbo.registry.common.domain.Route;
import com.alibaba.dubbo.registry.common.route.OverrideUtils;
import com.alibaba.dubbo.registry.common.route.RouteRule;
import com.alibaba.dubbo.registry.common.route.RouteRule.MatchPair;
import com.alibaba.dubbo.registry.common.route.RouteUtils;
import com.alibaba.dubbo.registry.common.util.Tool;
/**
* Consumers. URI: /services/$service/consumers
*
* @author william.liangf
*/
public class Consumers extends Restful {
@Autowired
private ProviderService providerService;
@Autowired
private ConsumerService consumerService;
@Autowired
private OverrideService overrideService;
@Autowired
private RouteService routeService;
public void index(Map<String, Object> context) throws Exception {
String service = (String) context.get("service");
String application = (String) context.get("application");
String address = (String) context.get("address");
List<Consumer> consumers;
List<Override> overrides;
List<Provider> providers = null;
List<Route> routes = null;
// service
if (service != null && service.length() > 0) {
consumers = consumerService.findByService(service);
overrides = overrideService.findByService(service);
providers = providerService.findByService(service);
routes = routeService.findByService(service);
}
// address
else if (address != null && address.length() > 0) {
consumers = consumerService.findByAddress(address);
overrides = overrideService.findByAddress(Tool.getIP(address));
}
// application
else if (application != null && application.length() > 0) {
consumers = consumerService.findByApplication(application);
overrides = overrideService.findByApplication(application);
}
// all
else {
consumers = consumerService.findAll();
overrides = overrideService.findAll();
}
if (consumers != null && consumers.size() > 0) {
for (Consumer consumer : consumers) {
if (service == null || service.length() == 0) {
providers = providerService.findByService(consumer.getService());
routes = routeService.findByService(consumer.getService());
}
List<Route> routed = new ArrayList<Route>();
consumer.setProviders(RouteUtils.route(consumer.getService(), consumer.getAddress(), consumer.getParameters(), providers, overrides, routes, null, routed));
consumer.setRoutes(routed);
OverrideUtils.setConsumerOverrides(consumer, overrides);
}
}
context.put("consumers", consumers);
}
public void show(Long id, Map<String, Object> context) {
Consumer consumer = consumerService.findConsumer(id);
List<Provider> providers = providerService.findByService(consumer.getService());
List<Route> routes = routeService.findByService(consumer.getService());
List<Override> overrides = overrideService.findByService(consumer.getService());
List<Route> routed = new ArrayList<Route>();
consumer.setProviders(RouteUtils.route(consumer.getService(), consumer.getAddress(), consumer.getParameters(), providers, overrides, routes, null, routed));
consumer.setRoutes(routed);
OverrideUtils.setConsumerOverrides(consumer, overrides);
context.put("consumer", consumer);
context.put("providers", consumer.getProviders());
context.put("routes", consumer.getRoutes());
context.put("overrides", consumer.getOverrides());
}
public void edit(Long id, Map<String, Object> context) {
show(id, context);
}
public boolean update(Consumer newConsumer, Map<String, Object> context) {
Long id = newConsumer.getId();
String parameters = newConsumer.getParameters();
Consumer consumer = consumerService.findConsumer(id);
if (consumer == null) {
context.put("message", getMessage("NoSuchOperationData", id));
return false;
}
String service = consumer.getService();
if (!super.currentUser.hasServicePrivilege(service)) {
context.put("message", getMessage("HaveNoServicePrivilege", service));
return false;
}
Map<String, String> oldMap = StringUtils.parseQueryString(consumer.getParameters());
Map<String, String> newMap = StringUtils.parseQueryString(parameters);
for (Map.Entry<String, String> entry : oldMap.entrySet()) {
if (entry.getValue().equals(newMap.get(entry.getKey()))) {
newMap.remove(entry.getKey());
}
}
String address = consumer.getAddress();
List<Override> overrides = overrideService.findByServiceAndAddress(consumer.getService(), consumer.getAddress());
OverrideUtils.setConsumerOverrides(consumer, overrides);
Override override = consumer.getOverride();
if (override != null) {
if (newMap.size() > 0) {
override.setParams(StringUtils.toQueryString(newMap));
override.setEnabled(true);
override.setOperator(operator);
override.setOperatorAddress(operatorAddress);
overrideService.updateOverride(override);
} else {
overrideService.deleteOverride(override.getId());
}
} else {
override = new Override();
override.setService(service);
override.setAddress(address);
override.setParams(StringUtils.toQueryString(newMap));
override.setEnabled(true);
override.setOperator(operator);
override.setOperatorAddress(operatorAddress);
overrideService.saveOverride(override);
}
return true;
}
public void routed(Long id, Map<String, Object> context) {
show(id, context);
}
public void notified(Long id, Map<String, Object> context) {
show(id, context);
}
public void overrided(Long id, Map<String, Object> context) {
show(id, context);
}
public boolean shield(Long[] ids, Map<String, Object> context) throws Exception {
return mock(ids, context, "force:return null");
}
public boolean tolerant(Long[] ids, Map<String, Object> context) throws Exception {
return mock(ids, context, "fail:return null");
}
public boolean recover(Long[] ids, Map<String, Object> context) throws Exception {
return mock(ids, context, "");
}
private boolean mock(Long[] ids, Map<String, Object> context, String mock) throws Exception {
if (ids == null || ids.length == 0){
context.put("message", getMessage("NoSuchOperationData"));
return false;
}
List<Consumer> consumers = new ArrayList<Consumer>();
for (Long id : ids) {
Consumer c = consumerService.findConsumer(id);
if(c != null){
consumers.add(c);
if (!super.currentUser.hasServicePrivilege(c.getService())) {
context.put("message", getMessage("HaveNoServicePrivilege", c.getService()));
return false;
}
}
}
for(Consumer consumer : consumers) {
String service = consumer.getService();
String address = Tool.getIP(consumer.getAddress());
List<Override> overrides = overrideService.findByServiceAndAddress(service, address);
if (overrides != null && overrides.size() > 0) {
for (Override override: overrides) {
Map<String, String> map = StringUtils.parseQueryString(override.getParams());
if (mock == null || mock.length() == 0) {
map.remove("mock");
} else {
map.put("mock", URL.encode(mock));
}
if (map.size() > 0) {
override.setParams(StringUtils.toQueryString(map));
override.setEnabled(true);
override.setOperator(operator);
override.setOperatorAddress(operatorAddress);
overrideService.updateOverride(override);
} else {
overrideService.deleteOverride(override.getId());
}
}
} else if (mock != null && mock.length() > 0) {
Override override = new Override();
override.setService(service);
override.setAddress(address);
override.setParams("mock=" + URL.encode(mock));
override.setEnabled(true);
override.setOperator(operator);
override.setOperatorAddress(operatorAddress);
overrideService.saveOverride(override);
}
}
return true;
}
public boolean allshield(Map<String, Object> context) throws Exception {
return allmock(context, "force:return null");
}
public boolean alltolerant(Map<String, Object> context) throws Exception {
return allmock(context, "fail:return null");
}
public boolean allrecover(Map<String, Object> context) throws Exception {
return allmock(context, "");
}
private boolean allmock(Map<String, Object> context, String mock) throws Exception {
String service = (String) context.get("service");
if (service == null || service.length() == 0) {
context.put("message", getMessage("NoSuchOperationData"));
return false;
}
if (! super.currentUser.hasServicePrivilege(service)) {
context.put("message", getMessage("HaveNoServicePrivilege", service));
return false;
}
List<Override> overrides = overrideService.findByService(service);
Override allOverride = null;
if (overrides != null && overrides.size() > 0) {
for (Override override: overrides) {
if (override.isDefault()) {
allOverride = override;
break;
}
}
}
if (allOverride != null) {
Map<String, String> map = StringUtils.parseQueryString(allOverride.getParams());
if (mock == null || mock.length() == 0) {
map.remove("mock");
} else {
map.put("mock", URL.encode(mock));
}
if (map.size() > 0) {
allOverride.setParams(StringUtils.toQueryString(map));
allOverride.setEnabled(true);
allOverride.setOperator(operator);
allOverride.setOperatorAddress(operatorAddress);
overrideService.updateOverride(allOverride);
} else {
overrideService.deleteOverride(allOverride.getId());
}
} else if (mock != null && mock.length() > 0) {
Override override = new Override();
override.setService(service);
override.setParams("mock=" + URL.encode(mock));
override.setEnabled(true);
override.setOperator(operator);
override.setOperatorAddress(operatorAddress);
overrideService.saveOverride(override);
}
return true;
}
public boolean allow(Long[] ids, Map<String, Object> context) throws Exception {
return access(ids, context, true, false);
}
public boolean forbid(Long[] ids, Map<String, Object> context) throws Exception {
return access(ids, context, false, false);
}
public boolean onlyallow(Long[] ids, Map<String, Object> context) throws Exception {
return access(ids, context, true, true);
}
public boolean onlyforbid(Long[] ids, Map<String, Object> context) throws Exception {
return access(ids, context, false, true);
}
private boolean access(Long[] ids, Map<String, Object> context, boolean allow, boolean only) throws Exception {
if (ids == null || ids.length == 0){
context.put("message", getMessage("NoSuchOperationData"));
return false;
}
List<Consumer> consumers = new ArrayList<Consumer>();
for (Long id : ids) {
Consumer c = consumerService.findConsumer(id);
if(c != null){
consumers.add(c);
if (!super.currentUser.hasServicePrivilege(c.getService())) {
context.put("message", getMessage("HaveNoServicePrivilege", c.getService()));
return false;
}
}
}
Map<String, Set<String>> serviceAddresses = new HashMap<String, Set<String>>();
for(Consumer consumer : consumers) {
String service = consumer.getService();
String address = Tool.getIP(consumer.getAddress());
Set<String> addresses = serviceAddresses.get(service);
if (addresses == null) {
addresses = new HashSet<String>();
serviceAddresses.put(service, addresses);
}
addresses.add(address);
}
for(Map.Entry<String, Set<String>> entry : serviceAddresses.entrySet()) {
String service = entry.getKey();
boolean isFirst = false;
List<Route> routes = routeService.findForceRouteByService(service);
Route route = null;
if(routes == null || routes.size() == 0){
isFirst = true;
route = new Route();
route.setService(service);
route.setForce(true);
route.setName(service+" 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");
}
if (only) {
matchPair.getUnmatches().clear();
matchPair.getMatches().clear();
if (allow) {
matchPair.getUnmatches().addAll(entry.getValue());
} else {
matchPair.getMatches().addAll(entry.getValue());
}
} else {
for (String consumerAddress : entry.getValue()) {
if(matchPair.getUnmatches().size() > 0) { // 白名单优先
matchPair.getMatches().remove(consumerAddress); // 去掉黑名单中相同数据
if (allow) { // 如果允许访问
matchPair.getUnmatches().add(consumerAddress); // 加入白名单
} else { // 如果禁止访问
matchPair.getUnmatches().remove(consumerAddress); // 从白名单中去除
}
} else { // 黑名单生效
if (allow) { // 如果允许访问
matchPair.getMatches().remove(consumerAddress); // 从黑名单中去除
} else { // 如果禁止访问
matchPair.getMatches().add(consumerAddress); // 加入黑名单
}
}
}
}
StringBuilder sb = new StringBuilder();
RouteRule.contidionToString(sb,when);
route.setMatchRule(sb.toString());
route.setUsername(operator);
if (matchPair.getMatches().size() > 0 || matchPair.getUnmatches().size() > 0) {
if(isFirst) {
routeService.createRoute(route);
} else {
routeService.updateRoute(route);
}
} else if (! isFirst) {
routeService.deleteRoute(route.getId());
}
}
return true;
}
}