Commit 87674a61 authored by Pierre-Yves Gibello's avatar Pierre-Yves Gibello
Browse files

Merge branch 'master' into 'update-ow2-project-conf'

# Conflicts:
#   data-collection/conf/ow2_projects.cfg.dist
#   data-collection/src/test/resources/ow2_projects.cfg
parents 781f2a18 c8107e8d
Pipeline #12630 passed with stages
in 3 minutes and 51 seconds
......@@ -112,7 +112,7 @@ $ mvn clean install
$ mvn jetty:run
```
The webapp is then available at http://localhost:8080 .
The webapp is then available at http://localhost:8080/index.jsp .
## Automate data collection and database feeding
......
......@@ -12,7 +12,7 @@ outputDir: </MRL/data/collection/directory/full/path>
include: </MRL/data/collection/credentials/configuration/file/full/path>
# Scanned projects list
projects: asm, authzforce, clif, docdoku, fractal, fusiondirectory, glpi, imixs-workflow, joram, knowage, lemonldap-ng, lutece, ocsinventory, proactive, rocket-chat, sat4j, seedstack, sympa, spoon, telosys, waarp, weblab, xwiki, zenroom
projects: asm, authzforce, clif, docdoku, fusiondirectory, glpi, imixs-workflow, jeka, joram, knowage, lemonldap-ng, lutece, ocsinventory, proactive, rocket-chat, sat4j, seedstack, sympa, spoon, telosys, waarp, weblab, xwiki, zenroom
# Data access configuration, for each listed project
......@@ -50,15 +50,6 @@ docdoku.scancode: https://gitlab.ow2.org/ow2/oscar/docdoku/-/jobs/artifacts/mast
docdoku.omm: https://projects.ow2.org/rest/wikis/projects/spaces/docdoku/pages/omm3/objects/ow2.Omm3/0/properties
docdoku.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/docdoku/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
# Fractal (missing data)
fractal.repo: https://gitlab.ow2.org/fractal/fractal
fractal.issues.endpoint: https://gitlab.ow2.org/api/v4/projects
fractal.issues.project: 214
fractal.sonarqube: Fractal:Juliac
##fractal.scancode:
fractal.omm: https://projects.ow2.org/rest/wikis/projects/spaces/fractal/pages/omm3/objects/ow2.Omm3/0/properties
fractal.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/fractal/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
# FusionDirectory (complete)
fusiondirectory.repo: https://github.com/fusiondirectory/fusiondirectory
fusiondirectory.issues.endpoint: https://api.github.com/repos/fusiondirectory/fusiondirectory
......@@ -73,7 +64,7 @@ fusiondirectory.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/fusiond
glpi.repo: https://github.com/glpi-project/glpi
glpi.issues.endpoint: https://api.github.com/repos/glpi-project/glpi
##glpi.sonarqube:
##glpi.scancode:
glpi.scancode: https://gitlab.ow2.org/ow2/oscar/glpi/-/jobs/artifacts/master/raw/scancode-glpi.json?job=scancode
glpi.omm: https://projects.ow2.org/rest/wikis/projects/spaces/glpi/pages/omm3/objects/ow2.Omm3/0/properties
glpi.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/glpi/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
......@@ -85,6 +76,14 @@ imixs-workflow.scancode: https://gitlab.ow2.org/ow2/oscar/imixs-workflow/-/jobs/
imixs-workflow.omm: https://projects.ow2.org/rest/wikis/projects/spaces/imixs-workflow/pages/omm3/objects/ow2.Omm3/0/properties
imixs-workflow.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/imixs-workflow/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
# Jeka (missing data)
jeka.repo: https://gitlab.ow2.org/jeka/jeka
jeka.issues.endpoint: https://api.github.com/repos/jerkar/jeka
#jeka.sonarqube:
jeka.scancode: https://gitlab.ow2.org/ow2/oscar/jeka/-/jobs/artifacts/master/raw/scancode-jeka.json?job=scancode
#jeka.omm: https://projects.ow2.org/rest/wikis/projects/spaces/jeka/pages/omm3/objects/ow2.Omm3/0/properties
#jeka.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/jeka/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
# Joram (complete)
joram.repo: https://gitlab.ow2.org/joram/joram
joram.issues.endpoint: https://gitlab.ow2.org/api/v4/projects
......@@ -127,19 +126,17 @@ lutece.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/lutece/pages/MKT
ocsinventory.repo: https://github.com/OCSInventory-NG/OCSInventory-Server
ocsinventory.issues.endpoint: https://api.github.com/repos/OCSInventory-NG/OCSInventory-Server
##ocsinventory.sonarqube:
##ocsinventory.scancode:
ocsinventory.scancode: https://gitlab.ow2.org/ow2/oscar/ocsinventory/-/jobs/artifacts/master/raw/scancode-OCSInventory-Server.json?job=scancode
ocsinventory.omm: https://projects.ow2.org/rest/wikis/projects/spaces/ocsinventory/pages/omm3/objects/ow2.Omm3/0/properties
ocsinventory.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/ocsinventory/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
## TODO: complete Prelude and add to list of scanned projects
# Prelude (missing data)
# TODO check repo is really Gitlab ??
prelude.repo: https://gitlab.ow2.org/prelude
# TODO check issues system is really Gitlab ??
prelude.issues.endpoint: https://gitlab.ow2.org/api/v4/groups
prelude.issues.project: 1127
prelude.repo: https://github.com/Prelude-SIEM/libprelude
# TODO support Redmine issue tracker https://www.prelude-siem.org/projects/libpreludedb/issues
##prelude.issues.endpoint:
##prelude.sonarqube:
##prelude.scancode:
prelude.scancode: https://gitlab.ow2.org/ow2/oscar/prelude/-/jobs/artifacts/master/raw/scancode-libprelude.json?job=scancode
prelude.omm: https://projects.ow2.org/rest/wikis/projects/spaces/prelude/pages/omm3/objects/ow2.Omm3/0/properties
prelude.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/prelude/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
......@@ -155,7 +152,7 @@ proactive.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/proactive/pag
rocket-chat.repo: https://github.com/RocketChat/Rocket.Chat
rocket-chat.issues.endpoint: https://api.github.com/repos/RocketChat/Rocket.Chat
##rocket-chat.sonarqube:
##rocket-chat.scancode:
rocket-chat.scancode: https://gitlab.ow2.org/ow2/oscar/rocketchat/-/jobs/artifacts/master/raw/scancode-Rocket.Chat.json?job=scancode
rocket-chat.omm: https://projects.ow2.org/rest/wikis/projects/spaces/rocket-chat/pages/omm3/objects/ow2.Omm3/0/properties
rocket-chat.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/rocket-chat/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
......@@ -183,6 +180,7 @@ spoon.sonarqube: fr.inria.gforge.spoon:spoon-core
spoon.scancode: https://gitlab.ow2.org/ow2/oscar/spoon/-/jobs/artifacts/master/raw/scancode-spoon.json?job=scancode
# spoon.scancode.excludePrefix: comma-separated prefixes to exclude
# spoon.scancode.excludeSuffix: comma-separated suffixes to exclude
spoon.scancode: https://gitlab.ow2.org/ow2/oscar/spoon/-/jobs/artifacts/master/raw/scancode-spoon.json?job=scancode
spoon.omm: https://projects.ow2.org/rest/wikis/projects/spaces/spoon/pages/omm3/objects/ow2.Omm3/0/properties
spoon.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/spoon/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
......@@ -233,7 +231,7 @@ xwiki.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/xwiki/pages/MKTFo
zenroom.repo: https://github.com/dyne/Zenroom
zenroom.issues.endpoint: https://api.github.com/repos/dyne/Zenroom
##zenroom.sonarqube:
##zenroom.scancode:
zenroom.scancode: https://gitlab.ow2.org/ow2/oscar/zenroom/-/jobs/artifacts/master/raw/scancode-Zenroom.json?job=scancode
zenroom.omm: https://projects.ow2.org/rest/wikis/projects/spaces/zenroom/pages/omm3/objects/ow2.Omm3/0/properties
zenroom.mkt: https://projects.ow2.org/rest/wikis/projects/spaces/zenroom/pages/MKTForm/objects/ow2.MKTFormClass/0/properties
......@@ -499,9 +499,11 @@ public class MainCollector {
if (url == null) return null;
else if (url.contains("jira")) {
StringBuilder script = new StringBuilder();
// Retrieve open but not commented issues:
// JQL: Type=Bug AND Status=Open AND issueFunction not in commented("") AND Project=<projectName>
script.append("{ curl -X GET").append(credentials).append(" -H \"Content-Type: application/json\" '").append(url).append("?maxResults=0&jql=Type=Bug%20AND%20Status=Open%20AND%20issueFunction%20not%20in%20commented(\"\")%20AND%20Project=").append(getIssuesProject(project)).append("'; ");
// Retrieve open but not commented issues = substraction of 2 stat queries:
// JQL for ALL bugs: Type=Bug AND Status=Open AND Project=<projectName>
// JQL for commented bugs (contain "AM" or "PM"): Type=Bug AND Status=Open AND comment!~'\"M"' AND Project=<projectName>
script.append("{ curl -X GET").append(credentials).append(" -H \"Content-Type: application/json\" '").append(url).append("?maxResults=0&jql=Type=Bug%20AND%20Status=Open%20AND%20Project=").append(getIssuesProject(project)).append("'; ");
script.append("curl -X GET").append(credentials).append(" -H \"Content-Type: application/json\" '").append(url).append("?maxResults=0&jql=Type=Bug%20AND%20Status=Open%20AND%20comment!~%27\\\"M\"%27%20AND%20Project=").append(getIssuesProject(project)).append("'; ");
// Gather latest 100 closed + 100 open bugs max
script.append("curl -X GET").append(credentials).append(" -H \"Content-Type: application/json\" '").append(url).append("?maxResults=100&jql=Type=Bug%20AND%20Status=Closed%20AND%20Project=").append(getIssuesProject(project)).append("'; ");
script.append("curl -X GET").append(credentials).append(" -H \"Content-Type: application/json\" '").append(url).append("?maxResults=100&jql=Type=Bug%20AND%20Status=Open%20AND%20Project=").append(getIssuesProject(project)).append("'; } > ").append(getOutputDir(true)).append(project).append("_issues.json");
......
......@@ -162,9 +162,15 @@ public class GithubHandler extends JsonDataHandler {
// Test main program.
public static void main(String args[]) throws Exception {
// if(args.length < 1) throw new Exception("Usage: GithubHandler <json-file>");
String jsonFile = "/tmp/issues.json";
if(args.length < 1) {
System.out.println("Usage: GithubHandler <json-file>");
System.out.println("Trying " + jsonFile + " as default");
} else {
jsonFile = args[0];
}
System.out.println("Started: " + new java.util.Date());
GithubHandler handler = new GithubHandler("test", "/tmp/docdoku_issues.json");
GithubHandler handler = new GithubHandler("test", jsonFile);
handler.run();
System.out.println("Finished: " + new java.util.Date());
if(handler.isDone()) {
......
......@@ -169,9 +169,15 @@ public class GitlabHandler extends JsonDataHandler {
// Test main program.
public static void main(String args[]) throws Exception {
// if(args.length < 1) throw new Exception("Usage: GitlabHandler <json-file>");
String jsonFile = "/tmp/issues.json";
if(args.length < 1) {
System.out.println("Usage: GitlabHandler <json-file>");
System.out.println("Trying " + jsonFile + " as default");
} else {
jsonFile = args[0];
}
System.out.println("Started: " + new java.util.Date());
GitlabHandler handler = new GitlabHandler("test", "/tmp/asm_issues.json");
GitlabHandler handler = new GitlabHandler("test", jsonFile);
handler.run();
System.out.println("Finished: " + new java.util.Date());
if(handler.isDone()) {
......
......@@ -28,7 +28,8 @@ import org.ow2.mrl.data.collect.JsonDataHandler;
public class JiraHandler extends JsonDataHandler {
int level = 0, issueLevel = 0;
int unansweredBugs;
int unansweredBugs = -1;
boolean inStatQueries = true;
LocalDateTime rDate, cDate, uDate;
String lastKey;
String iid;
......@@ -78,6 +79,7 @@ public class JiraHandler extends JsonDataHandler {
@Override
public void key(String key) {
if(! this.assignee) this.assignee = "assignee".equals(key);
if("expand".equals(key)) inStatQueries = false;
this.lastKey = key;
}
......@@ -101,21 +103,25 @@ public class JiraHandler extends JsonDataHandler {
this.assignee = false;
} else if("assignee".equals(this.lastKey)) {
this.assignee = false; // assignee value is an object, or "null" (if lastKey=assignee, it is null)
} else if("total".equals(this.lastKey)) {
// Total should be computed by JQL query returning stats (maxResults=0),
// like this one (returns open but not commented issues):
// Type=Bug AND Status=Open AND issueFunction not in commented("") AND Project=XWIKI
} else if(inStatQueries && "total".equals(this.lastKey)) {
// 2 JQL queries returning stats (maxResults=0):
// 1st one to get all bugs: Type=Bug AND Status=Open
// 2nd one to get commented bugs (contain "AM" or "PM"): Type=Bug AND Status=Open AND comment!~'\"M"'
// Unanswered bugs = all - commented
// Sample HTTP GET args:
// maxResults=0&jql=Type=Bug%20AND%20Status=Open%20AND%20issueFunction%20not%20in%20commented("")%20AND%20Project=XWIKI'
if(this.unansweredBugs <= 0) {
try {
this.unansweredBugs = Integer.parseInt(val);
} catch(Exception e) {
this.unansweredBugs = 0;
}
// maxResults=0&jql=Type=Bug%20AND%20Status=Open%20AND%20comment!~%27\"M"%27%20AND%20Project=XWIKI
int stat;
try {
stat = Integer.parseInt(val);
} catch(Exception e) {
stat = 0;
}
if(this.unansweredBugs < 0) {
this.unansweredBugs = stat; // Should be all bugs (1st query)
} else {
this.unansweredBugs -= stat; // Substract commented bugs (2nd query)
}
}
//computeAverage();
}
/**
......@@ -166,9 +172,15 @@ public class JiraHandler extends JsonDataHandler {
// Test main program.
public static void main(String args[]) throws Exception {
// if(args.length < 1) throw new Exception("Usage: JiraHandler <json-file>");
String jsonFile = "/tmp/issues.json";
if(args.length < 1) {
System.out.println("Usage: JiraHandler <json-file>");
System.out.println("Trying " + jsonFile + " as default");
} else {
jsonFile = args[0];
}
System.out.println("Started: " + new java.util.Date());
JiraHandler handler = new JiraHandler("test", "/tmp/xwiki_issues.json");
JiraHandler handler = new JiraHandler("test", jsonFile);
handler.run();
System.out.println("Finished: " + new java.util.Date());
if(handler.isDone()) {
......
......@@ -14,8 +14,10 @@ public class ScancodeHandler extends JsonDataHandler {
String excludePrefix, excludeSuffix; // comma-separated list of prefix/suffix to exclude
String lastKey;
String path;
boolean licenseName = false;
boolean checkFile = false;
boolean excludeFile = false;
boolean isFile = true;
int totalLicensed = 0; // nb of files with license
int totalFiles = 0; // total nb of files
......@@ -30,7 +32,10 @@ public class ScancodeHandler extends JsonDataHandler {
@Override
public void key(String key) {
this.lastKey = key;
if(key.equals("type")) this.checkFile = true; // type can be "file" or "directory"
if(key.equals("type")) {
this.checkFile = ! isExcluded(this.path); // type can be "file" or "directory"
this.path = null;
}
if(this.checkFile && "key".equals(key)) {
this.licenseName = true;
}
......@@ -39,7 +44,7 @@ public class ScancodeHandler extends JsonDataHandler {
@Override
public void simpleValue(String val) throws Exception {
if("path".equals(lastKey)) {
this.checkFile = ! isExcluded(val);
this.path = val;
}
if(this.checkFile) {
if(val.equals("file")) {
......@@ -55,13 +60,14 @@ public class ScancodeHandler extends JsonDataHandler {
}
/**
* Check if file is supposed to be excluded, or not
* Check if file is supposed to be excluded, or not.
* Exclusion patterns apply to file name only (not path).
* @param path Path to check
* @return true if excluded, false otherwise
*/
private boolean isExcluded(String path) {
if(path == null || path.length() > 0) return true; // Exclude empty paths
if(path == null || path.length() <= 0) return true; // Exclude empty paths
int pos = path.lastIndexOf(File.separatorChar);
String toCheck = (pos < 0 ? path : path.substring(pos+1)); // Check only file name
......@@ -129,9 +135,15 @@ public class ScancodeHandler extends JsonDataHandler {
// Test main program.
public static void main(String args[]) throws Exception {
if(args.length < 1) throw new Exception("Usage: ScancodeHandler <json-file>");
String jsonFile = "/tmp/scancode.json";
if(args.length < 1) {
System.out.println("Usage: ScancodeHandler <json-file>");
System.out.println("Trying " + jsonFile + " as default");
} else {
jsonFile = args[0];
}
System.out.println("Started: " + new java.util.Date());
ScancodeHandler handler = new ScancodeHandler("test", args[0], null, null);
ScancodeHandler handler = new ScancodeHandler("test", jsonFile, "", null);
handler.run();
System.out.println("Finished: " + new java.util.Date());
if(handler.isDone() && handler.getTotalLicensed() > 0) {
......
......@@ -73,12 +73,38 @@ public class SonarHandler extends JsonDataHandler {
return sonarMetric; // Unchanged if unknown
}
}
public double getQualitySonarQTestSuccess() {
return getMetrics().get("QualitySonarQTestSuccess");
}
public double getQualitySonarQTestCoverage() {
return getMetrics().get("QualitySonarQTestCoverage");
}
public double getBlockerIssue() {
return getMetrics().get("BlockerIssue");
}
public double getCriticalIssue() {
return getMetrics().get("CriticalIssue");
}
public double getNloc() {
return getMetrics().get("Nloc");
}
// Test main program.
public static void main(String args[]) throws Exception {
// if(args.length < 1) throw new Exception("Usage: JiraHandler <json-file>");
String jsonFile = "/tmp/sonar.json";
if(args.length < 1) {
System.out.println("Usage: SonarHandler <json-file>");
System.out.println("Trying " + jsonFile + " as default");
} else {
jsonFile = args[0];
}
System.out.println("Started: " + new java.util.Date());
SonarHandler handler = new SonarHandler("test", "/tmp/sonar.json");
SonarHandler handler = new SonarHandler("test", jsonFile);
handler.run();
System.out.println("Finished: " + new java.util.Date());
if(handler.isDone()) {
......
package org.ow2.mrl.data.github;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class GithubHandlerTest {
@Test
void testRun() {
GithubHandler handler = new GithubHandler("test",
"src/test/resources/issues/github_issues.json");
try {
handler.run();
assertEquals(16.4, handler.getBugOpenTime());
assertEquals(37956, handler.getBugResponseTime());
assertEquals(8, handler.getBugTrackerActiveUsers().size());
assertEquals(3, handler.getUnansweredBugs());
} catch(Exception e) {
e.printStackTrace();
}
}
}
package org.ow2.mrl.data.gitlab;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class GitlabHandlerTest {
@Test
void testRun() {
GitlabHandler handler = new GitlabHandler("test",
"src/test/resources/issues/gitlab_issues.json");
try {
handler.run();
assertEquals(2171, handler.getBugOpenTime());
assertEquals(5128339, handler.getBugResponseTime());
assertEquals(5, handler.getBugTrackerActiveUsers().size());
assertEquals(2, handler.getUnansweredBugs());
} catch(Exception e) {
e.printStackTrace();
}
}
}
package org.ow2.mrl.data.jira;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class JiraHandlerTest {
@Test
void testRun() {
JiraHandler handler = new JiraHandler("test",
"src/test/resources/issues/jira_issues.json");
try {
handler.run();
assertEquals(24.29, round2(handler.getBugOpenTime()));
assertEquals(256219.77, round2(handler.getBugResponseTime()));
assertEquals(8, handler.getBugTrackerActiveUsers().size());
assertEquals(33, handler.getUnansweredBugs());
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* Round double to 2 decimals
* @param d double to round
* @return rounded value (2 decimals)
*/
private double round2(double d) {
return Math.round(d * 100) / 100D;
}
}
package org.ow2.mrl.data.scancode;
import static org.junit.jupiter.api.Assertions.*;
import java.util.HashSet;
import java.util.Set;
import org.junit.jupiter.api.Test;
class ScancodeHandlerTest {
@Test
void testRun() {
ScancodeHandler handler = new ScancodeHandler("test",
"src/test/resources/scancode/scancode1.json", null, null);
try {
handler.run();
assertEquals(12, handler.getTotalFiles());
assertEquals(3, handler.getTotalLicensed());
assertEquals(2, handler.getLicenses().size());
assertEquals(0.75, handler.getNoLicenseRatio());
Set<String> licenses = new HashSet<String>();
licenses.add("agpl-3.0");
licenses.add("lgpl-3.0");
assertIterableEquals(licenses, handler.getLicenses());
} catch(Exception e) {
e.printStackTrace();
}
}
@Test
void testRunExclude() {
// Exclude file(s) starting with ("2016" or "2017")
// or ending with (".old" or "330.txt")
ScancodeHandler handler = new ScancodeHandler("test",
"src/test/resources/scancode/scancode1.json",
"2016,2017", ".old,330.txt");
try {
handler.run();
assertEquals(10, handler.getTotalFiles()); // 2 files excluded
assertEquals(3, handler.getTotalLicensed());
assertEquals(2, handler.getLicenses().size());
assertEquals(0.7, handler.getNoLicenseRatio());
Set<String> licenses = new HashSet<String>();
licenses.add("agpl-3.0");
licenses.add("lgpl-3.0");
assertIterableEquals(licenses, handler.getLicenses());
} catch(Exception e) {
e.printStackTrace();
}
}
}
package org.ow2.mrl.data.sonar;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class SonarHandlerTest {
@Test
void testRun() {
SonarHandler handler = new SonarHandler("test",
"src/test/resources/sonar/sonar1.json");
try {
handler.run();
assertEquals(100, handler.getQualitySonarQTestSuccess());
assertEquals(96.6, handler.getQualitySonarQTestCoverage());
assertEquals(0, handler.getBlockerIssue());
assertEquals(32, handler.getCriticalIssue());
assertEquals(10276, handler.getNloc());
} catch(Exception e) {
e.printStackTrace();
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
"files" : [
{
"license_expressions" : [],
"licenses" : [],
"path" : "telosys-tools-generator",
"percentage_of_license_text" : 0,
"scan_errors" : [],
"type" : "directory"
},
{
"license_expressions" : [],
"licenses" : [],
"path" : "telosys-tools-generator/build.properties",
"percentage_of_license_text" : 0,
"scan_errors" : [],
"type" : "file"
},
{
"license_expressions" : [],
"licenses" : [],
"path" : "telosys-tools-generator/build_svg.xml",
"percentage_of_license_text" : 0,
"scan_errors" : [],
"type" : "file"
},
{
"license_expressions" : [],
"licenses" : [],
"path" : "telosys-tools-generator/dependency-reduced-pom.xml",
"percentage_of_license_text" : 0,
"scan_errors" : [],
"type" : "file"
},
{
"license_expressions" : [
"lgpl-3.0"
],
"licenses" : [
{
"category" : "Copyleft Limited",
"end_line" : 165,
"homepage_url" : "http://www.gnu.org/licenses/lgpl-3.0.html",
"is_exception" : false,
"key" : "lgpl-3.0",
"matched_rule" : {
"identifier" : "lgpl-3.0.LICENSE",
"is_license_intro" : false,
"is_license_notice" : false,
"is_license_reference" : false,
"is_license_tag" : false,
"is_license_text" : true,
"license_expression" : "lgpl-3.0",
"licenses" : [
"lgpl-3.0"
],
"match_coverage" : 100,
"matched_length" : 1192,
"matcher" : "1-hash",
"rule_length" : 1192,
"rule_relevance" : 100
},
"name" : "GNU Lesser General Public License 3.0",
"owner" : "Free Software Foundation (FSF)",
"reference_url" : "https://scancode-licensedb.aboutcode.org/lgpl-3.0",