/*
* Copyright 1999-2101 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.governance.web.governance.module.screen;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.CollectionUtils;
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.web.common.module.screen.Restful;
import com.alibaba.dubbo.registry.common.domain.Override;
/**
* @author ding.lid
*/
public class Overrides extends Restful {
@Autowired
private OverrideService overrideService;
@Autowired
private ProviderService providerService;
@Autowired
private ConsumerService consumerService;
public void index(Map<String, Object> context) {
String service = (String) context.get("service");
String application = (String) context.get("application");
String address = (String) context.get("address");
List<Override> overrides;
if (StringUtils.isNotEmpty(service)) {
overrides = overrideService.findByService(service);
} else if(StringUtils.isNotEmpty(application)){
overrides = overrideService.findByApplication(application);
}else if(StringUtils.isNotEmpty(address)){
overrides = overrideService.findByAddress(address);
}
else{
overrides = overrideService.findAll();
}
context.put("overrides", overrides);
}
public void show(Long id, Map<String, Object> context) {
Override override = overrideService.findById(id);
Map<String, String> parameters = parseQueryString(override.getParams());
if(parameters.get(DEFAULT_MOCK_JSON_KEY) != null) {
String mock = URL.decode(parameters.get(DEFAULT_MOCK_JSON_KEY));
String[] tokens = parseMock(mock);
context.put(FORM_DEFAULT_MOCK_METHOD_FORCE, tokens[0]);
context.put(FORM_DEFAULT_MOCK_METHOD_JSON, tokens[1]);
parameters.remove(DEFAULT_MOCK_JSON_KEY);
}
Map<String, String> method2Force = new LinkedHashMap<String, String>();
Map<String, String> method2Json = new LinkedHashMap<String, String>();
for (Iterator<Map.Entry<String, String>> iterator = parameters.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String, String> e = iterator.next();
String key = e.getKey();
if(key.endsWith(MOCK_JSON_KEY_POSTFIX)) {
String m = key.substring(0, key.length() - MOCK_JSON_KEY_POSTFIX.length());
parseMock(m, e.getValue(), method2Force, method2Json);
iterator.remove();
}
}
context.put("methodForces", method2Force);
context.put("methodJsons", method2Json);
context.put("parameters", parameters);
context.put("override", override);
}
public void add(Map<String, Object> context){
List<String> serviceList = new ArrayList<String>();
List<String> applicationList = new ArrayList<String>();
String service = (String) context.get("service");
String application = (String) context.get("application");
if(StringUtils.isNotEmpty(application)){
serviceList.addAll(providerService.findServicesByApplication(application));
serviceList.addAll(consumerService.findServicesByApplication(application));
context.put("serviceList", serviceList);
}else if(StringUtils.isNotEmpty(service)){
applicationList.addAll(providerService.findApplicationsByServiceName(service));
applicationList.addAll(consumerService.findApplicationsByServiceName(service));
context.put("applicationList", applicationList);
}else{
serviceList.addAll(providerService.findServices());
serviceList.addAll(consumerService.findServices());
providerService.findServicesByApplication(application);
consumerService.findServicesByApplication(application);
}
context.put("serviceList", serviceList);
if (StringUtils.isNotEmpty(service) && !service.contains("*")) {
context.put("methods", CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(service))));
}
}
static final Pattern AND = Pattern.compile("\\&");
static final Pattern EQUAL = Pattern.compile("([^=\\s]*)\\s*=\\s*(\\S*)");
static Map<String, String> parseQueryString(String query) {
HashMap<String, String> ret = new HashMap<String, String>();
if(query == null || (query = query.trim()).length() == 0) return ret;
String[] kvs = AND.split(query);
for(String kv : kvs) {
Matcher matcher = EQUAL.matcher(kv);
if(!matcher.matches()) continue;
String key = matcher.group(1);
String value = matcher.group(2);
ret.put(key, value);
}
return ret;
}
public void edit(Long id, Map<String, Object> context) {
Override override = overrideService.findById(id);
Map<String, String> parameters = parseQueryString(override.getParams());
if(parameters.get(DEFAULT_MOCK_JSON_KEY)!=null){
String mock = URL.decode(parameters.get(DEFAULT_MOCK_JSON_KEY));
String[] tokens = parseMock(mock);
context.put(FORM_DEFAULT_MOCK_METHOD_FORCE, tokens[0]);
context.put(FORM_DEFAULT_MOCK_METHOD_JSON, tokens[1]);
parameters.remove(DEFAULT_MOCK_JSON_KEY);
}
Map<String, String> method2Force = new LinkedHashMap<String, String>();
Map<String, String> method2Json = new LinkedHashMap<String, String>();
List<String> methods = CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(override.getService())));
if(methods != null && methods.isEmpty()) {
for(String m : methods) {
parseMock(m, parameters.get(m + MOCK_JSON_KEY_POSTFIX), method2Force, method2Json);
parameters.remove(m + MOCK_JSON_KEY_POSTFIX);
}
}
for (Iterator<Map.Entry<String, String>> iterator = parameters.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String, String> e = iterator.next();
String key = e.getKey();
if(key.endsWith(MOCK_JSON_KEY_POSTFIX)) {
String m = key.substring(0, key.length() - MOCK_JSON_KEY_POSTFIX.length());
parseMock(m, e.getValue(), method2Force, method2Json);
iterator.remove();
}
}
context.put("methods", methods);
context.put("methodForces", method2Force);
context.put("methodJsons", method2Json);
context.put("parameters", parameters);
context.put("override", override);
}
private void parseMock(String m, String mock, Map<String, String> method2Force, Map<String, String> method2Json) {
String[] tokens = parseMock(mock);
method2Force.put(m, tokens[0]);
method2Json.put(m, tokens[1]);
}
private String[] parseMock(String mock) {
mock = URL.decode(mock);
String force;
if (mock.startsWith("force:")) {
force = "force";
mock = mock.substring("force:".length());
} else if (mock.startsWith("fail:")) {
force = "fail";
mock = mock.substring("fail:".length());
} else {
force = "fail";
}
String[] tokens = new String[2];
tokens[0] = force;
tokens[1] = mock;
return tokens;
}
static final String DEFAULT_MOCK_JSON_KEY = "mock";
static final String MOCK_JSON_KEY_POSTFIX = ".mock";
// FORM KEY
static final String FORM_OVERRIDE_KEY = "overrideKey";
static final String FORM_OVERRIDE_VALUE = "overrideValue";
static final String FORM_DEFAULT_MOCK_METHOD_FORCE = "mockDefaultMethodForce";
static final String FORM_DEFAULT_MOCK_METHOD_JSON = "mockDefaultMethodJson";
static final String FORM_ORIGINAL_METHOD_FORCE_PREFIX = "mockMethodForce.";
static final String FORM_ORIGINAL_METHOD_PREFIX = "mockMethod.";
static final String FORM_DYNAMIC_METHOD_NAME_PREFIX = "mockMethodName";
static final String FORM_DYNAMIC_METHOD_FORCE_PREFIX = "mockMethodForce";
static final String FORM_DYNAMIC_METHOD_JSON_PREFIX = "mockMethodJson";
boolean catchParams(Override override, Map<String, Object> context) {
String service = (String) context.get("service");
if(service == null || service.trim().length() == 0) {
context.put("message", getMessage("service is blank!"));
return false;
}
if (!super.currentUser.hasServicePrivilege(service)) {
context.put("message", getMessage("HaveNoServicePrivilege", service));
return false;
}
String defaultMockMethodForce = (String) context.get(FORM_DEFAULT_MOCK_METHOD_FORCE);
String defaultMockMethodJson = (String) context.get(FORM_DEFAULT_MOCK_METHOD_JSON);
Map<String, String> override2Value = new HashMap<String, String>();
Map<String, String> method2Json = new HashMap<String, String>();
for(Map.Entry<String, Object> param : context.entrySet()) {
String key = param.getKey().trim();
if(! (param.getValue() instanceof String) ) continue;
String value = (String) param.getValue();
if(key.startsWith(FORM_OVERRIDE_KEY) && value != null && value.trim().length() > 0) {
String index = key.substring(FORM_OVERRIDE_KEY.length());
String overrideValue = (String) context.get(FORM_OVERRIDE_VALUE + index);
if(overrideValue != null && overrideValue.trim().length() > 0) {
override2Value.put(value.trim(), overrideValue.trim());
}
}
if(key.startsWith(FORM_ORIGINAL_METHOD_PREFIX) && value != null && value.trim().length() > 0) {
String method = key.substring(FORM_ORIGINAL_METHOD_PREFIX.length());
String force = (String) context.get(FORM_ORIGINAL_METHOD_FORCE_PREFIX + method);
method2Json.put(method, force + ":" + value.trim());
}
if(key.startsWith(FORM_DYNAMIC_METHOD_NAME_PREFIX) && value != null && value.trim().length() > 0) {
String index = key.substring(FORM_DYNAMIC_METHOD_NAME_PREFIX.length());
String force = (String) context.get(FORM_DYNAMIC_METHOD_FORCE_PREFIX + index);
String json = (String) context.get(FORM_DYNAMIC_METHOD_JSON_PREFIX + index);
if(json != null && json.trim().length() > 0) {
method2Json.put(value.trim(), force + ":" + json.trim());
}
}
}
StringBuilder paramters = new StringBuilder();
boolean isFirst = true;
if(defaultMockMethodJson != null && defaultMockMethodJson.trim().length() > 0) {
paramters.append("mock=").append(URL.encode(defaultMockMethodForce + ":" + defaultMockMethodJson.trim()));
isFirst = false;
}
for(Map.Entry<String, String> e : method2Json.entrySet()) {
if(isFirst) isFirst = false;
else paramters.append("&");
paramters.append(e.getKey()).append(MOCK_JSON_KEY_POSTFIX).append("=").append(URL.encode(e.getValue()));
}
for(Map.Entry<String, String> e : override2Value.entrySet()) {
if(isFirst) isFirst = false;
else paramters.append("&");
paramters.append(e.getKey()).append("=").append(URL.encode(e.getValue()));
}
String p = paramters.toString();
if(p.trim().length() == 0) {
context.put("message", getMessage("Please enter Parameters!"));
return false;
}
override.setParams(p);
return true;
}
public boolean create(Override override, Map<String, Object> context) {
if(!catchParams(override, context)) return false;
overrideService.saveOverride(override);
return true;
}
public boolean update(Override override,Map<String, Object> context) {
Override o = overrideService.findById(override.getId());
override.setService(o.getService());
override.setAddress(o.getAddress());
override.setApplication(o.getApplication());
if(!catchParams(override, context)) return false;
overrideService.updateOverride(override);
return true;
}
public boolean delete(Long[] ids, Map<String, Object> context) {
for (Long id : ids) {
overrideService.deleteOverride(id);
}
return true;
}
public boolean enable(Long[] ids, Map<String, Object> context) {
for(Long id : ids){
Override override = overrideService.findById(id);
if(override == null){
context.put("message", getMessage("NoSuchOperationData", id));
return false;
}
else{
if (!super.currentUser.hasServicePrivilege(override.getService())) {
context.put("message", getMessage("HaveNoServicePrivilege", override.getService()));
return false;
}
}
}
for (Long id : ids) {
overrideService.enableOverride(id);
}
return true;
}
public boolean disable(Long[] ids, Map<String, Object> context) {
for(Long id : ids){
Override override = overrideService.findById(id);
if(override == null){
context.put("message", getMessage("NoSuchOperationData", id));
return false;
}
else{
if (!super.currentUser.hasServicePrivilege(override.getService())) {
context.put("message", getMessage("HaveNoServicePrivilege", override.getService()));
return false;
}
}
}
for (Long id : ids) {
overrideService.disableOverride(id);
}
return true;
}
}