Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for gradle #127

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ jobs:
with:
go-version: '1.20.1'

- name: Setup Gradle
uses: gradle/gradle-build-action@v3

- name: Install project modules
run: npm ci

Expand Down
19 changes: 19 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"dependencies": {
"@babel/core": "^7.23.2",
"@cyclonedx/cyclonedx-library": "^4.0.0",
"fast-toml": "^0.5.4",
"fast-xml-parser": "^4.2.4",
"help": "^3.0.2",
"packageurl-js": "^1.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/analysis.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {EOL} from "os";
import {RegexNotToBeLogged, getCustom} from "./tools.js";

Check warning on line 2 in src/analysis.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Expected 'multiple' syntax before 'single' syntax

Check warning on line 2 in src/analysis.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Expected 'multiple' syntax before 'single' syntax

export default { requestComponent, requestStack, validateToken }

Expand All @@ -9,7 +9,7 @@

/**
* Send a stack analysis request and get the report as 'text/html' or 'application/json'.
* @param {import('./provider').Provider} provider - the provided data for constructing the request
* @param {import('./provider').Provider | import('./providers/base_java.js').default } provider - the provided data for constructing the request
* @param {string} manifest - path for the manifest
* @param {string} url - the backend url to send the request to
* @param {boolean} [html=false] - true will return 'text/html', false will return 'application/json'
Expand Down
5 changes: 3 additions & 2 deletions src/provider.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import javaMvnProvider from './providers/java_maven.js'
import javascriptNpmProvider from './providers/javascript_npm.js'
import golangGomodulesProvider from './providers/golang_gomodules.js'

Check warning on line 2 in src/provider.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Imports should be sorted alphabetically

Check warning on line 2 in src/provider.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Imports should be sorted alphabetically
import pythonPipProvider from './providers/python_pip.js'
import path from 'node:path'

Check warning on line 4 in src/provider.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Imports should be sorted alphabetically

Check warning on line 4 in src/provider.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Imports should be sorted alphabetically
import Java_maven from "./providers/java_maven.js";

Check warning on line 5 in src/provider.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Imports should be sorted alphabetically

Check warning on line 5 in src/provider.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Imports should be sorted alphabetically
import Java_gradle from "./providers/java_gradle.js";

Check warning on line 6 in src/provider.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Imports should be sorted alphabetically

Check warning on line 6 in src/provider.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Imports should be sorted alphabetically

/** @typedef {{ecosystem: string, contentType: string, content: string}} Provided */
/** @typedef {{isSupported: function(string): boolean, provideComponent: function(string, {}): Provided, provideStack: function(string, {}): Provided}} Provider */
Expand All @@ -11,7 +12,7 @@
* MUST include all providers here.
* @type {[Provider]}
*/
export const availableProviders = [javaMvnProvider,javascriptNpmProvider,golangGomodulesProvider,pythonPipProvider]
export const availableProviders = [new Java_maven(),new Java_gradle(),javascriptNpmProvider,golangGomodulesProvider,pythonPipProvider]

/**
* Match a provider from a list or providers based on file type.
Expand Down
142 changes: 142 additions & 0 deletions src/providers/base_java.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import {execSync} from "node:child_process"
import {PackageURL} from 'packageurl-js'

Check warning on line 2 in src/providers/base_java.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Imports should be sorted alphabetically

Check warning on line 2 in src/providers/base_java.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Imports should be sorted alphabetically


/** @typedef {import('../provider').Provider} */

/** @typedef {import('../provider').Provided} Provided */

/** @typedef {{name: string, version: string}} Package */

/** @typedef {{groupId: string, artifactId: string, version: string, scope: string, ignore: boolean}} Dependency */

/**
* @type {string} ecosystem for java maven packages.
* @private
*/
export const ecosystem_maven = 'maven'
export const ecosystem_gradle = 'gradle'
export default class Base_Java {
constructor() {
}



DEP_REGEX = /(([-a-zA-Z0-9._]{2,})|[0-9])/g
CONFLICT_REGEX = /.*omitted for conflict with (\S+)\)/

/**
* Recursively populates the SBOM instance with the parsed graph
* @param {string} src - Source dependency to start the calculations from
* @param {number} srcDepth - Current depth in the graph for the given source
* @param {Array} lines - Array containing the text files being parsed
* @param {Sbom} sbom - The SBOM where the dependencies are being added
*/
parseDependencyTree(src, srcDepth, lines, sbom) {
if (lines.length === 0) {
return;
}
if ((lines.length === 1 && lines[0].trim() === "")) {
return;
}
let index = 0;
let target = lines[index];
let targetDepth = this.#getDepth(target);
while (targetDepth > srcDepth && index < lines.length) {
if (targetDepth === srcDepth + 1) {
let from = this.parseDep(src);
let to = this.parseDep(target);
let matchedScope = target.match(/:compile|:provided|:runtime|:test|:system/g)
let matchedScopeSrc = src.match(/:compile|:provided|:runtime|:test|:system/g)
// only add dependency to sbom if it's not with test scope or if it's root
if ((matchedScope && matchedScope[0] !== ":test" && (matchedScopeSrc && matchedScopeSrc[0] !== ":test")) || (srcDepth == 0 && matchedScope && matchedScope[0] !== ":test")) {

Check warning on line 52 in src/providers/base_java.js

View workflow job for this annotation

GitHub Actions / Lint and test project (18)

Expected '===' and instead saw '=='

Check warning on line 52 in src/providers/base_java.js

View workflow job for this annotation

GitHub Actions / Lint and test project (latest)

Expected '===' and instead saw '=='
sbom.addDependency(sbom.purlToComponent(from), to)
}
} else {
this.parseDependencyTree(lines[index - 1], this.#getDepth(lines[index - 1]), lines.slice(index), sbom)
}
target = lines[++index];
targetDepth = this.#getDepth(target);
}
}

/**
* Calculates how deep in the graph is the given line
* @param {string} line - line to calculate the depth from
* @returns {number} The calculated depth
* @private
*/
#getDepth(line) {
if (line === undefined) {
return -1;
}
return ((line.indexOf('-') - 1) / 3) + 1;
}

/**
* Create a PackageURL from any line in a Text Graph dependency tree for a manifest path.
* @param {string} line - line to parse from a dependencies.txt file
* @returns {PackageURL} The parsed packageURL
*/
parseDep(line) {

let match = line.match(this.DEP_REGEX);
if (!match) {
throw new Error(`Unable generate SBOM from dependency tree. Line: ${line} cannot be parsed into a PackageURL`);
}
let version
if (match.length >= 5 && ['compile', 'provided', 'runtime'].includes(match[5])) {
version = `${match[4]}-${match[3]}`
} else {
version = match[3]
}
let override = line.match(this.CONFLICT_REGEX);
if (override) {
version = override[1];
}
return this.toPurl(match[0], match[1], version);
}

/**
* Returns a PackageUrl For Java maven dependencies
* @param group
* @param artifact
* @param version
* @return {PackageURL}
*/
toPurl(group, artifact, version) {
if (typeof version === "number") {
version = version.toString()
}
return new PackageURL('maven', group, artifact, version, undefined, undefined);
}

/** this method invokes command string in a process in a synchronous way.
* @param cmdString - the command to be invoked
* @param errorMessage - the message to print to an exception thrown to client in case of error
* @protected
*/
_invokeCommand(cmdString, errorMessage) {
execSync(cmdString, err => {
if (err) {
throw new Error(`${errorMessage}`)
}
})
}

/** this method invokes command string in a process in a synchronous way.
* @param cmdString - the command to be invoked
* @param workingDir - the directory in which the command will be invoked
* @return the output of the command
* @protected
*/
_invokeCommandGetOutput(cmdString, workingDir) {
let opts = {}
if(workingDir) {
opts.cwd = workingDir
}
return execSync(cmdString, opts)
}


}
Loading
Loading