@@ -59,6 +59,9 @@ public final class GradleProvider extends BaseJavaProvider {
5959
6060 private static final Logger log = LoggersFactory .getLogger (GradleProvider .class .getName ());
6161
62+ private static final long TIMEOUT =
63+ Long .parseLong (System .getProperty ("trustify.gradle.timeout.seconds" , "120" ));
64+
6265 private final String gradleExecutable = Operations .getExecutable ("gradle" , "--version" );
6366
6467 public GradleProvider (Path manifest ) {
@@ -73,20 +76,24 @@ public String readLicenseFromManifest() {
7376 @ Override
7477 public Content provideStack () throws IOException {
7578 Path tempFile = getDependencies (manifest );
76- if (debugLoggingIsNeeded ()) {
77- String stackAnalysisDependencyTree = Files .readString (tempFile );
78- log .info (
79- String .format (
80- "Package Manager Gradle Stack Analysis Dependency Tree Output: %s %s" ,
81- System .lineSeparator (), stackAnalysisDependencyTree ));
82- }
83- Map <String , String > propertiesMap = extractProperties (manifest );
79+ try {
80+ if (debugLoggingIsNeeded ()) {
81+ String stackAnalysisDependencyTree = Files .readString (tempFile );
82+ log .info (
83+ String .format (
84+ "Package Manager Gradle Stack Analysis Dependency Tree Output: %s %s" ,
85+ System .lineSeparator (), stackAnalysisDependencyTree ));
86+ }
87+ Map <String , String > propertiesMap = extractProperties (manifest );
8488
85- var sbom = buildSbomFromTextFormat (tempFile , propertiesMap , AnalysisType .STACK );
86- var ignored = getIgnoredDeps (manifest );
89+ var sbom = buildSbomFromTextFormat (tempFile , propertiesMap , AnalysisType .STACK );
90+ var ignored = getIgnoredDeps (manifest );
8791
88- return new Content (
89- sbom .filterIgnoredDeps (ignored ).getAsJsonString ().getBytes (), Api .CYCLONEDX_MEDIA_TYPE );
92+ return new Content (
93+ sbom .filterIgnoredDeps (ignored ).getAsJsonString ().getBytes (), Api .CYCLONEDX_MEDIA_TYPE );
94+ } finally {
95+ Files .deleteIfExists (tempFile );
96+ }
9097 }
9198
9299 private List <String > getIgnoredDeps (Path manifestPath ) throws IOException {
@@ -228,28 +235,42 @@ private String extractPackageName(String line) {
228235 }
229236
230237 private Path getDependencies (Path manifestPath ) throws IOException {
231- // create a temp file for storing the dependency tree in
232- var tempFile = Files .createTempFile ("TRUSTIFY_DA_graph_" , null );
233- // the command will create the dependency tree in the temp file
234238 String gradleCommand = gradleExecutable + " dependencies" ;
235-
236239 String [] cmdList = gradleCommand .split ("\\ s+" );
237- String gradleOutput =
238- Operations .runProcessGetOutput (Path .of (manifestPath .getParent ().toString ()), cmdList );
239- Files .writeString (tempFile , gradleOutput );
240240
241+ var result =
242+ Operations .runProcessGetFullOutput (
243+ Path .of (manifestPath .getParent ().toString ()), cmdList , null , TIMEOUT );
244+
245+ if (result .getExitCode () != 0 ) {
246+ throw new RuntimeException (
247+ String .format (
248+ "gradle dependencies command failed with exit code %d for manifest '%s': %s" ,
249+ result .getExitCode (), manifestPath , result .getError ()));
250+ }
251+
252+ var tempFile = Files .createTempFile ("TRUSTIFY_DA_graph_" , null );
253+ Files .writeString (tempFile , result .getOutput ());
241254 return tempFile ;
242255 }
243256
244257 private Path getProperties (Path manifestPath ) throws IOException {
245- Path propsTempFile = Files .createTempFile ("propsfile" , ".txt" );
246258 String propCmd = gradleExecutable + " properties" ;
247259 String [] propCmdList = propCmd .split ("\\ s+" );
248- String properties =
249- Operations .runProcessGetOutput (Path .of (manifestPath .getParent ().toString ()), propCmdList );
250- // Create a temporary file
251- Files .writeString (propsTempFile , properties );
252260
261+ var result =
262+ Operations .runProcessGetFullOutput (
263+ Path .of (manifestPath .getParent ().toString ()), propCmdList , null , TIMEOUT );
264+
265+ if (result .getExitCode () != 0 ) {
266+ throw new RuntimeException (
267+ String .format (
268+ "gradle properties command failed with exit code %d for manifest '%s': %s" ,
269+ result .getExitCode (), manifestPath , result .getError ()));
270+ }
271+
272+ Path propsTempFile = Files .createTempFile ("propsfile" , ".txt" );
273+ Files .writeString (propsTempFile , result .getOutput ());
253274 return propsTempFile ;
254275 }
255276
@@ -509,9 +530,12 @@ private boolean containsVersion(String line) {
509530
510531 private String getRoot (Path textFormatFile , Map <String , String > propertiesMap )
511532 throws IOException {
512- String group = propertiesMap .get ("group" );
513- String version = propertiesMap .get ("version" );
533+ String group = propertiesMap .getOrDefault ("group" , "unknown " );
534+ String version = propertiesMap .getOrDefault ("version" , "0.0.0 " );
514535 String rootName = extractRootProjectValue (textFormatFile );
536+ if (rootName == null || rootName .isEmpty ()) {
537+ rootName = "unknown" ;
538+ }
515539 return group + ':' + rootName + ':' + "jar" + ':' + version ;
516540 }
517541
@@ -531,24 +555,28 @@ private String extractRootProjectValue(Path inputFilePath) throws IOException {
531555
532556 private Map <String , String > extractProperties (Path manifestPath ) throws IOException {
533557 Path propsTempFile = getProperties (manifestPath );
534- String content = Files .readString (propsTempFile );
535- // Define the regular expression pattern for key-value pairs
536- Pattern pattern = Pattern .compile ("([^:]+):\\ s+(.+)" );
537- Matcher matcher = pattern .matcher (content );
538- // Create a Map to store key-value pairs
539- Map <String , String > keyValueMap = new HashMap <>();
540-
541- // Iterate through matches and add them to the map
542- while (matcher .find ()) {
543- String key = matcher .group (1 ).trim ();
544- String value = matcher .group (2 ).trim ();
545- keyValueMap .put (key , value );
546- }
547- // Check if any key-value pairs were found
548- if (!keyValueMap .isEmpty ()) {
549- return keyValueMap ;
550- } else {
551- return Collections .emptyMap ();
558+ try {
559+ String content = Files .readString (propsTempFile );
560+ // Define the regular expression pattern for key-value pairs
561+ Pattern pattern = Pattern .compile ("([^:]+):\\ s+(.+)" );
562+ Matcher matcher = pattern .matcher (content );
563+ // Create a Map to store key-value pairs
564+ Map <String , String > keyValueMap = new HashMap <>();
565+
566+ // Iterate through matches and add them to the map
567+ while (matcher .find ()) {
568+ String key = matcher .group (1 ).trim ();
569+ String value = matcher .group (2 ).trim ();
570+ keyValueMap .put (key , value );
571+ }
572+ // Check if any key-value pairs were found
573+ if (!keyValueMap .isEmpty ()) {
574+ return keyValueMap ;
575+ } else {
576+ return Collections .emptyMap ();
577+ }
578+ } finally {
579+ Files .deleteIfExists (propsTempFile );
552580 }
553581 }
554582
@@ -577,14 +605,17 @@ private List<String> extractLines(Path inputFilePath, String startMarker) throws
577605
578606 @ Override
579607 public Content provideComponent () throws IOException {
580-
581608 Path tempFile = getDependencies (manifest );
582- Map <String , String > propertiesMap = extractProperties (manifest );
609+ try {
610+ Map <String , String > propertiesMap = extractProperties (manifest );
583611
584- Sbom sbom = buildSbomFromTextFormat (tempFile , propertiesMap , AnalysisType .COMPONENT );
585- var ignored = getIgnoredDeps (manifest );
612+ Sbom sbom = buildSbomFromTextFormat (tempFile , propertiesMap , AnalysisType .COMPONENT );
613+ var ignored = getIgnoredDeps (manifest );
586614
587- return new Content (
588- sbom .filterIgnoredDeps (ignored ).getAsJsonString ().getBytes (), Api .CYCLONEDX_MEDIA_TYPE );
615+ return new Content (
616+ sbom .filterIgnoredDeps (ignored ).getAsJsonString ().getBytes (), Api .CYCLONEDX_MEDIA_TYPE );
617+ } finally {
618+ Files .deleteIfExists (tempFile );
619+ }
589620 }
590621}
0 commit comments