blob: b692243e468dd12e74a7235e42854493be2b6056 [file] [log] [blame]
/*
* Copyright 2019 WeBank
*
* 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.webank.wedatasphere.linkis.configuration.service
import java.lang.Long
import java.util
import com.webank.wedatasphere.linkis.common.utils.{Logging, Utils}
import com.webank.wedatasphere.linkis.configuration.dao.ConfigMapper
import com.webank.wedatasphere.linkis.configuration.entity.{ConfigKey, _}
import com.webank.wedatasphere.linkis.configuration.exception.ConfigurationException
import com.webank.wedatasphere.linkis.configuration.util.Constants
import com.webank.wedatasphere.linkis.configuration.validate.ValidatorManager
import com.webank.wedatasphere.linkis.protocol.config.ResponseQueryConfig
import com.webank.wedatasphere.linkis.server.BDPJettyServerHelper
import org.apache.commons.lang.StringUtils
import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
/**
* Created by allenlliu on 2019/4/8.
*/
@Service
class ConfigurationService extends Logging {
@Autowired private var configMapper: ConfigMapper = _
@Autowired private var validatorManager: ValidatorManager = _
@Transactional
def addKey(creator:String,appName:String,treeName:String,key: ConfigKey): Unit ={
val appID:Long = configMapper.selectAppIDByAppName(appName)
val creatorID: Long = configMapper.selectAppIDByAppName(creator)
val tree:ConfigTree = configMapper.selectTreeByAppIDAndName(appID,treeName)
key.setId(null)
key.setApplicationID(creatorID)
configMapper.insertKey(key)
configMapper.insertKeyTree(key.getId,tree.getId)
}
def insertCreator(creator:String): Unit ={
val creatorID: Long = configMapper.selectAppIDByAppName(creator)
if(creatorID == null) configMapper.insertCreator(creator) else warn(s"creator${creator} exists")
}
def listKeyByCreatorAndAppName(creator:String, appName:String):java.util.List[ConfigKey] ={
val creatorID: Long = configMapper.selectAppIDByAppName(creator)
val appID:Long = configMapper.selectAppIDByAppName(appName)
configMapper.listKeyByCreatorAndAppName(creatorID,appID)
}
@Transactional
def copyKeyFromIDE(key:ConfigKey,creator:String, appName:String) ={
val creatorID: Long = configMapper.selectAppIDByAppName(creator)
key.setApplicationID(creatorID)
val treeID = configMapper.selectTreeIDByKeyID(key.getId)
key.setId(null)
configMapper.insertKey(key)
configMapper.insertKeyTree(key.getId,treeID)
}
def updateUserValue(setting: ConfigKeyValueVO) = {
if (!StringUtils.isEmpty(setting.getValue)) {
if(!StringUtils.isEmpty(setting.getUnit) && !setting.getValue.contains(setting.getUnit) && !setting.getValue.contains(setting.getUnit.toLowerCase)){
setting.setValue(setting.getValue + setting.getUnit)
}
val key = configMapper.selectKeyByKeyID(setting.getKeyID)
info(s"Save parameter ${key.getKey} value ${setting.getValue} is not empty, enter checksum...(保存参数${key.getKey}值${setting.getValue}不为空,进入校验...)")
if (!validatorManager.getOrCreateValidator(key.getValidateType).validate(setting.getValue, key.getValidateRange)) {
throw new ConfigurationException(s"Parameter verification failed(参数校验失败):${key.getKey}--${key.getValidateType}--${key.getValidateRange}--${setting.getValue}")
}
}
configMapper.updateUserValue(setting.getValue, setting.getValueID)
}
def getFullTree(appName: String, userName: String, creator: String): util.ArrayList[ConfigTree] = {
val id = 0L
val configTrees = configMapper.selectTreesByAppNameAndParentID(appName, id)
val configTreesReturn = new util.ArrayList[ConfigTree]()
import scala.collection.JavaConversions._
configTrees.foreach(f =>
configTreesReturn.add(recursiveFullTree(f.getId, appName, userName, creator))
)
configTreesReturn
}
def getVO(key: ConfigKey, value: ConfigKeyUser): ConfigKeyValueVO = {
val vo = new ConfigKeyValue
vo.setAdvanced(key.getAdvanced)
vo.setApplicationID(value.getApplicationID)
vo.setCreatorID(key.getApplicationID)
vo.setDefaultValue(key.getDefaultValue)
vo.setDescription(key.getDescription)
vo.setHidden(key.getHidden)
vo.setKey(key.getKey)
vo.setKeyID(key.getId)
vo.setLevel(key.getLevel)
vo.setName(key.getName)
vo.setUserName(value.getUserName)
vo.setValidateRange(key.getValidateRange)
vo.setValidateType(key.getValidateType)
vo.setValue(value.getValue)
vo.setValueID(value.getId)
vo.setUnit(key.getUnit)
vo
}
private def recursiveFullTree(id: Long, appName: String, userName: String, creator: String): ConfigTree = {
import scala.collection.JavaConversions._
val configTree = configMapper.selectTreeByTreeID(id)
val keys = getKeysByTreeID(configTree.getId(), configMapper.selectAppIDByAppName(creator))
if (!keys.isEmpty && keys.get(0) != null) {
keys.foreach {
f =>
var value = getValueByKeyId(f.getId, userName, appName)
if (value == null) {
value = persisteUserValue(f.getId, userName, appName)
}
//configTree.getSettings.add(getVO(f, value))
Utils.tryCatch(configTree.getSettings.add(getVO(f, value))){
t => {
info(t.getMessage)
info("restful get data...(开始将非法的数据置空...)")
val setting = new ConfigKeyValueVO
setting.setValue(null)
setting.setValueID(value.getId)
updateUserValue(setting)
info("Data is blanked out...(数据置空完成...)")
value.setValue(null)
configTree.getSettings.add(getVO(f, value))
}
}
}
}
val parentTree = configMapper.selectTreesByAppNameAndParentID(appName, id)
parentTree.foreach { f => configTree.getChildrens.add(recursiveFullTree(f.getId, appName, userName, creator)) }
return configTree
}
private def persisteUserValue(keyID: Long, userName: String, appName: String): ConfigKeyUser = {
var value = new ConfigKeyUser()
value.setKeyID(keyID)
value.setUserName(userName)
value.setApplicationID(configMapper.selectAppIDByAppName(appName))
try {
configMapper.insertValue(value)
} catch {
case e: Exception => value = getValueByKeyId(value.getKeyID, userName, appName)
}
value
}
private def getKeysByTreeID(treeID: Long, creatorID: Long): util.List[ConfigKey] = {
configMapper.selectKeysByTreeID(treeID, creatorID)
}
private def getValueByKeyId(keyID: Long, userName: String, appName: String): ConfigKeyUser = {
val appID = configMapper.selectAppIDByAppName(appName)
configMapper.selectValueByKeyId(keyID, userName, appID)
}
def queryAppConfigWithGlobal(userName: String, creator: String, appName: String, isMerge: Boolean): ResponseQueryConfig = {
val config = new ResponseQueryConfig
val globalMap = queryGolbalConfig(userName).getKeyAndValue
val appMap = queryAppConfig(userName, null, appName).getKeyAndValue //Here is when isMerge=false(这里是为了isMerge=false的时候)
val creatorMap = queryAppConfig(userName, creator, appName).getKeyAndValue
if (!isMerge) {
val notMerge = new util.HashMap[String, String]()
val globalJson: String = BDPJettyServerHelper.gson.toJson(globalMap)
val appJson: String = BDPJettyServerHelper.gson.toJson(appMap)
val creatorJson: String = BDPJettyServerHelper.gson.toJson(creatorMap)
notMerge.put("creator", creatorJson)
notMerge.put("appName", appJson)
notMerge.put("global", globalJson)
config.setKeyAndValue(notMerge)
config
} else {
globalMap.putAll(creatorMap)
config.setKeyAndValue(globalMap)
config
}
}
def queryAppConfig(userName: String, creator: String, appName: String): ResponseQueryConfig = {
val appID: Long = configMapper.selectAppIDByAppName(appName)
var creatorID: Long = null
if (StringUtils.isBlank(creator) || creator == appName) creatorID = appID
else if (StringUtils.isNotBlank(appName)) creatorID = configMapper.selectAppIDByAppName(creator)
getResponseConfig(userName, appID, creatorID)
}
def queryGolbalConfig(userName: String): ResponseQueryConfig = {
val globalID = configMapper.selectAppIDByAppName(Constants.GOLBAL_CONFIG_NAME)
getResponseConfig(userName, globalID, globalID)
}
private def getResponseConfig(userName: String, appID: Long, creatorID: Long): ResponseQueryConfig = {
val all = configMapper.selectAllAppKVs(creatorID,appID)//Currently, the tree table is connected to the left, so no one in the tree will be calculated.(目前左连接了tree表,所以不在树上的都不会被计算出来)
val user = configMapper.selectAppconfigByAppIDAndCreatorID(userName, creatorID, appID)
val config = new ResponseQueryConfig
config.setKeyAndValue(getMap(all, user))
config
}
private def getMap(all: util.List[ConfigKeyValueVO], user: util.List[ConfigKeyValueVO]): util.Map[String, String] = {
val map = new util.HashMap[String, String]()
import scala.collection.JavaConversions._
all.foreach(f => map.put(f.getKey, f.getValue))
user.foreach(f => map.put(f.getKey, f.getValue))
map
}
//Verify when data is sent to internal services(数据给内部服务的时候进行校验)
implicit def ConfigKeyValuesToVOs(configKeyValus: java.util.List[ConfigKeyValue]): java.util.List[ConfigKeyValueVO] = {
import scala.collection.JavaConversions._
val vos = new util.ArrayList[ConfigKeyValueVO]()
configKeyValus.foreach { f =>
if (StringUtils.isEmpty(f.getValue)) {
//All queries must enter, user's query, if the value is null, it will enter(all的查询必定进入,user的查询,如果值为null也会进入)
info(s"The rpc-query value is null, and the ${f.getUserName} parameter ${f.getKey} is appended with the default value ${f.getDefaultValue}(rpc-查询值为空,给${f.getUserName}参数${f.getKey}附上默认值${f.getDefaultValue})")
f.setValue(f.getDefaultValue)//Here you need to ensure that the default value is non-empty.(这里需要保证默认值是非空的)
}
Utils.tryCatch(vos.add(f)){
t => {
info(t.getMessage)
info("Rpc starts to empty illegal data...(rpc开始将非法的数据置空...)")
val setting = new ConfigKeyValueVO
setting.setValue(null)
setting.setValueID(f.getValueID)
updateUserValue(setting)
info("Data is blanked out...(数据置空完成...)")
f.setValue(f.getDefaultValue)
vos.add(f)
}
}
}
vos
}
//Check when data is returned to the front end(数据返回给前端的时候进行校验)
implicit def ConfigKeyValueToVO(configKeyValue: ConfigKeyValue): ConfigKeyValueVO = {
val vo = new ConfigKeyValueVO
var validateValue = configKeyValue.getValue
if (StringUtils.isEmpty(validateValue)) {
//According to the reason, rpc will not enter this side unless the default value of the key is null.()按道理rpc的不会进入这边,除非key的defaultvalue是null,进入这里也不影响)
info(s"Restful-${configKeyValue.getUserName} Query the ${configKeyValue.getKey} value to null, and let the default value ${configKeyValue.getDefaultValue} be checked(restful-${configKeyValue.getUserName}查询${configKeyValue.getKey}值为空,让默认值${configKeyValue.getDefaultValue}进行校验)")
validateValue = configKeyValue.getDefaultValue
}
if (!validatorManager.getOrCreateValidator(configKeyValue.getValidateType).validate(validateValue, configKeyValue.getValidateRange)) {
throw new ConfigurationException(s"Parameter verification failed(参数校验失败):${configKeyValue.getKey}--${configKeyValue.getValidateType}--${configKeyValue.getValidateRange}--${validateValue}--${configKeyValue.getUserName}")
}
BeanUtils.copyProperties(configKeyValue, vo)
vo
}
}