From e8790e9f0970cd190c928edeed0752883b93ad41 Mon Sep 17 00:00:00 2001 From: youys <1272586223@qq.com> Date: Wed, 6 Jul 2022 16:52:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=91=E8=84=91=E4=BB=A3=E7=A0=81=E8=B4=A8?= =?UTF-8?q?=E9=87=8F=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 + .../educoder/ecsonar/constant/Constant.java | 6 + .../controller/CloudBrainController.java | 52 ++++++- .../ecsonar/dao/CloudTaskInfoDao.java | 2 +- .../ecsonar/dao/CloudTaskInfoDetailDao.java | 16 ++ .../net/educoder/ecsonar/dao/ProjectDao.java | 10 ++ .../educoder/ecsonar/model/IssuesMetrics.java | 46 ++++++ .../vo/CloudQualityInspectMetricsVO.java | 81 ++++++++++ .../model/vo/CloudQualityInspectResultVO.java | 43 ++++++ .../ecsonar/model/vo/IssuesSearchVO.java | 37 +++++ .../educoder/ecsonar/model/vo/IssuesVO.java | 55 +++++++ .../ecsonar/model/vo/SourceCodeVO.java | 28 ++++ .../ecsonar/services/CloudBrainService.java | 146 +++++++++++++++++- src/main/resources/application.properties | 4 +- 14 files changed, 520 insertions(+), 12 deletions(-) create mode 100644 src/main/java/net/educoder/ecsonar/model/IssuesMetrics.java create mode 100644 src/main/java/net/educoder/ecsonar/model/vo/CloudQualityInspectMetricsVO.java create mode 100644 src/main/java/net/educoder/ecsonar/model/vo/CloudQualityInspectResultVO.java create mode 100644 src/main/java/net/educoder/ecsonar/model/vo/IssuesSearchVO.java create mode 100644 src/main/java/net/educoder/ecsonar/model/vo/IssuesVO.java create mode 100644 src/main/java/net/educoder/ecsonar/model/vo/SourceCodeVO.java diff --git a/pom.xml b/pom.xml index 62f400a..1fce790 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,12 @@ 5.7.19 + + cn.hutool + hutool-http + 5.7.19 + + com.alibaba fastjson diff --git a/src/main/java/net/educoder/ecsonar/constant/Constant.java b/src/main/java/net/educoder/ecsonar/constant/Constant.java index 26d24e6..d70d37e 100644 --- a/src/main/java/net/educoder/ecsonar/constant/Constant.java +++ b/src/main/java/net/educoder/ecsonar/constant/Constant.java @@ -19,4 +19,10 @@ public class Constant { public static final List language = Arrays.asList(JAVA, C, CXX, PYTHON); public static final String SUCCESS = "SUCCESS"; + + + public static final String BUG = "BUG"; + public static final String VULNERABILITY = "VULNERABILITY"; + public static final String CODE_SMELL = "CODE_SMELL"; + public static final String SECURITY_HOTSPOT = "SECURITY_HOTSPOT"; } diff --git a/src/main/java/net/educoder/ecsonar/controller/CloudBrainController.java b/src/main/java/net/educoder/ecsonar/controller/CloudBrainController.java index dfd2f19..73ec300 100644 --- a/src/main/java/net/educoder/ecsonar/controller/CloudBrainController.java +++ b/src/main/java/net/educoder/ecsonar/controller/CloudBrainController.java @@ -3,7 +3,7 @@ package net.educoder.ecsonar.controller; import com.alibaba.fastjson.JSONObject; import net.educoder.ecsonar.model.api.QualityInspect; import net.educoder.ecsonar.model.api.QualityInspectIsCompleted; -import net.educoder.ecsonar.model.vo.CloudBrainQualityInspectVO; +import net.educoder.ecsonar.model.vo.*; import net.educoder.ecsonar.services.CloudBrainService; import net.educoder.ecsonar.utils.ResponseResult; import org.apache.commons.collections4.CollectionUtils; @@ -12,7 +12,9 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @Author: youys @@ -28,10 +30,16 @@ public class CloudBrainController { @Autowired private CloudBrainService cloudBrainService; + /** + * 云脑代码质量检测 + * + * @param cloudBrainQualityInspectVO + * @return + */ @PostMapping("/cloudQualityInspect") public ResponseResult cloudQualityInspect(@RequestBody List cloudBrainQualityInspectVO) { logger.info("cloudQualityInspect请求参数:{}", JSONObject.toJSONString(cloudBrainQualityInspectVO)); - if(CollectionUtils.isEmpty(cloudBrainQualityInspectVO)){ + if (CollectionUtils.isEmpty(cloudBrainQualityInspectVO)) { ResponseResult.error("参数不能为空"); } QualityInspect qualityInspect = cloudBrainService.startQualityInspect(cloudBrainQualityInspectVO); @@ -40,13 +48,45 @@ public class CloudBrainController { /** - * 质量检测任务是否完成 + * 检测结果查询 + * * @param taskId * @return */ - @GetMapping(value = "/cloudQualityInspectIsCompleted/{taskId}") - public ResponseResult cloudQualityInspectIsCompleted(@PathVariable String taskId){ - QualityInspectIsCompleted result = cloudBrainService.cloudQualityInspectIsCompleted(taskId); + @GetMapping(value = "/cloudQualityInspectResult") + public ResponseResult cloudQualityInspectResult(@RequestParam String taskId) { + CloudQualityInspectResultVO result = cloudBrainService.cloudQualityInspectResult(taskId); + return ResponseResult.success(result); + } + + + /** + * issues详情查询 + * + * @param searchVO + * @return + */ + @GetMapping(value = "/issues/search") + public ResponseResult issuesSearch(IssuesSearchVO searchVO) { + List result = cloudBrainService.issuesSearch(searchVO); + return ResponseResult.success(result); + } + + + /** + * 获取源码 + * + * @param component + * @return + */ + @GetMapping(value = "/getSourceCode") + public ResponseResult getSourceCode(@RequestParam String component) { + + List sources = cloudBrainService.getSourceCode(component); + + Map result = new HashMap<>(2); + result.put("sources", sources); + return ResponseResult.success(result); } diff --git a/src/main/java/net/educoder/ecsonar/dao/CloudTaskInfoDao.java b/src/main/java/net/educoder/ecsonar/dao/CloudTaskInfoDao.java index 6d62683..5409e41 100644 --- a/src/main/java/net/educoder/ecsonar/dao/CloudTaskInfoDao.java +++ b/src/main/java/net/educoder/ecsonar/dao/CloudTaskInfoDao.java @@ -34,6 +34,6 @@ public interface CloudTaskInfoDao { * @param id * @param status */ - @Update("update cloud_task_info set status=#{status} where id=#{id}") + @Update("update cloud_task_info set status=#{status},update_time=current_timestamp where id=#{id}") void updateCloudTaskInfoStatus(@Param("id") String id, @Param("status") Integer status); } diff --git a/src/main/java/net/educoder/ecsonar/dao/CloudTaskInfoDetailDao.java b/src/main/java/net/educoder/ecsonar/dao/CloudTaskInfoDetailDao.java index 3fc7031..3433df8 100644 --- a/src/main/java/net/educoder/ecsonar/dao/CloudTaskInfoDetailDao.java +++ b/src/main/java/net/educoder/ecsonar/dao/CloudTaskInfoDetailDao.java @@ -6,6 +6,8 @@ import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; +import java.util.List; + /** * @Author: youys * @Date: 2022/1/18 @@ -31,6 +33,20 @@ public interface CloudTaskInfoDetailDao { void updateCloudTaskInfoDetailStatus(@Param("id") String id, @Param("status") Integer status); + /** + * 查询完成数 + * @param taskId + * @return + */ @Select("select count(1) from cloud_task_info_detail where task_id=#{taskId} and status=1") Integer selectCountByTaskId(String taskId); + + + /** + * 查询projectNames + * @param taskId + * @return + */ + @Select("select project_name from cloud_task_info_detail where task_id=#{taskId} and status=1") + List selectProjectNamesByTaskId(String taskId); } diff --git a/src/main/java/net/educoder/ecsonar/dao/ProjectDao.java b/src/main/java/net/educoder/ecsonar/dao/ProjectDao.java index 8097198..2ff5db0 100644 --- a/src/main/java/net/educoder/ecsonar/dao/ProjectDao.java +++ b/src/main/java/net/educoder/ecsonar/dao/ProjectDao.java @@ -1,5 +1,6 @@ package net.educoder.ecsonar.dao; +import net.educoder.ecsonar.model.IssuesMetrics; import net.educoder.ecsonar.model.Metrics; import net.educoder.ecsonar.model.Project; import org.apache.ibatis.annotations.Mapper; @@ -48,4 +49,13 @@ public interface ProjectDao { "(SELECT COALESCE(count(*),0) minor_violations FROM issues where project_uuid=#{projectUuid} and status='OPEN' and issue_type=3 and severity='MINOR')," + "(select text_value violations from project_measures where component_uuid = #{projectUuid} and metric_id = 93 order by id desc limit 1)") Metrics selectMetricsByProjectUuid(String projectUuid); + + + + + @Select("select (select count(1) from issues where project_uuid=#{projectUuid} and issue_type=1) vulnerability," + + "(select count(1) from issues where project_uuid=#{projectUuid} and issue_type=2) bugs," + + "(select count(1) from issues where project_uuid=#{projectUuid} and issue_type=3) codeSmell," + + "(select value from project_measures pm where component_uuid=#{projectUuid} and metric_id=3) codeLines") + IssuesMetrics selectIssuesMetrics(String projectUuid); } diff --git a/src/main/java/net/educoder/ecsonar/model/IssuesMetrics.java b/src/main/java/net/educoder/ecsonar/model/IssuesMetrics.java new file mode 100644 index 0000000..5231aaa --- /dev/null +++ b/src/main/java/net/educoder/ecsonar/model/IssuesMetrics.java @@ -0,0 +1,46 @@ +package net.educoder.ecsonar.model; + +/** + * @Author: youys + * @Date: 2022/7/6 + * @Description: + */ +public class IssuesMetrics { + + private Integer bugs; + private Integer vulnerability; + private Integer codeSmell; + private Integer codeLines; + + public Integer getBugs() { + return bugs; + } + + public void setBugs(Integer bugs) { + this.bugs = bugs; + } + + public Integer getVulnerability() { + return vulnerability; + } + + public void setVulnerability(Integer vulnerability) { + this.vulnerability = vulnerability; + } + + public Integer getCodeSmell() { + return codeSmell; + } + + public void setCodeSmell(Integer codeSmell) { + this.codeSmell = codeSmell; + } + + public Integer getCodeLines() { + return codeLines; + } + + public void setCodeLines(Integer codeLines) { + this.codeLines = codeLines; + } +} diff --git a/src/main/java/net/educoder/ecsonar/model/vo/CloudQualityInspectMetricsVO.java b/src/main/java/net/educoder/ecsonar/model/vo/CloudQualityInspectMetricsVO.java new file mode 100644 index 0000000..b8589f7 --- /dev/null +++ b/src/main/java/net/educoder/ecsonar/model/vo/CloudQualityInspectMetricsVO.java @@ -0,0 +1,81 @@ +package net.educoder.ecsonar.model.vo; + + +/** + * @Author: youys + * @Date: 2022/7/6 + * @Description: + */ +public class CloudQualityInspectMetricsVO { + + + private String taskId; + private String projectName; + + /** + * bug + */ + private Integer bugs; + /**¬ + * 漏洞 + */ + private Integer vulnerability; + /** + * 代码气味 + */ + private Integer codeSmell; + /** + * 代码行数 + */ + private Integer codeLines; + + + public String getProjectName() { + return projectName; + } + + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public Integer getBugs() { + return bugs; + } + + public void setBugs(Integer bugs) { + this.bugs = bugs; + } + + public Integer getVulnerability() { + return vulnerability; + } + + public void setVulnerability(Integer vulnerability) { + this.vulnerability = vulnerability; + } + + + public Integer getCodeLines() { + return codeLines; + } + + public void setCodeLines(Integer codeLines) { + this.codeLines = codeLines; + } + + public Integer getCodeSmell() { + return codeSmell; + } + + public void setCodeSmell(Integer codeSmell) { + this.codeSmell = codeSmell; + } +} diff --git a/src/main/java/net/educoder/ecsonar/model/vo/CloudQualityInspectResultVO.java b/src/main/java/net/educoder/ecsonar/model/vo/CloudQualityInspectResultVO.java new file mode 100644 index 0000000..6287ed1 --- /dev/null +++ b/src/main/java/net/educoder/ecsonar/model/vo/CloudQualityInspectResultVO.java @@ -0,0 +1,43 @@ +package net.educoder.ecsonar.model.vo; + + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author: youys + * @Date: 2022/7/6 + * @Description: + */ +public class CloudQualityInspectResultVO { + + + private String taskId; + private Integer completed; + + private List metricsVOList = new ArrayList<>(0); + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public Integer getCompleted() { + return completed; + } + + public void setCompleted(Integer completed) { + this.completed = completed; + } + + public List getMetricsVOList() { + return metricsVOList; + } + + public void setMetricsVOList(List metricsVOList) { + this.metricsVOList = metricsVOList; + } +} diff --git a/src/main/java/net/educoder/ecsonar/model/vo/IssuesSearchVO.java b/src/main/java/net/educoder/ecsonar/model/vo/IssuesSearchVO.java new file mode 100644 index 0000000..b6ebbf8 --- /dev/null +++ b/src/main/java/net/educoder/ecsonar/model/vo/IssuesSearchVO.java @@ -0,0 +1,37 @@ +package net.educoder.ecsonar.model.vo; + +/** + * @Author: youys + * @Date: 2022/7/6 + * @Description: + */ +public class IssuesSearchVO { + + private String taskId; + private String projectName; + private String type; + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getProjectName() { + return projectName; + } + + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/src/main/java/net/educoder/ecsonar/model/vo/IssuesVO.java b/src/main/java/net/educoder/ecsonar/model/vo/IssuesVO.java new file mode 100644 index 0000000..6f4a248 --- /dev/null +++ b/src/main/java/net/educoder/ecsonar/model/vo/IssuesVO.java @@ -0,0 +1,55 @@ +package net.educoder.ecsonar.model.vo; + +/** + * @Author: youys + * @Date: 2022/7/6 + * @Description: + */ +public class IssuesVO { + + private String component; + private String message; + private String status; + private String severity; + private Integer line; + + public String getComponent() { + return component; + } + + public void setComponent(String component) { + this.component = component; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getSeverity() { + return severity; + } + + public void setSeverity(String severity) { + this.severity = severity; + } + + public Integer getLine() { + return line; + } + + public void setLine(Integer line) { + this.line = line; + } +} diff --git a/src/main/java/net/educoder/ecsonar/model/vo/SourceCodeVO.java b/src/main/java/net/educoder/ecsonar/model/vo/SourceCodeVO.java new file mode 100644 index 0000000..0441a03 --- /dev/null +++ b/src/main/java/net/educoder/ecsonar/model/vo/SourceCodeVO.java @@ -0,0 +1,28 @@ +package net.educoder.ecsonar.model.vo; + +/** + * @Author: youys + * @Date: 2022/7/6 + * @Description: + */ +public class SourceCodeVO { + + private String code; + private Integer line; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Integer getLine() { + return line; + } + + public void setLine(Integer line) { + this.line = line; + } +} diff --git a/src/main/java/net/educoder/ecsonar/services/CloudBrainService.java b/src/main/java/net/educoder/ecsonar/services/CloudBrainService.java index e901da9..9c6c7ea 100644 --- a/src/main/java/net/educoder/ecsonar/services/CloudBrainService.java +++ b/src/main/java/net/educoder/ecsonar/services/CloudBrainService.java @@ -1,23 +1,29 @@ package net.educoder.ecsonar.services; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import net.educoder.ecsonar.dao.CloudTaskInfoDao; import net.educoder.ecsonar.dao.CloudTaskInfoDetailDao; +import net.educoder.ecsonar.dao.ProjectDao; import net.educoder.ecsonar.exception.BusinessException; import net.educoder.ecsonar.model.CloudTaskInfo; import net.educoder.ecsonar.model.CloudTaskInfoDetail; +import net.educoder.ecsonar.model.IssuesMetrics; +import net.educoder.ecsonar.model.Project; import net.educoder.ecsonar.model.api.QualityInspect; import net.educoder.ecsonar.model.api.QualityInspectIsCompleted; -import net.educoder.ecsonar.model.vo.CloudBrainQualityInspectVO; +import net.educoder.ecsonar.model.vo.*; import net.educoder.ecsonar.task.CloudBrainQualityInspectRunnable; import net.educoder.ecsonar.utils.IdUtils; -import net.educoder.ecsonar.utils.SystemUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -41,6 +47,9 @@ public class CloudBrainService { @Autowired private DbOperateService dbOperateService; + @Autowired + private ProjectDao projectDao; + @Autowired @Qualifier("sonarScannerPool") private ExecutorService sonarScannerPool; @@ -49,6 +58,9 @@ public class CloudBrainService { @Qualifier("sonarQueryResultPool") private ExecutorService sonarQueryResultPool; + @Value("${sonar.host}") + private String sonarHost; + @Transactional(rollbackFor = Exception.class) public QualityInspect startQualityInspect(List cloudBrainQualityInspectVO) { @@ -108,4 +120,130 @@ public class CloudBrainService { QualityInspectIsCompleted qualityInspectIsCompleted = new QualityInspectIsCompleted(taskId, completed); return qualityInspectIsCompleted; } + + public CloudQualityInspectResultVO cloudQualityInspectResult(String taskId) { + + QualityInspectIsCompleted qualityInspectIsCompleted = cloudQualityInspectIsCompleted(taskId); + + + CloudQualityInspectResultVO resultVO = new CloudQualityInspectResultVO(); + resultVO.setTaskId(taskId); + resultVO.setCompleted(qualityInspectIsCompleted.getCompleted()); + if (qualityInspectIsCompleted.getCompleted() == 0) { + return resultVO; + } + + CloudTaskInfo cloudTaskInfo = cloudTaskInfoDao.queryById(taskId); + + if (cloudTaskInfo == null) { + return resultVO; + } + + List projectNames = cloudTaskInfoDetailDao.selectProjectNamesByTaskId(taskId); + + + List metricsVOList = new ArrayList<>(projectNames.size()); + for (String projectName : projectNames) { + Project project = projectDao.findByName(projectName); + + IssuesMetrics issuesMetrics = projectDao.selectIssuesMetrics(project.getProject_uuid()); + CloudQualityInspectMetricsVO metricsVO = new CloudQualityInspectMetricsVO(); + metricsVO.setProjectName(projectName); + metricsVO.setBugs(issuesMetrics.getBugs()); + metricsVO.setVulnerability(issuesMetrics.getVulnerability()); + metricsVO.setCodeSmell(issuesMetrics.getCodeSmell()); + metricsVO.setCodeLines(issuesMetrics.getCodeLines()); + metricsVOList.add(metricsVO); + + + } + + resultVO.setMetricsVOList(metricsVOList); + return resultVO; + } + + + /** + * issues 搜索 + * @param searchVO + * @return + */ + public List issuesSearch(IssuesSearchVO searchVO) { + List issues = doGetIssues(searchVO.getProjectName(), searchVO.getType()); + return issues; + } + + + /** + * 获取源码 + * @param component + * @return + */ + public List getSourceCode(String component) { + return doGetSourceCode(component); + } + + + /** + * 获取issues + * + * @param projectName + * @param types + * @return + */ + private List doGetIssues(String projectName, String types) { + + StringBuilder sb = new StringBuilder(); + sb.append("/api/issues/search?componentKeys=").append(projectName) + .append("&s=FILE_LINE&resolved=false&types=").append(types) + .append("&ps=500&organization=default-organization&facets=severities%2Ctypes&additionalFields=_all"); + + String url = sonarHost + sb.toString(); + + String result = HttpUtil.get(url); + if (StringUtils.isEmpty(result)) { + return new ArrayList<>(0); + } + JSONArray issuesArray = JSONObject.parseObject(result).getJSONArray("issues"); + List issuesVOS = new ArrayList<>(issuesArray.size()); + for (Object o : issuesArray) { + JSONObject issueObj = (JSONObject) o; + + IssuesVO vo = new IssuesVO(); + vo.setComponent(issueObj.getString("component")); + vo.setLine(issueObj.getInteger("line")); + vo.setMessage(issueObj.getString("message")); + vo.setSeverity(issueObj.getString("severity")); + vo.setStatus(issueObj.getString("status")); + + issuesVOS.add(vo); + } + return issuesVOS; + } + + private List doGetSourceCode(String component) { + + StringBuilder sb = new StringBuilder(); + sb.append("/api/sources/lines?key=").append(component) + .append("&from=1&to=50100"); + String url = sonarHost + sb.toString(); + + String result = HttpUtil.get(url); + if (StringUtils.isEmpty(result)) { + return new ArrayList<>(0); + } + JSONArray sourcesArrays = JSONObject.parseObject(result).getJSONArray("sources"); + List sourceCodeVOS = new ArrayList<>(sourcesArrays.size()); + for (Object o : sourcesArrays) { + JSONObject issueObj = (JSONObject) o; + + SourceCodeVO vo = new SourceCodeVO(); + vo.setCode(issueObj.getString("code")); + vo.setLine(issueObj.getInteger("line")); + sourceCodeVOS.add(vo); + } + return sourceCodeVOS; + } + + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8f9fc25..3609fd7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -56,4 +56,6 @@ last.run.id=0 skip.checked=true -server.port=8081 \ No newline at end of file +server.port=8081 + +sonar.host=http://localhost:9000 \ No newline at end of file