sonar分析

test
youys 3 years ago
parent 3bb714f796
commit 3487d0739f

@ -51,6 +51,18 @@
<artifactId>druid-spring-boot-starter</artifactId> <artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version> <version>1.1.9</version>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.7.19</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>

@ -2,8 +2,9 @@ package net.educoder.ecsonar;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class EcsonarApplication { public class EcsonarApplication {
public static void main(String[] args) { public static void main(String[] args) {

@ -0,0 +1,109 @@
package net.educoder.ecsonar.config;
import net.educoder.ecsonar.exception.BusinessException;
import net.educoder.ecsonar.utils.ResponseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import javax.servlet.http.HttpServletRequest;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
@ControllerAdvice
public class CustomExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomExceptionHandler.class);
/**
* Exception
*
* @param request
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult handleException(HttpServletRequest request, Exception e) {
LOGGER.error("接口:{},Exception异常:" + e.getMessage(), request.getRequestURI(), e);
return ResponseResult.error("系统出问题了");
}
/**
* BindException
*
* @param request
* @param be
* @return
*/
@ExceptionHandler(BindException.class)
@ResponseBody
public ResponseResult handleException(HttpServletRequest request, BindException be) {
LOGGER.error("接口:{},BindException异常:" + be.getMessage(), request.getRequestURI());
return ResponseResult.error("参数错误");
}
/**
* BusinessException
*
* @param request
* @param e
* @return
*/
@ExceptionHandler(BusinessException.class)
@ResponseBody
public ResponseResult handleException(HttpServletRequest request, BusinessException e) {
LOGGER.error("接口:"+request.getRequestURI()+",BusinessException异常:",e);
return ResponseResult.error(e.getMessage());
}
/**
* MaxUploadSizeExceededException
*
* @param request
* @param e
* @return
*/
@ExceptionHandler(MaxUploadSizeExceededException.class)
@ResponseBody
public ResponseResult handleException(HttpServletRequest request, MaxUploadSizeExceededException e) {
LOGGER.error("接口:{},文件上传超过最大设置的值:" + e.getMessage(), request.getRequestURI());
return ResponseResult.error("文件上传超过最大设置的值");
}
/**
* 405
*
* @param ex
* @param request
* @return
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseBody
public ResponseResult handleHttpRequestMethodNotSupported(HttpServletRequest request, HttpRequestMethodNotSupportedException ex) {
LOGGER.error("接口:{},请求方式错误405:" + ex.getMessage(), request.getRequestURI(), ex);
return ResponseResult.error("请求方式错误405");
}
/**
*
*
* @param ex
* @param request
* @return
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseBody
public ResponseResult handleMissingServletRequestParameter(HttpServletRequest request, MissingServletRequestParameterException ex) {
LOGGER.error("接口:{},缺少必传参数400:" + ex.getMessage(), request.getRequestURI(), ex);
return ResponseResult.error("缺少必填参数");
}
}

@ -63,7 +63,8 @@ public class DynamicDataSourceConfig {
masterDataSource.setUsername(masterUsername); masterDataSource.setUsername(masterUsername);
masterDataSource.setPassword(masterPassword); masterDataSource.setPassword(masterPassword);
masterDataSource.setInitialSize(initSize); masterDataSource.setInitialSize(initSize);
masterDataSource.setConnectionInitSqls(INIT_SQLS); masterDataSource.setMaxActive(initSize);
masterDataSource.setMinIdle(initSize);
return masterDataSource; return masterDataSource;
} }
@ -75,6 +76,8 @@ public class DynamicDataSourceConfig {
readonlyDataSource.setUsername(readonlyUsername); readonlyDataSource.setUsername(readonlyUsername);
readonlyDataSource.setPassword(readonlyPassword); readonlyDataSource.setPassword(readonlyPassword);
readonlyDataSource.setInitialSize(initSize); readonlyDataSource.setInitialSize(initSize);
readonlyDataSource.setMaxActive(initSize);
readonlyDataSource.setMinIdle(initSize);
readonlyDataSource.setConnectionInitSqls(INIT_SQLS); readonlyDataSource.setConnectionInitSqls(INIT_SQLS);
return readonlyDataSource; return readonlyDataSource;
} }

@ -22,7 +22,7 @@ public class DynamicDataSourceContextHolder {
*/ */
public static String getContextKey(){ public static String getContextKey(){
String key = DATASOURCE_CONTEXT_KEY_HOLDER.get(); String key = DATASOURCE_CONTEXT_KEY_HOLDER.get();
return key == null? net.educode.detection.config.DynamicDataSourceConfig.MASTER: key; return key == null? DynamicDataSourceConfig.MASTER: key;
} }
/** /**

@ -2,16 +2,31 @@ package net.educoder.ecsonar.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import java.util.concurrent.ExecutorService; import java.util.concurrent.*;
import java.util.concurrent.Executors;
@Configuration @Configuration
public class ThreadPoolConfig { public class ThreadPoolConfig {
@Bean @Bean("sonarScannerPool")
public ExecutorService getThreadPool(){ @Primary
return Executors.newFixedThreadPool(10); public ExecutorService sonarScannerPool() {
ThreadFactory sonarScannerPool = new CustomizableThreadFactory("sonarScanner-pool-");
return new ThreadPoolExecutor(10, 10, 60,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(10000), sonarScannerPool,
new ThreadPoolExecutor.AbortPolicy());
}
@Bean("sonarQueryResultPool")
public ExecutorService queryResultPool() {
ThreadFactory sonarQueryResultPool = new CustomizableThreadFactory("sonarScanner-pool-");
return new ThreadPoolExecutor(5, 10, 60,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(10000),
sonarQueryResultPool,
new ThreadPoolExecutor.AbortPolicy());
} }
} }

@ -0,0 +1,54 @@
package net.educoder.ecsonar.config;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
List<MediaType> supportedMediaTypes = new ArrayList<>(20);
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
supportedMediaTypes.add(MediaType.APPLICATION_PDF);
supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XML);
supportedMediaTypes.add(MediaType.IMAGE_GIF);
supportedMediaTypes.add(MediaType.IMAGE_JPEG);
supportedMediaTypes.add(MediaType.IMAGE_PNG);
supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
supportedMediaTypes.add(MediaType.TEXT_HTML);
supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
supportedMediaTypes.add(MediaType.TEXT_PLAIN);
supportedMediaTypes.add(MediaType.TEXT_XML);
fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
// FastJsonConfig fastJsonConfig = new FastJsonConfig();
// fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
//
// fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
converters.add(0,fastJsonHttpMessageConverter);
}
}

@ -0,0 +1,20 @@
package net.educoder.ecsonar.constant;
import java.util.Arrays;
import java.util.List;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class Constant {
public static final String JAVA = "JAVA";
public static final String C = "C";
public static final String CXX = "C++";
public static final String PYTHON = "PYTHON";
public static final List<String> language = Arrays.asList(JAVA, C, CXX, PYTHON);
}

@ -1,11 +1,15 @@
package net.educoder.ecsonar.controller; package net.educoder.ecsonar.controller;
import net.educoder.ecsonar.constant.Constant;
import net.educoder.ecsonar.model.RollPage;
import net.educoder.ecsonar.model.api.QualityInspect;
import net.educoder.ecsonar.model.api.QualityInspectIsCompleted; import net.educoder.ecsonar.model.api.QualityInspectIsCompleted;
import net.educoder.ecsonar.model.api.QualityInspectResult; import net.educoder.ecsonar.model.api.QualityInspectResultData;
import net.educoder.ecsonar.model.vo.QualityInspectVO; import net.educoder.ecsonar.model.vo.QualityInspectVO;
import net.educoder.ecsonar.services.QualityInspectService; import net.educoder.ecsonar.services.QualityInspectService;
import net.educoder.ecsonar.utils.ResponseResult; import net.educoder.ecsonar.utils.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
/** /**
@ -13,7 +17,7 @@ import org.springframework.web.bind.annotation.*;
* @Date: 2022/1/17 * @Date: 2022/1/17
* @Description: * @Description:
*/ */
@RestController @Controller
@RequestMapping("/api") @RequestMapping("/api")
public class QualityInspectController { public class QualityInspectController {
@ -27,9 +31,13 @@ public class QualityInspectController {
* @return * @return
*/ */
@RequestMapping(value = "qualityInspect", method = RequestMethod.POST) @RequestMapping(value = "qualityInspect", method = RequestMethod.POST)
@ResponseBody
public ResponseResult<String> qualityInspect(@RequestBody QualityInspectVO qualityInspectVO){ public ResponseResult<String> qualityInspect(@RequestBody QualityInspectVO qualityInspectVO){
String taskId = qualityInspectService.qualityInspect(qualityInspectVO); if (!Constant.language.contains(qualityInspectVO.getLanguage())) {
return ResponseResult.success(taskId); return ResponseResult.error("不支持的语言");
}
QualityInspect qualityInspect = qualityInspectService.qualityInspect(qualityInspectVO);
return ResponseResult.success(qualityInspect);
} }
@ -39,6 +47,7 @@ public class QualityInspectController {
* @return * @return
*/ */
@RequestMapping(value = "qualityInspectIsCompleted", method = RequestMethod.GET) @RequestMapping(value = "qualityInspectIsCompleted", method = RequestMethod.GET)
@ResponseBody
public ResponseResult<QualityInspectIsCompleted> qualityInspectIsCompleted(@RequestParam String taskId){ public ResponseResult<QualityInspectIsCompleted> qualityInspectIsCompleted(@RequestParam String taskId){
QualityInspectIsCompleted result = qualityInspectService.qualityInspectIsCompleted(taskId); QualityInspectIsCompleted result = qualityInspectService.qualityInspectIsCompleted(taskId);
return ResponseResult.success(result); return ResponseResult.success(result);
@ -51,8 +60,20 @@ public class QualityInspectController {
* @return * @return
*/ */
@RequestMapping(value = "qualityInspectResultQuery", method = RequestMethod.GET) @RequestMapping(value = "qualityInspectResultQuery", method = RequestMethod.GET)
public ResponseResult<QualityInspectResult> qualityInspectResultQuery(@RequestParam String taskId){ @ResponseBody
QualityInspectResult result = qualityInspectService.qualityInspectResultQuery(taskId); public ResponseResult<RollPage<QualityInspectResultData>> qualityInspectResultQuery(
@RequestParam(defaultValue = "50") Integer pageSize,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam String taskId){
if (pageNum <= 1) {
pageNum = 1;
}
QualityInspectIsCompleted isCompleted = qualityInspectService.qualityInspectIsCompleted(taskId);
if(isCompleted.getCompleted() != 1){
return ResponseResult.error("质量检测正在处理中");
}
RollPage<QualityInspectResultData> result = qualityInspectService.qualityInspectResultQuery(pageNum, pageSize,taskId);
return ResponseResult.success(result); return ResponseResult.success(result);
} }

@ -0,0 +1,16 @@
package net.educoder.ecsonar.dao;
import org.apache.ibatis.annotations.Select;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public interface CeActivityDao {
@Select("select status from ce_activity where component_uuid=#{projectId} and is_last=true")
String queryActivityStatus(String projectId);
}

@ -0,0 +1,15 @@
package net.educoder.ecsonar.dao;
import net.educoder.ecsonar.model.GameCodes;
import org.apache.ibatis.annotations.Select;
/**
* @Author: youys
* @Date: 2021/12/31
* @Description:
*/
public interface GameCodesDao {
@Select("select new_code code,path from game_codes where id=#{id}")
GameCodes queryOriginalCodeById(Long id);
}

@ -0,0 +1,26 @@
package net.educoder.ecsonar.dao;
import net.educoder.ecsonar.model.TaskInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public interface TaskInfoDao {
@Insert("insert into task_info(id,language,homework_id,people_number) values(#{id},#{language},#{homeworkId},#{peopleNumber} )")
void insertTaskInfo(TaskInfo taskInfo);
@Update("update task_info set status=#{status},update_time=current_timestamp where id=#{id}")
void updateTaskInfoStatus(@Param("id") String id, @Param("status") Integer status);
@Select("select id,homework_id homeworkId,status,people_number peopleNumber,create_time createTime,update_time updateTime from task_info where id=#{id}")
TaskInfo selectById(String id);
}

@ -0,0 +1,74 @@
package net.educoder.ecsonar.dao;
import net.educoder.ecsonar.model.TaskInfoDetail;
import org.apache.ibatis.annotations.Insert;
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
* @Description:
*/
public interface TaskInfoDetailDao {
/**
*
*
* @param taskInfoDetail
*/
@Insert("insert into task_info_detail(id,task_id,project_name,student_id,name,code_ids) values(#{id},#{taskId},#{projectName},#{studentId},#{name},#{codeIds})")
void insertTaskInfoDetail(TaskInfoDetail taskInfoDetail);
/**
*
*
* @param id
* @param status
*/
@Update("update task_info_detail set status=#{status},update_time=current_timestamp where id=#{id}")
void updateTaskInfoDetailStatus(@Param("id") String id, @Param("status") Integer status);
/**
* taskIdsonar
*
* @param taskId
* @return
*/
@Select("select count(1) from task_info_detail where task_id=#{taskId} and status != 0")
Integer selectCountByTaskId(@Param("taskId") String taskId);
/**
* idTaskInfoDetail
*
* @param id
* @return
*/
@Select("select id,task_id taskId,project_name projectName,student_id studentId,name,code_ids codeIds,status,create_time createTime,update_time updateTime from task_info_detail where id=#{id}")
TaskInfoDetail selectById(String id);
/**
* count
*
* @param taskId
* @param pageSize
* @param offset
* @return
*/
@Select("select count(1) from task_info_detail where task_id=#{taskId} limit #{pageSize} offset #{offset}")
Integer selectTaskInfoDetailPageCount(@Param("taskId") String taskId, @Param("pageSize") Integer pageSize, @Param("offset") Integer offset);
/**
*
*
* @param taskId
* @param pageSize
* @param position
* @return
*/
@Select("select id,task_id taskId,project_name projectName,student_id studentId,name,code_ids codeIds,status,create_time createTime,update_time updateTime from task_info_detail where task_id=#{taskId} limit #{pageSize} offset #{position}")
List<TaskInfoDetail> selectTaskInfoDetailPageList(@Param("taskId") String taskId, @Param("pageSize") Integer pageSize, @Param("position") Integer position);
}

@ -0,0 +1,17 @@
package net.educoder.ecsonar.exception;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class BusinessException extends RuntimeException{
private Integer code;
private String message;
public BusinessException(Integer code, String message){
super(message);
this.code = code;
this.message = message;
}
}

@ -0,0 +1,28 @@
package net.educoder.ecsonar.model;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class GameCodes {
private String code;
private String path;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}

@ -0,0 +1,71 @@
package net.educoder.ecsonar.model;
import java.util.List;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class RollPage<T> {
private static final Integer DEFAULT_PAGE_SIZE = 50;
private Integer pageSize;
private Integer currentPage = 1;
private Integer pageSum = 0;
private Integer recordSum = 0;
private List<T> recordList;
public RollPage() {
pageSize = DEFAULT_PAGE_SIZE;
}
public Integer getPageSum() {
if (this.pageSum == 0) {
this.pageSum = (int) Math.ceil(this.recordSum / this.pageSize) + ((this.recordSum % this.pageSize == 0) ? 0 : 1);
}
return pageSum;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getCurrentPage() {
return currentPage;
}
public void setCurrentPage(Integer currentPage) {
this.currentPage = currentPage;
}
public void setPageSum(Integer pageSum) {
this.pageSum = pageSum;
}
public Integer getRecordSum() {
return recordSum;
}
public void setRecordSum(Integer recordSum) {
this.recordSum = recordSum;
}
public List<T> getRecordList() {
return recordList;
}
public void setRecordList(List<T> recordList) {
this.recordList = recordList;
}
}

@ -0,0 +1,53 @@
package net.educoder.ecsonar.model;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class SonarScannerParam {
/**
* sonar
*/
private String projectKey;
/**
*
*/
private String projectPath;
/**
* c/++ cppcheck
*/
private String cppCheckReportPath;
public SonarScannerParam(String projectKey, String projectPath) {
this.projectKey = projectKey;
this.projectPath = projectPath;
}
public String getProjectKey() {
return projectKey;
}
public void setProjectKey(String projectKey) {
this.projectKey = projectKey;
}
public String getProjectPath() {
return projectPath;
}
public void setProjectPath(String projectPath) {
this.projectPath = projectPath;
}
public String getCppCheckReportPath() {
return cppCheckReportPath;
}
public void setCppCheckReportPath(String cppCheckReportPath) {
this.cppCheckReportPath = cppCheckReportPath;
}
}

@ -0,0 +1,78 @@
package net.educoder.ecsonar.model;
import java.util.Date;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class TaskInfo {
private String id;
private String language;
private String homeworkId;
/**
* 0 1
*/
private Integer status;
private Integer peopleNumber;
private Date createTime;
private Date updateTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getHomeworkId() {
return homeworkId;
}
public void setHomeworkId(String homeworkId) {
this.homeworkId = homeworkId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getPeopleNumber() {
return peopleNumber;
}
public void setPeopleNumber(Integer peopleNumber) {
this.peopleNumber = peopleNumber;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}

@ -0,0 +1,97 @@
package net.educoder.ecsonar.model;
import java.util.Date;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class TaskInfoDetail {
private String id;
private String taskId;
private String projectName;
private String studentId;
private String name;
private String codeIds;
/**
* 0 1 -1
*/
private Integer status;
private Date createTime;
private Date updateTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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 getStudentId() {
return studentId;
}
public void setStudentId(String studentId) {
this.studentId = studentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCodeIds() {
return codeIds;
}
public void setCodeIds(String codeIds) {
this.codeIds = codeIds;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

@ -28,6 +28,24 @@ public class Quality {
*/ */
private String grade; private String grade;
public Quality() {
}
/**
* @param blocker
* @param major
* @param minor
* @param critical
* @param grade A-E
*/
public Quality(Integer blocker, Integer major, Integer minor, Integer critical, String grade) {
this.blocker = blocker;
this.major = major;
this.minor = minor;
this.critical = critical;
this.grade = grade;
}
public Integer getBlocker() { public Integer getBlocker() {
return blocker; return blocker;
} }

@ -0,0 +1,20 @@
package net.educoder.ecsonar.model.api;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class QualityInspect {
private String taskId;
public QualityInspect(String taskId){
this.taskId = taskId;
}
public String getTaskId() {
return taskId;
}
}

@ -1,42 +0,0 @@
package net.educoder.ecsonar.model.api;
import java.util.List;
/**
* @Author: youys
* @Date: 2022/1/17
* @Description:
*/
public class QualityInspectResult {
/**
* id
*/
private String taskId;
/**
*
*/
private List<QualityInspectResultData> dataList;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public List<QualityInspectResultData> getDataList() {
return dataList;
}
public void setDataList(List<QualityInspectResultData> dataList) {
this.dataList = dataList;
}
}

@ -39,7 +39,7 @@ public class QualityInspectResultData {
/** /**
* *
*/ */
private BigDecimal complexity; private String complexity;
/** /**
* *
@ -99,11 +99,11 @@ public class QualityInspectResultData {
this.codeSmall = codeSmall; this.codeSmall = codeSmall;
} }
public BigDecimal getComplexity() { public String getComplexity() {
return complexity; return complexity;
} }
public void setComplexity(BigDecimal complexity) { public void setComplexity(String complexity) {
this.complexity = complexity; this.complexity = complexity;
} }

@ -21,7 +21,7 @@ public class QualityInspectUserDataVO {
/** /**
* id * id
*/ */
private List<Integer> codeIds; private List<Long> codeIds;
public String getStudentId() { public String getStudentId() {
return studentId; return studentId;
@ -39,11 +39,11 @@ public class QualityInspectUserDataVO {
this.name = name; this.name = name;
} }
public List<Integer> getCodeIds() { public List<Long> getCodeIds() {
return codeIds; return codeIds;
} }
public void setCodeIds(List<Integer> codeIds) { public void setCodeIds(List<Long> codeIds) {
this.codeIds = codeIds; this.codeIds = codeIds;
} }
} }

@ -0,0 +1,67 @@
package net.educoder.ecsonar.services;
import net.educoder.ecsonar.config.DynamicDataSourceConfig;
import net.educoder.ecsonar.config.DynamicDataSourceContextHolder;
import net.educoder.ecsonar.dao.CeActivityDao;
import net.educoder.ecsonar.dao.GameCodesDao;
import net.educoder.ecsonar.dao.ProjectDao;
import net.educoder.ecsonar.dao.TaskInfoDetailDao;
import net.educoder.ecsonar.model.GameCodes;
import net.educoder.ecsonar.model.Project;
import net.educoder.ecsonar.model.TaskInfoDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author: youys
* @Date: 2021/12/31
* @Description:
*/
@Service
public class DbOperateService {
@Autowired
private GameCodesDao gameCodesDao;
@Autowired
private CeActivityDao ceActivityDao;
@Autowired
private ProjectDao projectDao;
@Autowired
private TaskInfoDetailDao taskInfoDetailDao;
/**
* idcode
* @param id
* @return
*/
public GameCodes queryGameCodesById(Long id){
DynamicDataSourceContextHolder.setContextKey(DynamicDataSourceConfig.READONLY);
GameCodes gameCode = gameCodesDao.queryOriginalCodeById(id);
DynamicDataSourceContextHolder.removeContextKey();
return gameCode;
}
/**
*
* @param projectName
* @return
*/
public String queryCeActivityStatus(String projectName){
Project project = projectDao.findByName(projectName);
if(project == null ){
return null;
}
return ceActivityDao.queryActivityStatus(project.getProject_uuid());
}
public void updateTaskInfoDetail(String id, Integer status){
taskInfoDetailDao.updateTaskInfoDetailStatus(id, status);
}
}

@ -1,10 +1,34 @@
package net.educoder.ecsonar.services; package net.educoder.ecsonar.services;
import net.educoder.ecsonar.exception.BusinessException;
import net.educoder.ecsonar.dao.TaskInfoDao;
import net.educoder.ecsonar.dao.TaskInfoDetailDao;
import net.educoder.ecsonar.model.Metrics;
import net.educoder.ecsonar.model.RollPage;
import net.educoder.ecsonar.model.TaskInfo;
import net.educoder.ecsonar.model.TaskInfoDetail;
import net.educoder.ecsonar.model.api.Quality;
import net.educoder.ecsonar.model.api.QualityInspect;
import net.educoder.ecsonar.model.api.QualityInspectIsCompleted; import net.educoder.ecsonar.model.api.QualityInspectIsCompleted;
import net.educoder.ecsonar.model.api.QualityInspectResult; import net.educoder.ecsonar.model.api.QualityInspectResultData;
import net.educoder.ecsonar.model.vo.QualityInspectUserDataVO;
import net.educoder.ecsonar.model.vo.QualityInspectVO; import net.educoder.ecsonar.model.vo.QualityInspectVO;
import net.educoder.ecsonar.task.QualityInspectRunnable;
import net.educoder.ecsonar.utils.IdUtils;
import net.educoder.ecsonar.utils.SystemUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
/** /**
* @Author: youys * @Author: youys
* @Date: 2022/1/17 * @Date: 2022/1/17
@ -13,25 +37,170 @@ import org.springframework.stereotype.Service;
@Service @Service
public class QualityInspectService { public class QualityInspectService {
private static final Logger LOGGER = LoggerFactory.getLogger(QualityInspectService.class);
@Autowired
private TaskInfoDao taskInfoDao;
@Autowired
private TaskInfoDetailDao taskInfoDetailDao;
@Autowired
private DbOperateService dbOperateService;
@Autowired
private SonarService sonarService;
@Autowired
private ReportService reportService;
@Autowired
@Qualifier("sonarScannerPool")
private ExecutorService sonarScannerPool;
@Autowired
@Qualifier("sonarQueryResultPool")
private ExecutorService sonarQueryResultPool;
public String qualityInspect(QualityInspectVO qualityInspectVO) { public QualityInspect qualityInspect(QualityInspectVO qualityInspectVO) {
List<QualityInspectUserDataVO> userDatas = qualityInspectVO.getUserDatas();
LOGGER.info("homeworkId:{}{}个人提交了代码", qualityInspectVO.getHomeworkId(), userDatas.size());
return null; if (CollectionUtils.isEmpty(userDatas)) {
throw new BusinessException(2, "用户数据不能为空");
}
TaskInfo taskInfo = new TaskInfo();
taskInfo.setId(IdUtils.nextStrId());
taskInfo.setHomeworkId(qualityInspectVO.getHomeworkId());
taskInfo.setLanguage(qualityInspectVO.getLanguage());
taskInfo.setPeopleNumber(qualityInspectVO.getUserDatas().size());
taskInfoDao.insertTaskInfo(taskInfo);
for (QualityInspectUserDataVO userData : userDatas) {
TaskInfoDetail taskInfoDetail = new TaskInfoDetail();
taskInfoDetail.setId(IdUtils.nextStrId());
taskInfoDetail.setTaskId(taskInfo.getId());
taskInfoDetail.setProjectName(String.format("%s-%s", qualityInspectVO.getHomeworkId(), userData.getStudentId()));
taskInfoDetail.setName(userData.getName());
taskInfoDetail.setStudentId(userData.getStudentId());
taskInfoDetail.setCodeIds(userData.getCodeIds().toString());
taskInfoDetailDao.insertTaskInfoDetail(taskInfoDetail);
QualityInspectRunnable runnable = new QualityInspectRunnable(taskInfo.getId(), qualityInspectVO.getLanguage(),
qualityInspectVO.getHomeworkId(), taskInfoDetail, userData, sonarQueryResultPool);
runnable.setDbOperateService(dbOperateService);
runnable.setSonarService(sonarService);
// 提交任务
sonarScannerPool.execute(runnable);
}
// 提交之后返回taskId
return new QualityInspect(taskInfo.getId());
} }
public QualityInspectResult qualityInspectResultQuery(String taskId) { public RollPage<QualityInspectResultData> qualityInspectResultQuery(Integer pageNum, Integer pageSize, String taskId) {
RollPage<QualityInspectResultData> rollPage = new RollPage();
rollPage.setCurrentPage(pageNum);
rollPage.setPageSize(pageSize);
int offset = (pageNum - 1) * pageSize;
Integer totalCount = taskInfoDetailDao.selectTaskInfoDetailPageCount(taskId, pageSize, offset);
rollPage.setRecordSum(totalCount);
QualityInspectResult result = new QualityInspectResult();
if (totalCount == null || totalCount == 0) {
rollPage.setRecordList(new ArrayList<>());
} else {
List<TaskInfoDetail> taskInfoDetails = taskInfoDetailDao.selectTaskInfoDetailPageList(taskId, pageSize, offset);
return result; List<QualityInspectResultData> resultDataList = new ArrayList<>(taskInfoDetails.size());
rollPage.setRecordList(resultDataList);
// 组装数据
for (TaskInfoDetail taskInfoDetail : taskInfoDetails) {
QualityInspectResultData resultData = new QualityInspectResultData();
resultData.setName(taskInfoDetail.getName());
resultData.setStudentId(taskInfoDetail.getStudentId());
Metrics metrics = reportService.getMetrics(taskInfoDetail.getProjectName());
resultData.setBug(new Quality(metrics.getBlock_bugs(), metrics.getMajor_bugs(), metrics.getMinor_bugs(), metrics.getCritical_bugs(), metrics.getBugs()));
resultData.setVulnerability(new Quality(metrics.getBlock_violations(), metrics.getMajor_violations(), metrics.getMinor_violations(), metrics.getCritical_violations(), metrics.getViolations()));
resultData.setCodeSmall(new Quality(metrics.getBlock_code_smells(), metrics.getMajor_code_smells(), metrics.getMinor_code_smells(), metrics.getCritical_code_smells(), metrics.getCode_smells()));
resultData.setComplexity(metrics.getComplexity());
resultData.setTotalRowNumber(metrics.getLines());
resultData.setQualityScore(calcQualityScore(resultData));
resultDataList.add(resultData);
}
}
return rollPage;
} }
public QualityInspectIsCompleted qualityInspectIsCompleted(String taskId) { public QualityInspectIsCompleted qualityInspectIsCompleted(String taskId) {
QualityInspectIsCompleted completed = new QualityInspectIsCompleted(taskId, 1); TaskInfo taskInfo = taskInfoDao.selectById(taskId);
if (taskInfo == null) {
throw new BusinessException(2, "任务id不存在");
}
if (taskInfo.getStatus() == 1) {
return new QualityInspectIsCompleted(taskId, taskInfo.getStatus());
}
Integer taskNumber = taskInfoDetailDao.selectCountByTaskId(taskInfo.getId());
int completed = taskInfo.getPeopleNumber().equals(taskNumber) ? 1 : 0;
// 数据库未更新状态但sonar任务已经全部执行完更新task_info状态
if (taskInfo.getStatus() == 0 && completed == 1) {
taskInfoDao.updateTaskInfoStatus(taskInfo.getId(), 1);
// 并且删除文件 /tmp/taskId/* /tmp/homeworkId/*
String command = String.format("rm -rf /tmp/%s/* && rm -rf /tmp/%s/*", taskId, taskInfo.getHomeworkId());
SystemUtil.executeAndGetExitStatus(command);
}
QualityInspectIsCompleted qualityInspectIsCompleted = new QualityInspectIsCompleted(taskId, completed);
return qualityInspectIsCompleted;
}
/**
*
* 10 5 3 1
*
* @param resultData
* @return
*/
private BigDecimal calcQualityScore(QualityInspectResultData resultData) {
if (resultData.getTotalRowNumber() <= 0) {
return null;
}
// 100 -(阻断 * 10 + 严重 * 5 + 主要* 3 + 次要 * 1/ 总行数 * 100
Quality bug = resultData.getBug();
BigDecimal bugScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(bug.getBlocker() * 10 + bug.getCritical() * 5 + bug.getMajor() * 3 + bug.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()),2,RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
Quality vulnerability = resultData.getVulnerability();
BigDecimal vulnerabilityScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(vulnerability.getBlocker() * 10 + vulnerability.getCritical() * 5 + vulnerability.getMajor() * 3 + vulnerability.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()),2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
Quality codeSmall = resultData.getCodeSmall();
BigDecimal codeSmallScore = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(codeSmall.getBlocker() * 10 + codeSmall.getCritical() * 5 + codeSmall.getMajor() * 3 + codeSmall.getMinor() * 1).divide(BigDecimal.valueOf(resultData.getTotalRowNumber()),2,RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
return null; // 总得分= bugScore * 0.5 + vulnerabilityScore * 0.3 + codeSmallScore * 0.2
BigDecimal score = bugScore.multiply(BigDecimal.valueOf(0.5)).add(vulnerabilityScore.multiply(BigDecimal.valueOf(0.3))).add(codeSmallScore.multiply(BigDecimal.valueOf(0.2))).setScale(2, RoundingMode.HALF_UP);
return score;
} }
} }

@ -73,9 +73,9 @@ public class ReportService {
metrics.setMinor_bugs(0); metrics.setMinor_bugs(0);
metrics.setMinor_code_smells(0); metrics.setMinor_code_smells(0);
metrics.setMinor_violations(0); metrics.setMinor_violations(0);
metrics.setBugs("A"); metrics.setBugs("-");
metrics.setViolations("A"); metrics.setViolations("-");
metrics.setCode_smells("A"); metrics.setCode_smells("-");
return metrics; return metrics;
} }

@ -1,6 +1,8 @@
package net.educoder.ecsonar.services; package net.educoder.ecsonar.services;
import net.educoder.ecsonar.constant.Constant;
import net.educoder.ecsonar.model.SonarScannerParam;
import net.educoder.ecsonar.model.api.Person; import net.educoder.ecsonar.model.api.Person;
import net.educoder.ecsonar.model.api.SonarRequest; import net.educoder.ecsonar.model.api.SonarRequest;
import net.educoder.ecsonar.task.ReadExcelRunnable; import net.educoder.ecsonar.task.ReadExcelRunnable;
@ -15,15 +17,19 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.*; import java.io.*;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -45,6 +51,55 @@ public class SonarService {
@Autowired @Autowired
private ExecutorService executorService; private ExecutorService executorService;
private ConcurrentHashMap<String, Consumer<SonarScannerParam>> concurrentHashMap = new ConcurrentHashMap(8);
@PostConstruct
public void init() {
concurrentHashMap.put(Constant.JAVA, param -> {
String command = "sonar-scanner " +
"-Dsonar.host.url=" + sonarUrl + " " +
"-Dsonar.sourceEncoding=utf-8 " +
"-Dsonar.projectKey=" + param.getProjectKey() + " " +
"-Dsonar.login=" + sonarToken + " " +
"-Dsonar.java.binaries=./ " +
"-Dsonar.projectBaseDir=" + param.getProjectPath();
SystemUtil.executeAndGetExitStatus(command);
});
concurrentHashMap.put(Constant.PYTHON, param -> {
String command = "sonar-scanner " +
"-Dsonar.host.url=" + sonarUrl + " " +
"-Dsonar.sourceEncoding=utf-8 " +
"-Dsonar.projectKey=" + param.getProjectKey() + " " +
"-Dsonar.login=" + sonarToken + " " +
"-Dsonar.projectBaseDir=" + param.getProjectPath();
SystemUtil.executeAndGetExitStatus(command);
});
concurrentHashMap.put(Constant.C, param -> {
String command = "cppcheck --xml --xml-version=2 --enable=all " + param.getProjectPath() + " 2> " + param.getCppCheckReportPath() +
"&& sonar-scanner " +
"-Dsonar.host.url=" + sonarUrl + " " +
"-Dsonar.sourceEncoding=utf-8 " +
"-Dsonar.projectKey=" + param.getProjectKey() + " " +
"-Dsonar.login=" + sonarToken + " " +
"-Dsonar.cxx.cppcheck.reportPath=" + param.getCppCheckReportPath() + " " +
"-Dsonar.projectBaseDir=" + param.getProjectPath();
SystemUtil.executeAndGetExitStatus(command);
});
concurrentHashMap.put(Constant.CXX, param -> {
String command = "cppcheck --xml --xml-version=2 --enable=all " + param.getProjectPath() + " 2> " + param.getCppCheckReportPath() +
"&& sonar-scanner " +
"-Dsonar.host.url=" + sonarUrl + " " +
"-Dsonar.sourceEncoding=utf-8 " +
"-Dsonar.projectKey=" + param.getProjectKey() + " " +
"-Dsonar.login=" + sonarToken + " " +
"-Dsonar.cxx.cppcheck.reportPath=" + param.getCppCheckReportPath() + " " +
"-Dsonar.projectBaseDir=" + param.getProjectPath();
SystemUtil.executeAndGetExitStatus(command);
});
}
/** /**
* *
* *
@ -59,13 +114,13 @@ public class SonarService {
String savePath = zipSavePath + zipFilename; String savePath = zipSavePath + zipFilename;
//1. 下载文件 //1. 下载文件
if (index==1) { if (index == 1) {
download(zipUrl, savePath); download(zipUrl, savePath);
} }
//2. 解压目录 //2. 解压目录
String extractPath = zipSavePath + key; String extractPath = zipSavePath + key;
if (index==1) { if (index == 1) {
log.info("savePath: {}, extractPath: {}", savePath, extractPath); log.info("savePath: {}, extractPath: {}", savePath, extractPath);
extract(savePath, extractPath); extract(savePath, extractPath);
} }
@ -82,7 +137,7 @@ public class SonarService {
log.info("scan zipSavePath: {}, zipFilename: {}, savePath: {}, extractPath: {}, subPath: {}", zipSavePath, zipFilename, savePath, extractPath, subPath); log.info("scan zipSavePath: {}, zipFilename: {}, savePath: {}, extractPath: {}, subPath: {}", zipSavePath, zipFilename, savePath, extractPath, subPath);
if (!new File(extractPath + subPath).exists()){ if (!new File(extractPath + subPath).exists()) {
throw new Exception("项目文件夹不存在"); throw new Exception("项目文件夹不存在");
} }
@ -119,17 +174,24 @@ public class SonarService {
} }
public void sonar(String language, SonarScannerParam sonarScannerParam) {
Consumer<SonarScannerParam> consumer = concurrentHashMap.get(language);
if (consumer != null) {
log.info("语言:{},projectName:{},path:{}找到了consumer", language, sonarScannerParam.getProjectKey(),sonarScannerParam.getProjectPath());
consumer.accept(sonarScannerParam);
}
}
public void sonar(String projectPath, String key) { public void sonar(String projectPath, String key) {
String command = "cppcheck --xml --xml-version=2 --enable=all "+projectPath+" 2> /tmp/"+key+"-result.xml &&" + String command = "sonar-scanner " +
"source ~/.bash_profile && sonar-scanner " +
"-Dsonar.host.url=" + sonarUrl + " " + "-Dsonar.host.url=" + sonarUrl + " " +
"-Dsonar.sourceEncoding=utf-8 " + "-Dsonar.sourceEncoding=utf-8 " +
"-Dsonar.projectKey=" + key + " " + "-Dsonar.projectKey=" + key + " " +
"-Dsonar.login=" + sonarToken + " " + "-Dsonar.login=" + sonarToken + " " +
"-Dsonar.java.binaries=./ " + "-Dsonar.java.binaries=./ " +
"-Dsonar.cxx.cppcheck.reportPath=/tmp/"+ key+"-result.xml " +
"-Dsonar.projectBaseDir=" + projectPath; "-Dsonar.projectBaseDir=" + projectPath;
log.info("projectPath:{},key:{}, command: {}", projectPath,key, command); log.info("projectPath:{},key:{}, command: {}", projectPath, key, command);
SystemUtil.executeAndGetExitStatus(command); SystemUtil.executeAndGetExitStatus(command);
} }
@ -140,14 +202,14 @@ public class SonarService {
*/ */
private void extract(String zipFile, String extractPath) throws Exception { private void extract(String zipFile, String extractPath) throws Exception {
File extractFile = new File(extractPath); File extractFile = new File(extractPath);
if (extractFile.exists()){ if (extractFile.exists()) {
extractFile.delete(); extractFile.delete();
} }
extractFile.mkdir(); extractFile.mkdir();
SystemUtil.ExecuteResp executeResp = SystemUtil.executeAndGetExitStatus("cd " SystemUtil.ExecuteResp executeResp = SystemUtil.executeAndGetExitStatus("cd "
+ extractPath + extractPath
+ " && "+extractProgramPath+" -encoding GBK " + zipFile); + " && " + extractProgramPath + " -encoding GBK " + zipFile);
} }
/** /**
@ -181,9 +243,10 @@ public class SonarService {
/** /**
* excel * excel
*
* @param excelPath * @param excelPath
*/ */
public void scanExcel(String excelPath){ public void scanExcel(String excelPath) {
int homeworkId = 20210101; int homeworkId = 20210101;
@ -192,7 +255,7 @@ public class SonarService {
Map<String, List<Person>> collect = personList.stream().collect(Collectors.groupingBy(Person::getUid)); Map<String, List<Person>> collect = personList.stream().collect(Collectors.groupingBy(Person::getUid));
collect.forEach((k,v)->{ collect.forEach((k, v) -> {
SonarRequest request = new SonarRequest(); SonarRequest request = new SonarRequest();
request.setHomeworkId(homeworkId); request.setHomeworkId(homeworkId);
request.setPersonList(v); request.setPersonList(v);

@ -0,0 +1,110 @@
package net.educoder.ecsonar.task;
import cn.hutool.core.io.FileUtil;
import net.educoder.ecsonar.constant.Constant;
import net.educoder.ecsonar.model.GameCodes;
import net.educoder.ecsonar.model.SonarScannerParam;
import net.educoder.ecsonar.model.TaskInfoDetail;
import net.educoder.ecsonar.model.vo.QualityInspectUserDataVO;
import net.educoder.ecsonar.services.DbOperateService;
import net.educoder.ecsonar.services.SonarService;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.ExecutorService;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class QualityInspectRunnable implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(QualityInspectRunnable.class);
private String taskId;
public String language;
public String homeworkId;
private QualityInspectUserDataVO userData;
private ExecutorService queryResultPool;
private TaskInfoDetail taskInfoDetail;
private DbOperateService dbOperateService;
private SonarService sonarService;
public QualityInspectRunnable(String taskId, String language, String homeworkId,
TaskInfoDetail taskInfoDetail,
QualityInspectUserDataVO userData,
ExecutorService queryResultPool) {
this.taskId = taskId;
this.language = language;
this.homeworkId = homeworkId;
this.taskInfoDetail = taskInfoDetail;
this.userData = userData;
this.queryResultPool = queryResultPool;
}
@Override
public void run() {
String projectName = String.format("%s-%s", homeworkId, userData.getStudentId());
String path = String.format("/tmp/%s/%s/", homeworkId, projectName);
List<Long> codeIds = userData.getCodeIds();
for (Long codeId : codeIds) {
File file = new File(path);
try {
FileUtils.forceMkdir(file);
} catch (IOException e) {
}
GameCodes gameCodes = dbOperateService.queryGameCodesById(codeId);
FileUtil.writeString(gameCodes.getCode(), path + gameCodes.getPath(), Charset.forName("UTF-8"));
}
// 写完所有文件开始用sonar进行质量分析
SonarScannerParam param = new SonarScannerParam(projectName, path);
if (Constant.C.equalsIgnoreCase(language) || Constant.CXX.equalsIgnoreCase(language)) {
String resultPath = String.format("/tmp/%s", taskId);
File f = new File(resultPath);
if (!f.exists()) {
f.mkdirs();
}
param.setCppCheckReportPath(resultPath + String.format("/%s-result.xml", projectName));
}
// 调用sonar服务
LOGGER.info("projectName:{}, detailId:{} 开始调用sonar分析,语言:{}", projectName,taskInfoDetail.getId(),language);
sonarService.sonar(language, param);
// 提交一个查结果的任务
SonarQueryResultRunnable queryResultRunnable = new SonarQueryResultRunnable(projectName, taskInfoDetail.getId(), dbOperateService);
LOGGER.info("projectName:{}, detailId:{} 提交了查询结果的任务", projectName,taskInfoDetail.getId());
queryResultPool.execute(queryResultRunnable);
}
public DbOperateService getDbOperateService() {
return dbOperateService;
}
public void setDbOperateService(DbOperateService dbOperateService) {
this.dbOperateService = dbOperateService;
}
public SonarService getSonarService() {
return sonarService;
}
public void setSonarService(SonarService sonarService) {
this.sonarService = sonarService;
}
}

@ -0,0 +1,46 @@
package net.educoder.ecsonar.task;
import net.educoder.ecsonar.services.DbOperateService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @Author: youys
* @Date: 2022/1/18
* @Description:
*/
public class SonarQueryResultRunnable implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(SonarQueryResultRunnable.class);
private static final String SUCCESS = "SUCCESS";
private String projectName;
private String detailId;
private DbOperateService dbOperateService;
public SonarQueryResultRunnable(String projectName, String detailId, DbOperateService dbOperateService) {
this.projectName = projectName;
this.detailId = detailId;
this.dbOperateService = dbOperateService;
}
@Override
public void run() {
String status;
while((status = dbOperateService.queryCeActivityStatus(projectName)) == null){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
LOGGER.info("detailId:[{}],sonar还未执行完", detailId);
}
// 查询
LOGGER.info("detailId:[{}], 查询sonar执行状态[{}]", detailId, status);
// 更新状态
dbOperateService.updateTaskInfoDetail(detailId, SUCCESS.equals(status) ? 1 : -1);
}
}

@ -12,4 +12,8 @@ public final class IdUtils {
return idWorker.nextId(); return idWorker.nextId();
} }
public static String nextStrId() {
return String.valueOf(idWorker.nextId());
}
} }

@ -1,11 +1,13 @@
package net.educoder.ecsonar.utils; package net.educoder.ecsonar.utils;
import java.io.Serializable;
/** /**
* @Author: youys * @Author: youys
* @Date: 2022/1/17 * @Date: 2022/1/17
* @Description: * @Description:
*/ */
public class ResponseResult<T> { public class ResponseResult<T> implements Serializable {
private Integer code; private Integer code;
private String msg; private String msg;
@ -21,6 +23,8 @@ public class ResponseResult<T> {
} }
public ResponseResult(T data){ public ResponseResult(T data){
this.code = 1;
this.msg = "";
this.data = data; this.data = data;
} }
@ -29,11 +33,35 @@ public class ResponseResult<T> {
} }
public static ResponseResult success(Object data){ public static <T> ResponseResult success(T data){
return new ResponseResult(data); return new ResponseResult(data);
} }
public static ResponseResult error(String msg){ public static ResponseResult error(String msg){
return new ResponseResult(2,msg); return new ResponseResult(-1,msg);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
} }
} }

@ -1,147 +1,133 @@
package net.educoder.ecsonar.utils; package net.educoder.ecsonar.utils;
/**
* Twitter_Snowflake<br>
* SnowFlake(-):<br>
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 -
* 000000000000 <br>
* 1longJava01id0<br>
* 41()41 - )
* id使IdWorkerstartTime41使69T
* = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
* 1010245datacenterId5workerId<br>
* 1212()4096ID<br>
* 64Long<br>
* SnowFlakeID(IDID)SnowFlake26ID
*/
public class SnowflakeIdWorker { public class SnowflakeIdWorker {
/** 开始时间截 (2019-08-06) */
// ==============================Fields=========================================== private final long twepoch = 1565020800000L;
/** 开始时间截 (2015-01-01) */
private final long twepoch = 1420041600000L; /** 机器id所占的位数 */
private final long workerIdBits = 5L;
/** 机器id所占的位数 */
private final long workerIdBits = 5L; /** 数据标识id所占的位数 */
private final long datacenterIdBits = 5L;
/** 数据标识id所占的位数 */
private final long datacenterIdBits = 5L; /** 支持的最大机器id结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
/** 支持的最大机器id结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
private final long maxWorkerId = -1L ^ (-1L << workerIdBits); /** 支持的最大数据标识id结果是31 */
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
/** 支持的最大数据标识id结果是31 */
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); /** 序列在id中占的位数 */
private final long sequenceBits = 12L;
/** 序列在id中占的位数 */
private final long sequenceBits = 12L; /** 机器ID向左移12位 */
private final long workerIdShift = sequenceBits;
/** 机器ID向左移12位 */
private final long workerIdShift = sequenceBits; /** 数据标识id向左移17位(12+5) */
private final long datacenterIdShift = sequenceBits + workerIdBits;
/** 数据标识id向左移17位(12+5) */
private final long datacenterIdShift = sequenceBits + workerIdBits; /** 时间截向左移22位(5+5+12) */
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
/** 时间截向左移22位(5+5+12) */
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; /** 生成序列的掩码这里为4095 (0b111111111111=0xfff=4095) */
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
/** 生成序列的掩码这里为4095 (0b111111111111=0xfff=4095) */
private final long sequenceMask = -1L ^ (-1L << sequenceBits); /** 工作机器ID(0~31) */
private long workerId;
/** 工作机器ID(0~31) */
private long workerId; /** 数据中心ID(0~31) */
private long datacenterId;
/** 数据中心ID(0~31) */
private long datacenterId; /** 毫秒内序列(0~4095) */
private long sequence = 0L;
/** 毫秒内序列(0~4095) */
private long sequence = 0L; /** 上次生成ID的时间截 */
private long lastTimestamp = -1L;
/** 上次生成ID的时间截 */
private long lastTimestamp = -1L; //==============================Constructors====================
/**
// ==============================Constructors===================================== *
/** * @param workerId ID (0~31)
* * @param datacenterId ID (0~31)
* */
* @param workerId public SnowflakeIdWorker(long workerId, long datacenterId) {
* ID (0~31) if (workerId > maxWorkerId || workerId < 0) {
* @param datacenterId throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
* ID (0~31) }
*/ if (datacenterId > maxDatacenterId || datacenterId < 0) {
public SnowflakeIdWorker(long workerId, long datacenterId) { throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
if (workerId > maxWorkerId || workerId < 0) { }
throw new IllegalArgumentException( this.workerId = workerId;
String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); this.datacenterId = datacenterId;
} }
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException( // ==============================Methods=================================
String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); /**
} * ID (线)
this.workerId = workerId; * @return SnowflakeId
this.datacenterId = datacenterId; */
} public synchronized long nextId() {
long timestamp = timeGen();
// ==============================Methods==========================================
/** //如果当前时间小于上一次ID生成的时间戳说明系统时钟回退过这个时候应当抛出异常
* ID (线) if (timestamp < lastTimestamp) {
* throw new RuntimeException(
* @return SnowflakeId String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
*/ }
public synchronized long nextId() {
long timestamp = timeGen(); //如果是同一时间生成的,则进行毫秒内序列
if (lastTimestamp == timestamp) {
// 如果当前时间小于上一次ID生成的时间戳说明系统时钟回退过这个时候应当抛出异常 sequence = (sequence + 1) & sequenceMask;
if (timestamp < lastTimestamp) { //毫秒内序列溢出
throw new RuntimeException(String.format( if (sequence == 0) {
"Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); //阻塞到下一个毫秒,获得新的时间戳
} timestamp = tilNextMillis(lastTimestamp);
}
// 如果是同一时间生成的,则进行毫秒内序列 }
if (lastTimestamp == timestamp) { //时间戳改变,毫秒内序列重置
sequence = (sequence + 1) & sequenceMask; else {
// 毫秒内序列溢出 sequence = 0L;
if (sequence == 0) { }
// 阻塞到下一个毫秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp); //上次生成ID的时间截
} lastTimestamp = timestamp;
}
// 时间戳改变,毫秒内序列重置 //移位并通过或运算拼到一起组成64位的ID
else { return ((timestamp - twepoch) << timestampLeftShift)
sequence = 0L; | (datacenterId << datacenterIdShift)
} | (workerId << workerIdShift)
| sequence;
// 上次生成ID的时间截 }
lastTimestamp = timestamp;
/**
// 移位并通过或运算拼到一起组成64位的ID *
return ((timestamp - twepoch) << timestampLeftShift) // * @param lastTimestamp ID
| (datacenterId << datacenterIdShift) // * @return
| (workerId << workerIdShift) // */
| sequence; protected long tilNextMillis(long lastTimestamp) {
} long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
/** timestamp = timeGen();
* }
* return timestamp;
* @param lastTimestamp }
* ID
* @return /**
*/ *
protected long tilNextMillis(long lastTimestamp) { * @return ()
long timestamp = timeGen(); */
while (timestamp <= lastTimestamp) { protected long timeGen() {
timestamp = timeGen(); return System.currentTimeMillis();
} }
return timestamp;
} //==============================Test=============================================
/** 测试 */
/** public static void main(String[] args) {
* SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
* for (int i = 0; i < 10; i++) {
* @return () long id = idWorker.nextId();
*/ System.out.println(Long.toBinaryString(id));
protected long timeGen() { System.out.println(id);
return System.currentTimeMillis(); }
} }
} }

@ -4,12 +4,12 @@
#spring.datasource.password=root #spring.datasource.password=root
#spring.datasource.driver-class-name=org.postgresql.Driver #spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.initSize=20
spring.datasource.master.url=jdbc:postgresql://127.0.0.1:5432/sonar7.7 spring.datasource.master.url=jdbc:postgresql://127.0.0.1:5432/sonar7.7
#spring.datasource.url=jdbc:postgresql://117.50.14.123:5432/sonar #spring.datasource.url=jdbc:postgresql://117.50.14.123:5432/sonar
spring.datasource.master.username=root spring.datasource.master.username=root
spring.datasource.master.password=root spring.datasource.master.password=root
spring.datasource.master.driverClass=org.postgresql.Driver spring.datasource.master.driverClassName=org.postgresql.Driver
spring.datasource.readonly.driverClassName=com.mysql.jdbc.Driver spring.datasource.readonly.driverClassName=com.mysql.jdbc.Driver

Loading…
Cancel
Save