Compare commits
9 Commits
manual-ana
...
master
Author | SHA1 | Date |
---|---|---|
youys | 3c6a5734dd | 3 days ago |
youys | 268808fb1b | 4 days ago |
youys | 6fb9fb7db1 | 5 months ago |
youys | e63f429860 | 5 months ago |
youys | bada54f8cb | 2 years ago |
youys | e3c2405364 | 2 years ago |
youys | a3acd04f2c | 2 years ago |
youys | 4874377f89 | 2 years ago |
youys | 6fde10384e | 2 years ago |
@ -0,0 +1,19 @@
|
||||
package net.educoder.ecsonar.dao;
|
||||
|
||||
import net.educoder.ecsonar.model.FileSource;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description:
|
||||
*/
|
||||
public interface FileSourceDao {
|
||||
|
||||
/**
|
||||
* 根据file_uuid查询源文件
|
||||
* @param fileUuid
|
||||
* @return
|
||||
*/
|
||||
FileSource findFileSourceFileUuid(@Param("fileUuid") String fileUuid);
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package net.educoder.ecsonar.dao;
|
||||
|
||||
import net.educoder.ecsonar.model.Issues;
|
||||
import net.educoder.ecsonar.model.dto.DegreeDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description:
|
||||
*/
|
||||
public interface IssuesDao {
|
||||
|
||||
|
||||
/**
|
||||
* 查询issue总记录数
|
||||
* @param projectUuid
|
||||
* @param issueType
|
||||
* @param severity
|
||||
* @return
|
||||
*/
|
||||
Integer getPageIssuesCount(String projectUuid,Integer issueType, String severity);
|
||||
|
||||
/**
|
||||
* 分页查询issue列表
|
||||
* @param projectUuid
|
||||
* @param issueType
|
||||
* @param severity
|
||||
* @param start
|
||||
* @param pageSize
|
||||
* @return
|
||||
*/
|
||||
List<Issues> getPageIssues(String projectUuid,Integer issueType, String severity, Integer start, Integer pageSize);
|
||||
|
||||
|
||||
/**
|
||||
* 查询不同程度的漏洞、缺陷、代码规范数量
|
||||
* @param projectUuid
|
||||
* @param issueType
|
||||
* @return
|
||||
*/
|
||||
DegreeDTO queryDegree(String projectUuid, Integer issueType, Integer metricId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
* @param issueId
|
||||
* @return
|
||||
*/
|
||||
Issues queryById(Long issueId);
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package net.educoder.ecsonar.enums;
|
||||
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description: 分析类型
|
||||
*/
|
||||
public enum AnalyseTypeEnum {
|
||||
|
||||
CodeSmell(1,80),
|
||||
BUG(2, 89),
|
||||
Vulnerability(3,93);
|
||||
|
||||
private Integer type;
|
||||
private Integer metricId;
|
||||
|
||||
|
||||
AnalyseTypeEnum(Integer type, Integer metricId) {
|
||||
this.type = type;
|
||||
this.metricId = metricId;
|
||||
}
|
||||
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Integer getMetricId() {
|
||||
return metricId;
|
||||
}
|
||||
|
||||
public static AnalyseTypeEnum getAnalyseTypeEnum(Integer type) {
|
||||
for (AnalyseTypeEnum analyseType : values()) {
|
||||
if (analyseType.type.equals(type)) {
|
||||
return analyseType;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Not Found AnalyseTypeEnum by type=" + type);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package net.educoder.ecsonar.enums;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description: 严重程度
|
||||
*/
|
||||
public enum DegreeEnum {
|
||||
|
||||
All(0, "ALL", "全部"),
|
||||
Blocker(1, "BLOCKER", "阻断"),
|
||||
Critical(2, "CRITICAL", "严重"),
|
||||
Major(3, "MAJOR", "主要"),
|
||||
Minor(4, "MINOR", "次要"),
|
||||
Info(5, "INFO", "提示");
|
||||
|
||||
|
||||
/**
|
||||
* 传值类型
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 对应数据库类型
|
||||
*/
|
||||
private String value;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String desc;
|
||||
|
||||
DegreeEnum(Integer type, String value, String desc) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
|
||||
public static DegreeEnum getDegreeEnum(Integer type) {
|
||||
for (DegreeEnum de : values()) {
|
||||
if (de.type.equals(type)) {
|
||||
return de;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Not Found DegreeEnum by type=" + type);
|
||||
}
|
||||
|
||||
public static DegreeEnum getDegreeEnumByValue(String value) {
|
||||
for (DegreeEnum de : values()) {
|
||||
if (de.value.equals(value)) {
|
||||
return de;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Not Found DegreeEnum by value=" + value);
|
||||
}
|
||||
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package net.educoder.ecsonar.model;
|
||||
|
||||
import com.google.protobuf.CodedInputStream;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import lombok.Data;
|
||||
import net.educoder.ecsonar.protobuf.DbFileSources;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/9/27
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class FileSource {
|
||||
|
||||
private static final String SIZE_LIMIT_EXCEEDED_EXCEPTION_MESSAGE = "Protocol message was too large. May be malicious. " +
|
||||
"Use CodedInputStream.setSizeLimit() to increase the size limit.";
|
||||
|
||||
private Long id;
|
||||
private String projectUuid;
|
||||
private String fileUuid;
|
||||
private String lineHashes;
|
||||
|
||||
private String srcHash;
|
||||
private byte[] binaryData = new byte[0];
|
||||
private String dataHash;
|
||||
|
||||
public DbFileSources.Data decodeSourceData(byte[] binaryData) {
|
||||
try {
|
||||
return decodeRegularSourceData(binaryData);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(
|
||||
format("Fail to decompress and deserialize source data [id=%s,fileUuid=%s,projectUuid=%s]", id, fileUuid, projectUuid),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
private static DbFileSources.Data decodeRegularSourceData(byte[] binaryData) throws IOException {
|
||||
try (LZ4BlockInputStream lz4Input = new LZ4BlockInputStream(new ByteArrayInputStream(binaryData))) {
|
||||
return DbFileSources.Data.parseFrom(lz4Input);
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
if (SIZE_LIMIT_EXCEEDED_EXCEPTION_MESSAGE.equals(e.getMessage())) {
|
||||
return decodeHugeSourceData(binaryData);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static DbFileSources.Data decodeHugeSourceData(byte[] binaryData) throws IOException {
|
||||
try (LZ4BlockInputStream lz4Input = new LZ4BlockInputStream(new ByteArrayInputStream(binaryData))) {
|
||||
CodedInputStream input = CodedInputStream.newInstance(lz4Input);
|
||||
input.setSizeLimit(Integer.MAX_VALUE);
|
||||
return DbFileSources.Data.parseFrom(input);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package net.educoder.ecsonar.model;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/9/19
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class Issues {
|
||||
|
||||
private Long id;
|
||||
private String kee;
|
||||
private Integer ruleId;
|
||||
private String severity;
|
||||
private String message;
|
||||
private String status;
|
||||
private String projectUuid;
|
||||
private Integer issueType;
|
||||
private Integer lines;
|
||||
private byte[] locations = new byte[0];
|
||||
|
||||
/**
|
||||
* bug名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* bug描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 对应file_sources表的file_uuid
|
||||
* 对应issue表的component_uuid
|
||||
*/
|
||||
private String uuid;
|
||||
|
||||
/**
|
||||
* 语言
|
||||
*/
|
||||
private String language;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package net.educoder.ecsonar.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class AnalyseDetailDTO {
|
||||
|
||||
private DegreeDTO bug;
|
||||
private DegreeDTO vulnerability;
|
||||
private DegreeDTO codeSmall;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package net.educoder.ecsonar.model.dto;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/9/27
|
||||
* @Description: 分析详情列表返回数据
|
||||
*/
|
||||
@Data
|
||||
public class AnalyseDetailListDTO {
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
private String filePath;
|
||||
/**
|
||||
* 行号
|
||||
*/
|
||||
private Integer rowNumber;
|
||||
|
||||
/**
|
||||
* 语言
|
||||
*/
|
||||
private String language;
|
||||
/**
|
||||
* 级别
|
||||
*/
|
||||
private String level;
|
||||
|
||||
/**
|
||||
* 找文件唯一标识
|
||||
*/
|
||||
private String uuid;
|
||||
|
||||
private Integer ruleId;
|
||||
|
||||
private Long issueId;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package net.educoder.ecsonar.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/10/17
|
||||
* @Description: 代码详情
|
||||
*/
|
||||
@Data
|
||||
public class CodeDetailDTO {
|
||||
|
||||
/**
|
||||
* 代码
|
||||
*/
|
||||
private List<FileSourceDTO> codes;
|
||||
/**
|
||||
* 示例代码
|
||||
*/
|
||||
private String example;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 错误消息
|
||||
*/
|
||||
private String errMessage;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package net.educoder.ecsonar.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class DegreeDTO {
|
||||
|
||||
private String levelStr = "A";
|
||||
|
||||
private Integer total = 0;
|
||||
|
||||
/**
|
||||
* 阻断
|
||||
*/
|
||||
private Integer blocker = 0;
|
||||
|
||||
/**
|
||||
* 严重
|
||||
*/
|
||||
private Integer critical = 0;
|
||||
/**
|
||||
* 主要
|
||||
*/
|
||||
private Integer major = 0;
|
||||
|
||||
/**
|
||||
* 次要
|
||||
*/
|
||||
private Integer minor = 0;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package net.educoder.ecsonar.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/9/27
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class FileSourceDTO {
|
||||
|
||||
private Integer rowNumber;
|
||||
private String code;
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package net.educoder.ecsonar.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/22
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class ProblemAnalysisDTO {
|
||||
|
||||
private String title;
|
||||
private String example;
|
||||
|
||||
|
||||
/**
|
||||
* 语言
|
||||
*/
|
||||
private String language;
|
||||
|
||||
/**
|
||||
* 20min
|
||||
*/
|
||||
private String constantIssue;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private String createTime;
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package net.educoder.ecsonar.model.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description: 分析详情列表入参
|
||||
*/
|
||||
@Data
|
||||
public class AnalyseDetailListVO extends PageVO {
|
||||
|
||||
/**
|
||||
* 类型
|
||||
* 1 代码规范
|
||||
* 2 bug
|
||||
* 3 漏洞
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 严重程度
|
||||
* all 全部
|
||||
*/
|
||||
private Integer degree;
|
||||
|
||||
|
||||
@NotBlank(message = "作业id不能为空")
|
||||
private String homeworkId;
|
||||
|
||||
@NotBlank(message = "学号不能为空")
|
||||
private String studentNo;
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package net.educoder.ecsonar.model.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class AnalyseDetailVO {
|
||||
|
||||
@NotBlank(message = "作业id不能为空")
|
||||
private String homeworkId;
|
||||
|
||||
@NotBlank(message = "学号不能为空")
|
||||
private String studentNo;
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package net.educoder.ecsonar.model.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/9/27
|
||||
* @Description: 代码详情请求参数
|
||||
*/
|
||||
@Data
|
||||
public class CodeDetailVO {
|
||||
|
||||
|
||||
private String uuid;
|
||||
private Integer ruleId;
|
||||
private Long issueId;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package net.educoder.ecsonar.model.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2022/12/20
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class PageVO {
|
||||
|
||||
private Integer currentPage = 1;
|
||||
private Integer pageSize = 20;
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,163 +0,0 @@
|
||||
package net.educoder.ecsonar.utils;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.RuntimeUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* @Author: youys
|
||||
* @Date: 2023/5/19
|
||||
* @Description:
|
||||
*/
|
||||
public class RarUtil {
|
||||
|
||||
public static void unrar(String sourceFilePath, String outputDirectory) {
|
||||
String s = RuntimeUtil.execForStr("unar", sourceFilePath,"-o", outputDirectory);
|
||||
System.out.println("result====" + s);
|
||||
}
|
||||
|
||||
|
||||
public static void un7Z(String sourceFilePath, String outputDirectory) {
|
||||
String s = RuntimeUtil.execForStr("unar", sourceFilePath,"-o", outputDirectory);
|
||||
System.out.println("result====" + s);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// unrar("/tmp/20230301/201905962222/20230519153409_wuiol3vn.rar", "/Users/youyongsheng/Desktop/aa");
|
||||
// un7Z("/tmp/20230301/201905962241/20230519153506_i39sv5p2.7z", "/Users/youyongsheng/Desktop/aa");
|
||||
|
||||
// unzip();
|
||||
valid("/tmp/20230402");
|
||||
// removeFullCode("/tmp/20230302");
|
||||
}
|
||||
|
||||
|
||||
public static void unzip(){
|
||||
String sourceDir = "/tmp/20230401";
|
||||
String targetDir = "/tmp/20230402";
|
||||
|
||||
File directory = new File(sourceDir);
|
||||
File[] studentDirs = directory.listFiles();
|
||||
if (studentDirs == null) {
|
||||
System.out.println("No student directories found.");
|
||||
return;
|
||||
}
|
||||
|
||||
int i=0;
|
||||
for (File studentDir : studentDirs) {
|
||||
if (!studentDir.isDirectory()) {
|
||||
System.out.println("111--------------------------------");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
String studentId = studentDir.getName();
|
||||
String studentTargetDir = targetDir + "/" + studentId;
|
||||
|
||||
File[] zipFiles = studentDir.listFiles();
|
||||
// File[] zipFiles = studentDir.listFiles((dir, name) -> name.endsWith(".zip"));
|
||||
// if (zipFiles == null) {
|
||||
// System.out.println("No zip files found for student: " + studentId);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
|
||||
for (File zipFile : zipFiles) {
|
||||
try {
|
||||
if(zipFile.getName().endsWith(".zip")){
|
||||
unzip(zipFile.getAbsolutePath(), studentTargetDir);
|
||||
}else if(zipFile.getName().endsWith(".rar")){
|
||||
unRar(zipFile.getAbsolutePath(), studentTargetDir);
|
||||
}else{
|
||||
RarUtil.un7Z(zipFile.getAbsolutePath(), studentTargetDir);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error occurred while unzipping file: " + zipFile.getName());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("--------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
private static void unzip(String zipFilePath, String targetDir) throws IOException {
|
||||
System.out.println(zipFilePath + " to " + targetDir);
|
||||
ZipUtil.unzip(zipFilePath,targetDir, Charset.forName("GBK"));
|
||||
}
|
||||
|
||||
private static void unRar(String zipFilePath, String targetDir) throws Exception {
|
||||
System.out.println(zipFilePath + " to " + targetDir);
|
||||
RarUtil.unrar(zipFilePath,targetDir);
|
||||
}
|
||||
|
||||
|
||||
public static void valid(String path){
|
||||
File directory = new File(path);
|
||||
File[] studentDirs = directory.listFiles();
|
||||
if (studentDirs == null) {
|
||||
System.out.println("No student directories found.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (File studentDir : studentDirs) {
|
||||
if (studentDir.isDirectory()) {
|
||||
|
||||
File[] files = studentDir.listFiles();
|
||||
if(files == null || files.length == 0){
|
||||
System.out.println(studentDir.getName()+" -> null");
|
||||
}
|
||||
for (File file : files) {
|
||||
System.out.println(studentDir.getName()+" ->" + file.getName());
|
||||
}
|
||||
System.out.println("--------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void removeFullCode(String path){
|
||||
// 删除完整代码
|
||||
File directory = new File(path);
|
||||
File[] studentDirs = directory.listFiles();
|
||||
if (studentDirs == null) {
|
||||
System.out.println("No student directories found.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (File studentDir : studentDirs) {
|
||||
if (studentDir.isDirectory()) {
|
||||
|
||||
String stuNo = studentDir.getName();
|
||||
File[] files = studentDir.listFiles();
|
||||
if(files.length == 2){
|
||||
for (File file : files) {
|
||||
if (file.getName().contains("完整")) {
|
||||
System.out.println(stuNo + "==11===" + file.getAbsolutePath());
|
||||
cn.hutool.core.io.FileUtil.del(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
}else if(files.length == 1){
|
||||
File file = files[0];
|
||||
File[] files1 = file.listFiles();
|
||||
if(files1 != null && files1.length == 2){
|
||||
for (File f : files1) {
|
||||
if (f.getName().contains("完整")) {
|
||||
System.out.println(stuNo + "==22===" + f.getAbsolutePath());
|
||||
FileUtil.del(f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* SonarQube
|
||||
* Copyright (C) 2009-2019 SonarSource SA
|
||||
* mailto:info AT sonarsource DOT com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package net.educoder.ecsonar.utils.html;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
class CharactersReader {
|
||||
|
||||
static final int END_OF_STREAM = -1;
|
||||
|
||||
private final BufferedReader stringBuffer;
|
||||
private final Deque<String> openTags;
|
||||
|
||||
private int currentValue;
|
||||
private int previousValue;
|
||||
private int currentIndex = -1;
|
||||
|
||||
public CharactersReader(BufferedReader stringBuffer) {
|
||||
this.stringBuffer = stringBuffer;
|
||||
this.openTags = new ArrayDeque<>();
|
||||
}
|
||||
|
||||
boolean readNextChar() throws IOException {
|
||||
previousValue = currentValue;
|
||||
currentValue = stringBuffer.read();
|
||||
currentIndex++;
|
||||
return currentValue != END_OF_STREAM;
|
||||
}
|
||||
|
||||
int getCurrentValue() {
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
int getPreviousValue() {
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
int getCurrentIndex() {
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
void registerOpenTag(String textType) {
|
||||
openTags.push(textType);
|
||||
}
|
||||
|
||||
void removeLastOpenTag() {
|
||||
openTags.remove();
|
||||
}
|
||||
|
||||
Deque<String> getOpenTags() {
|
||||
return openTags;
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* SonarQube
|
||||
* Copyright (C) 2009-2019 SonarSource SA
|
||||
* mailto:info AT sonarsource DOT com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package net.educoder.ecsonar.utils.html;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
class DecorationDataHolder {
|
||||
|
||||
private static final String ENTITY_SEPARATOR = ";";
|
||||
private static final String FIELD_SEPARATOR = ",";
|
||||
private static final String SYMBOL_PREFIX = "sym-";
|
||||
private static final String HIGHLIGHTABLE = "sym";
|
||||
|
||||
private List<OpeningHtmlTag> openingTagsEntries;
|
||||
private int openingTagsIndex;
|
||||
private List<Integer> closingTagsOffsets;
|
||||
private int closingTagsIndex;
|
||||
|
||||
DecorationDataHolder() {
|
||||
openingTagsEntries = new ArrayList<>();
|
||||
closingTagsOffsets = new ArrayList<>();
|
||||
}
|
||||
|
||||
void loadSymbolReferences(String symbolsReferences) {
|
||||
String[] symbols = symbolsReferences.split(ENTITY_SEPARATOR);
|
||||
for (String symbol : symbols) {
|
||||
String[] symbolFields = symbol.split(FIELD_SEPARATOR);
|
||||
int declarationStartOffset = Integer.parseInt(symbolFields[0]);
|
||||
int declarationEndOffset = Integer.parseInt(symbolFields[1]);
|
||||
int symbolLength = declarationEndOffset - declarationStartOffset;
|
||||
String[] symbolOccurrences = Arrays.copyOfRange(symbolFields, 2, symbolFields.length);
|
||||
loadSymbolOccurrences(declarationStartOffset, symbolLength, symbolOccurrences);
|
||||
}
|
||||
}
|
||||
|
||||
void loadLineSymbolReferences(String symbolsReferences) {
|
||||
String[] symbols = symbolsReferences.split(ENTITY_SEPARATOR);
|
||||
for (String symbol : symbols) {
|
||||
String[] symbolFields = symbol.split(FIELD_SEPARATOR);
|
||||
int startOffset = Integer.parseInt(symbolFields[0]);
|
||||
int endOffset = Integer.parseInt(symbolFields[1]);
|
||||
int symbolLength = endOffset - startOffset;
|
||||
int symbolId = Integer.parseInt(symbolFields[2]);
|
||||
loadSymbolOccurrences(symbolId, symbolLength, new String[] { Integer.toString(startOffset) });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loadSyntaxHighlightingData(String syntaxHighlightingRules) {
|
||||
String[] rules = syntaxHighlightingRules.split(ENTITY_SEPARATOR);
|
||||
for (String rule : rules) {
|
||||
String[] ruleFields = rule.split(FIELD_SEPARATOR);
|
||||
int startOffset = Integer.parseInt(ruleFields[0]);
|
||||
int endOffset = Integer.parseInt(ruleFields[1]);
|
||||
if (startOffset < endOffset) {
|
||||
insertAndPreserveOrder(new OpeningHtmlTag(startOffset, ruleFields[2]), openingTagsEntries);
|
||||
insertAndPreserveOrder(endOffset, closingTagsOffsets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<OpeningHtmlTag> getOpeningTagsEntries() {
|
||||
return openingTagsEntries;
|
||||
}
|
||||
|
||||
OpeningHtmlTag getCurrentOpeningTagEntry() {
|
||||
return openingTagsIndex < openingTagsEntries.size() ? openingTagsEntries.get(openingTagsIndex) : null;
|
||||
}
|
||||
|
||||
void nextOpeningTagEntry() {
|
||||
openingTagsIndex++;
|
||||
}
|
||||
|
||||
List<Integer> getClosingTagsOffsets() {
|
||||
return closingTagsOffsets;
|
||||
}
|
||||
|
||||
int getCurrentClosingTagOffset() {
|
||||
return closingTagsIndex < closingTagsOffsets.size() ? closingTagsOffsets.get(closingTagsIndex) : -1;
|
||||
}
|
||||
|
||||
void nextClosingTagOffset() {
|
||||
closingTagsIndex++;
|
||||
}
|
||||
|
||||
private void loadSymbolOccurrences(int declarationStartOffset, int symbolLength, String[] symbolOccurrences) {
|
||||
for (String symbolOccurrence : symbolOccurrences) {
|
||||
int occurrenceStartOffset = Integer.parseInt(symbolOccurrence);
|
||||
int occurrenceEndOffset = occurrenceStartOffset + symbolLength;
|
||||
insertAndPreserveOrder(new OpeningHtmlTag(occurrenceStartOffset, SYMBOL_PREFIX + declarationStartOffset + " " + HIGHLIGHTABLE), openingTagsEntries);
|
||||
insertAndPreserveOrder(occurrenceEndOffset, closingTagsOffsets);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertAndPreserveOrder(OpeningHtmlTag newEntry, List<OpeningHtmlTag> openingHtmlTags) {
|
||||
int insertionIndex = 0;
|
||||
Iterator<OpeningHtmlTag> tagIterator = openingHtmlTags.iterator();
|
||||
while (tagIterator.hasNext() && tagIterator.next().getStartOffset() <= newEntry.getStartOffset()) {
|
||||
insertionIndex++;
|
||||
}
|
||||
openingHtmlTags.add(insertionIndex, newEntry);
|
||||
}
|
||||
|
||||
private void insertAndPreserveOrder(int newOffset, List<Integer> orderedOffsets) {
|
||||
int insertionIndex = 0;
|
||||
Iterator<Integer> entriesIterator = orderedOffsets.iterator();
|
||||
while (entriesIterator.hasNext() && entriesIterator.next() <= newOffset) {
|
||||
insertionIndex++;
|
||||
}
|
||||
orderedOffsets.add(insertionIndex, newOffset);
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* SonarQube
|
||||
* Copyright (C) 2009-2019 SonarSource SA
|
||||
* mailto:info AT sonarsource DOT com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package net.educoder.ecsonar.utils.html;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 给代码增加样式
|
||||
*/
|
||||
public final class HtmlSourceDecorator {
|
||||
|
||||
private static volatile HtmlSourceDecorator htmlSourceDecorator = null;
|
||||
|
||||
private HtmlSourceDecorator() {
|
||||
}
|
||||
|
||||
public static HtmlSourceDecorator getInstance() {
|
||||
if (htmlSourceDecorator == null) {
|
||||
synchronized (HtmlSourceDecorator.class) {
|
||||
if (htmlSourceDecorator == null) {
|
||||
htmlSourceDecorator = new HtmlSourceDecorator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return htmlSourceDecorator;
|
||||
}
|
||||
|
||||
public String getDecoratedSourceAsHtml(@NotNull String sourceLine, @NotNull String highlighting, @NotNull String symbols) {
|
||||
if (sourceLine == null) {
|
||||
return null;
|
||||
}
|
||||
DecorationDataHolder decorationDataHolder = new DecorationDataHolder();
|
||||
if (StringUtils.isNotBlank(highlighting)) {
|
||||
decorationDataHolder.loadSyntaxHighlightingData(highlighting);
|
||||
}
|
||||
if (StringUtils.isNotBlank(symbols)) {
|
||||
decorationDataHolder.loadLineSymbolReferences(symbols);
|
||||
}
|
||||
HtmlTextDecorator textDecorator = new HtmlTextDecorator();
|
||||
List<String> decoratedSource = textDecorator.decorateTextWithHtml(sourceLine, decorationDataHolder, 1, 1);
|
||||
if (decoratedSource == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (decoratedSource.isEmpty()) {
|
||||
return "";
|
||||
} else {
|
||||
return decoratedSource.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* SonarQube
|
||||
* Copyright (C) 2009-2019 SonarSource SA
|
||||
* mailto:info AT sonarsource DOT com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package net.educoder.ecsonar.utils.html;
|
||||
|
||||
import com.google.common.io.Closeables;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
|
||||
@Slf4j
|
||||
public class HtmlTextDecorator {
|
||||
|
||||
static final char CR_END_OF_LINE = '\r';
|
||||
static final char LF_END_OF_LINE = '\n';
|
||||
static final char HTML_OPENING = '<';
|
||||
static final char HTML_CLOSING = '>';
|
||||
static final char AMPERSAND = '&';
|
||||
static final String ENCODED_HTML_OPENING = "<";
|
||||
static final String ENCODED_HTML_CLOSING = ">";
|
||||
static final String ENCODED_AMPERSAND = "&";
|
||||
|
||||
List<String> decorateTextWithHtml(String text, DecorationDataHolder decorationDataHolder) {
|
||||
return decorateTextWithHtml(text, decorationDataHolder, null, null);
|
||||
}
|
||||
|
||||
List<String> decorateTextWithHtml(String text, DecorationDataHolder decorationDataHolder, @Nullable Integer from, @Nullable Integer to) {
|
||||
|
||||
StringBuilder currentHtmlLine = new StringBuilder();
|
||||
List<String> decoratedHtmlLines = newArrayList();
|
||||
int currentLine = 1;
|
||||
|
||||
BufferedReader stringBuffer = null;
|
||||
try {
|
||||
stringBuffer = new BufferedReader(new StringReader(text));
|
||||
|
||||
CharactersReader charsReader = new CharactersReader(stringBuffer);
|
||||
|
||||
while (charsReader.readNextChar()) {
|
||||
if (shouldStop(currentLine, to)) {
|
||||
break;
|
||||
}
|
||||
if (shouldStartNewLine(charsReader)) {
|
||||
if (canAddLine(currentLine, from)) {
|
||||
decoratedHtmlLines.add(currentHtmlLine.toString());
|
||||
}
|
||||
currentLine++;
|
||||
currentHtmlLine = new StringBuilder();
|
||||
}
|
||||
addCharToCurrentLine(charsReader, currentHtmlLine, decorationDataHolder);
|
||||
}
|
||||
|
||||
closeCurrentSyntaxTags(charsReader, currentHtmlLine);
|
||||
|
||||
if (shouldStartNewLine(charsReader)) {
|
||||
addLine(decoratedHtmlLines, currentHtmlLine.toString(), currentLine, from, to);
|
||||
currentLine++;
|
||||
addLine(decoratedHtmlLines, "", currentLine, from, to);
|
||||
} else if (currentHtmlLine.length() > 0) {
|
||||
addLine(decoratedHtmlLines, currentHtmlLine.toString(), currentLine, from, to);
|
||||
}
|
||||
|
||||
} catch (IOException exception) {
|
||||
String errorMsg = "An exception occurred while highlighting the syntax of one of the project's files";
|
||||
log.error(errorMsg);
|
||||
throw new IllegalStateException(errorMsg, exception);
|
||||
} finally {
|
||||
Closeables.closeQuietly(stringBuffer);
|
||||
}
|
||||
|
||||
return decoratedHtmlLines;
|
||||
}
|
||||
|
||||
private void addCharToCurrentLine(CharactersReader charsReader, StringBuilder currentHtmlLine, DecorationDataHolder decorationDataHolder) {
|
||||
if (shouldStartNewLine(charsReader)) {
|
||||
if (shouldReopenPendingTags(charsReader)) {
|
||||
reopenCurrentSyntaxTags(charsReader, currentHtmlLine);
|
||||
}
|
||||
}
|
||||
|
||||
int numberOfTagsToClose = getNumberOfTagsToClose(charsReader.getCurrentIndex(), decorationDataHolder);
|
||||
closeCompletedTags(charsReader, numberOfTagsToClose, currentHtmlLine);
|
||||
|
||||
if (shouldClosePendingTags(charsReader)) {
|
||||
closeCurrentSyntaxTags(charsReader, currentHtmlLine);
|
||||
}
|
||||
|
||||
Collection<String> tagsToOpen = getTagsToOpen(charsReader.getCurrentIndex(), decorationDataHolder);
|
||||
openNewTags(charsReader, tagsToOpen, currentHtmlLine);
|
||||
|
||||
if (shouldAppendCharToHtmlOutput(charsReader)) {
|
||||
char currentChar = (char) charsReader.getCurrentValue();
|
||||
currentHtmlLine.append(normalize(currentChar));
|
||||
}
|
||||
}
|
||||
|
||||
private static void addLine(List<String> decoratedHtmlLines, String line, int currentLine, @Nullable Integer from, @Nullable Integer to) {
|
||||
if (canAddLine(currentLine, from) && !shouldStop(currentLine, to)) {
|
||||
decoratedHtmlLines.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean canAddLine(int currentLine, @Nullable Integer from) {
|
||||
return from == null || currentLine >= from;
|
||||
}
|
||||
|
||||
private static boolean shouldStop(int currentLine, @Nullable Integer to) {
|
||||
return to != null && to < currentLine;
|
||||
}
|
||||
|
||||
private char[] normalize(char currentChar) {
|
||||
char[] normalizedChars;
|
||||
if (currentChar == HTML_OPENING) {
|
||||
normalizedChars = ENCODED_HTML_OPENING.toCharArray();
|
||||
} else if (currentChar == HTML_CLOSING) {
|
||||
normalizedChars = ENCODED_HTML_CLOSING.toCharArray();
|
||||
} else if (currentChar == AMPERSAND) {
|
||||
normalizedChars = ENCODED_AMPERSAND.toCharArray();
|
||||
} else {
|
||||
normalizedChars = new char[] {currentChar};
|
||||
}
|
||||
return normalizedChars;
|
||||
}
|
||||
|
||||
private boolean shouldAppendCharToHtmlOutput(CharactersReader charsReader) {
|
||||
return charsReader.getCurrentValue() != CR_END_OF_LINE && charsReader.getCurrentValue() != LF_END_OF_LINE;
|
||||
}
|
||||
|
||||
private int getNumberOfTagsToClose(int currentIndex, DecorationDataHolder dataHolder) {
|
||||
int numberOfTagsToClose = 0;
|
||||
|
||||
while (currentIndex == dataHolder.getCurrentClosingTagOffset()) {
|
||||
numberOfTagsToClose++;
|
||||
dataHolder.nextClosingTagOffset();
|
||||
}
|
||||
return numberOfTagsToClose;
|
||||
}
|
||||
|
||||
private Collection<String> getTagsToOpen(int currentIndex, DecorationDataHolder dataHolder) {
|
||||
Collection<String> tagsToOpen = newArrayList();
|
||||
while (dataHolder.getCurrentOpeningTagEntry() != null && currentIndex == dataHolder.getCurrentOpeningTagEntry().getStartOffset()) {
|
||||
tagsToOpen.add(dataHolder.getCurrentOpeningTagEntry().getCssClass());
|
||||
dataHolder.nextOpeningTagEntry();
|
||||
}
|
||||
return tagsToOpen;
|
||||
}
|
||||
|
||||
private boolean shouldClosePendingTags(CharactersReader charactersReader) {
|
||||
return charactersReader.getCurrentValue() == CR_END_OF_LINE
|
||||
|| (charactersReader.getCurrentValue() == LF_END_OF_LINE && charactersReader.getPreviousValue() != CR_END_OF_LINE)
|
||||
|| (charactersReader.getCurrentValue() == CharactersReader.END_OF_STREAM && charactersReader.getPreviousValue() != LF_END_OF_LINE);
|
||||
}
|
||||
|
||||
private boolean shouldReopenPendingTags(CharactersReader charactersReader) {
|
||||
return (charactersReader.getPreviousValue() == LF_END_OF_LINE && charactersReader.getCurrentValue() != LF_END_OF_LINE)
|
||||
|| (charactersReader.getPreviousValue() == CR_END_OF_LINE && charactersReader.getCurrentValue() != CR_END_OF_LINE
|
||||
&& charactersReader.getCurrentValue() != LF_END_OF_LINE);
|
||||
}
|
||||
|
||||
private boolean shouldStartNewLine(CharactersReader charactersReader) {
|
||||
return charactersReader.getPreviousValue() == LF_END_OF_LINE
|
||||
|| (charactersReader.getPreviousValue() == CR_END_OF_LINE && charactersReader.getCurrentValue() != LF_END_OF_LINE);
|
||||
}
|
||||
|
||||
private void closeCompletedTags(CharactersReader charactersReader, int numberOfTagsToClose,
|
||||
StringBuilder decoratedText) {
|
||||
for (int i = 0; i < numberOfTagsToClose; i++) {
|
||||
injectClosingHtml(decoratedText);
|
||||
charactersReader.removeLastOpenTag();
|
||||
}
|
||||
}
|
||||
|
||||
private void openNewTags(CharactersReader charactersReader, Collection<String> tagsToOpen,
|
||||
StringBuilder decoratedText) {
|
||||
for (String tagToOpen : tagsToOpen) {
|
||||
injectOpeningHtmlForRule(tagToOpen, decoratedText);
|
||||
charactersReader.registerOpenTag(tagToOpen);
|
||||
}
|
||||
}
|
||||
|
||||
private void closeCurrentSyntaxTags(CharactersReader charactersReader, StringBuilder decoratedText) {
|
||||
for (int i = 0; i < charactersReader.getOpenTags().size(); i++) {
|
||||
injectClosingHtml(decoratedText);
|
||||
}
|
||||
}
|
||||
|
||||
private void reopenCurrentSyntaxTags(CharactersReader charactersReader, StringBuilder decoratedText) {
|
||||
for (String tags : charactersReader.getOpenTags()) {
|
||||
injectOpeningHtmlForRule(tags, decoratedText);
|
||||
}
|
||||
}
|
||||
|
||||
private void injectOpeningHtmlForRule(String textType, StringBuilder decoratedText) {
|
||||
decoratedText.append("<span class=\"").append(textType).append("\">");
|
||||
}
|
||||
|
||||
private void injectClosingHtml(StringBuilder decoratedText) {
|
||||
decoratedText.append("</span>");
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* SonarQube
|
||||
* Copyright (C) 2009-2019 SonarSource SA
|
||||
* mailto:info AT sonarsource DOT com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
package net.educoder.ecsonar.utils.html;
|
||||
|
||||
class OpeningHtmlTag {
|
||||
|
||||
private final int startOffset;
|
||||
private final String cssClass;
|
||||
|
||||
OpeningHtmlTag(int startOffset, String cssClass) {
|
||||
this.startOffset = startOffset;
|
||||
this.cssClass = cssClass;
|
||||
}
|
||||
|
||||
int getStartOffset() {
|
||||
return startOffset;
|
||||
}
|
||||
|
||||
String getCssClass() {
|
||||
return cssClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return compareTo((OpeningHtmlTag) o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = startOffset;
|
||||
result = 31 * result + (cssClass != null ? cssClass.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean compareTo(OpeningHtmlTag otherTag) {
|
||||
if (startOffset != otherTag.startOffset) {
|
||||
return false;
|
||||
}
|
||||
return (cssClass != null) ? cssClass.equals(otherTag.cssClass) : (otherTag.cssClass == null);
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="net.educoder.ecsonar.dao.FileSourceDao">
|
||||
|
||||
|
||||
<select id="findFileSourceFileUuid" parameterType="java.lang.String" resultType="net.educoder.ecsonar.model.FileSource">
|
||||
select
|
||||
id,
|
||||
project_uuid as projectUuid,
|
||||
file_uuid as fileUuid,
|
||||
binary_data as binaryData,
|
||||
line_hashes as lineHashes,
|
||||
data_hash as dataHash,
|
||||
src_hash as srcHash
|
||||
from file_sources where file_uuid=#{fileUuid,jdbcType=VARCHAR}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="net.educoder.ecsonar.dao.IssuesDao">
|
||||
|
||||
|
||||
<select id="getPageIssuesCount" resultType="java.lang.Integer">
|
||||
select
|
||||
count(1)
|
||||
from issues i
|
||||
inner join rules r on i.rule_id =r.id
|
||||
inner join projects p on p.uuid =i.component_uuid
|
||||
where i.project_uuid = #{projectUuid,jdbcType=VARCHAR}
|
||||
and i.status='OPEN'
|
||||
and p.root_uuid =#{projectUuid,jdbcType=VARCHAR} and p.uuid !=#{projectUuid,jdbcType=VARCHAR} and p."scope" ='FIL'
|
||||
<if test="issueType != null">
|
||||
and i.issue_type=#{issueType,jdbcType=INTEGER}
|
||||
</if>
|
||||
<if test="severity != null">
|
||||
and i.severity=#{severity,jdbcType=VARCHAR}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="getPageIssues" resultType="net.educoder.ecsonar.model.Issues">
|
||||
select
|
||||
i.id,i.kee,i.rule_id ruleId,i.severity,i.status,i.project_uuid projectUuid,i.issue_type issueType,i.locations,i.line lines,r.name,r.description,r.language,p.path,p.uuid,i.message
|
||||
from issues i
|
||||
inner join rules r on i.rule_id =r.id
|
||||
inner join projects p on p.uuid =i.component_uuid
|
||||
where i.project_uuid = #{projectUuid,jdbcType=VARCHAR}
|
||||
and i.status='OPEN'
|
||||
and p.root_uuid =#{projectUuid,jdbcType=VARCHAR} and p.uuid !=#{projectUuid,jdbcType=VARCHAR} and p."scope" ='FIL'
|
||||
<if test="issueType != null">
|
||||
and i.issue_type=#{issueType,jdbcType=INTEGER}
|
||||
</if>
|
||||
<if test="severity != null">
|
||||
and i.severity=#{severity,jdbcType=VARCHAR}
|
||||
</if>
|
||||
limit #{pageSize} offset #{start}
|
||||
</select>
|
||||
|
||||
<select id="queryDegree" resultType="net.educoder.ecsonar.model.dto.DegreeDTO">
|
||||
select
|
||||
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and status='OPEN' and severity != 'INFO') total,
|
||||
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and severity = 'MAJOR' and status='OPEN') major,
|
||||
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and severity = 'MINOR' and status='OPEN') minor,
|
||||
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and severity = 'BLOCKER' and status='OPEN') blocker,
|
||||
(select count(1) from issues i where project_uuid =#{projectUuid} and issue_type=#{issueType} and severity = 'CRITICAL' and status='OPEN') critical,
|
||||
(select text_value from project_measures i where component_uuid =#{projectUuid} and metric_id = #{metricId} order by id desc limit 1) levelStr
|
||||
</select>
|
||||
|
||||
|
||||
<select id="queryById" parameterType="java.lang.Long" resultType="net.educoder.ecsonar.model.Issues">
|
||||
select i.id,i.kee,i.rule_id ruleId,i.severity,i.status,i.project_uuid projectUuid,i.issue_type issueType,i.locations,i.line lines,i.message from issues i where id=#{issueId}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="net.educoder.ecsonar.dao.ProjectDao">
|
||||
|
||||
|
||||
<select id="findRuleById" parameterType="java.lang.Integer" resultType="net.educoder.ecsonar.model.Rule">
|
||||
select
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
language,
|
||||
def_remediation_base_effort defRemediationBaseEffort,
|
||||
system_tags tags,
|
||||
created_at createTime
|
||||
from rules where id=#{id,jdbcType=INTEGER}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
@ -0,0 +1,41 @@
|
||||
// SonarQube, open source software quality management tool.
|
||||
// Copyright (C) 2008-2016 SonarSource
|
||||
// mailto:contact AT sonarsource DOT com
|
||||
//
|
||||
// SonarQube is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// SonarQube is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package sonarqube.db.commons;
|
||||
|
||||
// The java package can be changed without breaking compatibility.
|
||||
// it impacts only the generated Java code.
|
||||
option java_package = "net.educoder.quality.protobuf";
|
||||
option optimize_for = SPEED;
|
||||
|
||||
// Lines start at 1 and line offsets start at 0
|
||||
message TextRange {
|
||||
// Start line. Should never be absent
|
||||
optional int32 start_line = 1;
|
||||
|
||||
// End line (inclusive). Absent means it is same as start line
|
||||
optional int32 end_line = 2;
|
||||
|
||||
// If absent it means range starts at the first offset of start line
|
||||
optional int32 start_offset = 3;
|
||||
|
||||
// If absent it means range ends at the last offset of end line
|
||||
optional int32 end_offset = 4;
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
SonarQube, open source software quality management tool.
|
||||
Copyright (C) 2008-2016 SonarSource
|
||||
mailto:contact AT sonarsource DOT com
|
||||
|
||||
SonarQube is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
SonarQube is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// Structure of db column FILE_SOURCES.BINARY_DATA
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
// Package must not be changed for backward-compatibility
|
||||
// with the DB rows inserted in DB before 5.2
|
||||
package org.sonar.server.source.db;
|
||||
|
||||
// The java package can be changed without breaking compatibility.
|
||||
// it impacts only the generated Java code.
|
||||
option java_package = "net.educoder.quality.protobuf";
|
||||
option optimize_for = SPEED;
|
||||
|
||||
message Line {
|
||||
optional int32 line = 1;
|
||||
optional string source = 2;
|
||||
|
||||
// SCM
|
||||
optional string scm_revision = 3;
|
||||
optional string scm_author = 4;
|
||||
optional int64 scm_date = 5;
|
||||
|
||||
// Deprecated fields in 6.2 (has been deprecated when merging coverage into a single metric)
|
||||
// They are still used to read coverage info from sources that have not be re-analyzed
|
||||
optional int32 deprecated_ut_line_hits = 6;
|
||||
optional int32 deprecated_ut_conditions = 7;
|
||||
optional int32 deprecated_ut_covered_conditions = 8;
|
||||
optional int32 deprecated_it_line_hits = 9;
|
||||
optional int32 deprecated_it_conditions = 10;
|
||||
optional int32 deprecated_it_covered_conditions = 11;
|
||||
optional int32 deprecated_overall_line_hits = 12;
|
||||
optional int32 deprecated_overall_conditions = 13;
|
||||
optional int32 deprecated_overall_covered_conditions = 14;
|
||||
|
||||
optional string highlighting = 15;
|
||||
optional string symbols = 16;
|
||||
repeated int32 duplication = 17 [packed = true];
|
||||
|
||||
// coverage info (since 6.2)
|
||||
optional int32 line_hits = 18;
|
||||
optional int32 conditions = 19;
|
||||
optional int32 covered_conditions = 20;
|
||||
|
||||
optional bool is_new_line = 21;
|
||||
}
|
||||
|
||||
message Range {
|
||||
optional int32 startOffset = 1;
|
||||
optional int32 endOffset = 2;
|
||||
}
|
||||
|
||||
// TODO should be dropped as it prevents streaming
|
||||
message Data {
|
||||
repeated Line lines = 1;
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
// SonarQube, open source software quality management tool.
|
||||
// Copyright (C) 2008-2016 SonarSource
|
||||
// mailto:contact AT sonarsource DOT com
|
||||
//
|
||||
// SonarQube is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// SonarQube is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
// Structure of table ISSUES
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package sonarqube.db.issues;
|
||||
|
||||
import "db-commons.proto";
|
||||
|
||||
// The java package can be changed without breaking compatibility.
|
||||
// it impacts only the generated Java code.
|
||||
option java_package = "net.educoder.quality.protobuf";
|
||||
option optimize_for = SPEED;
|
||||
|
||||
message Locations {
|
||||
optional sonarqube.db.commons.TextRange text_range = 1;
|
||||
repeated Flow flow = 2;
|
||||
}
|
||||
|
||||
message Flow {
|
||||
repeated Location location = 1;
|
||||
}
|
||||
|
||||
message Location {
|
||||
optional string component_id = 1;
|
||||
// Only when component is a file. Can be empty for a file if this is an issue global to the file.
|
||||
optional sonarqube.db.commons.TextRange text_range = 2;
|
||||
optional string msg = 3;
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
SonarQube, open source software quality management tool.
|
||||
Copyright (C) 2008-2016 SonarSource
|
||||
mailto:contact AT sonarsource DOT com
|
||||
|
||||
SonarQube is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
SonarQube is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// Structure of db column PROJECT_BRANCHES.PULL_REQUEST_DATA
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package sonarqube.db.project_branches;
|
||||
|
||||
// The java package can be changed without breaking compatibility.
|
||||
// it impacts only the generated Java code.
|
||||
option java_package = "net.educoder.quality.protobuf";
|
||||
option optimize_for = SPEED;
|
||||
|
||||
message PullRequestData {
|
||||
string branch = 1;
|
||||
string title = 2;
|
||||
string url = 3;
|
||||
|
||||
map<string, string> attributes = 4;
|
||||
|
||||
string target = 5;
|
||||
}
|
Binary file not shown.
Loading…
Reference in new issue