1313import org .apache .commons .lang3 .StringUtils ;
1414import org .apache .maven .model .MailingList ;
1515import org .apache .maven .model .Model ;
16+ import org .cyclonedx .Format ;
1617import org .cyclonedx .Version ;
1718import org .cyclonedx .exception .GeneratorException ;
1819import org .cyclonedx .generators .BomGeneratorFactory ;
@@ -74,10 +75,7 @@ public class CycloneDxSbomGenerator {
7475
7576 private static final String CLASSIFIER_CYCLONEDX = "cyclonedx" ;
7677 private static final String FORMAT_ALL = "all" ;
77- private static final String FORMAT_JSON = "json" ;
78- private static final String FORMAT_XML = "xml" ;
79- private static final String DEFAULT_FORMAT = FORMAT_JSON ;
80- private static final List <String > SUPPORTED_FORMATS = List .of (FORMAT_JSON , FORMAT_XML );
78+ private static final String DEFAULT_FORMAT = "json" ;
8179
8280 public static CycloneDxSbomGenerator newInstance () {
8381 return new CycloneDxSbomGenerator ();
@@ -139,37 +137,57 @@ public CycloneDxSbomGenerator setIncludeLicenseText(boolean includeLicenseText)
139137 return this ;
140138 }
141139
140+ public List <String > generateText () {
141+ final Bom bom = createSbom ();
142+ if (FORMAT_ALL .equalsIgnoreCase (format )) {
143+ Format [] formats = Format .values ();
144+ final List <String > result = new ArrayList <>(formats .length );
145+ for (Format format : formats ) {
146+ result .add (formatSbom (bom , format .getExtension ()));
147+ }
148+ return result ;
149+ }
150+ return List .of (formatSbom (bom , format == null ? DEFAULT_FORMAT : format ));
151+ }
152+
142153 public List <SbomResult > generate () {
143- ensureNotGenerated ();
144- Objects .requireNonNull (manifest , "Manifest is null" );
145154 if (outputFile == null && outputDir == null ) {
146155 throw new IllegalArgumentException ("Either outputDir or outputFile must be provided" );
147156 }
148- generated = true ;
157+ final Bom bom = createSbom () ;
149158
150- var bom = new Bom ();
151- bom .setMetadata (new Metadata ());
152- addToolInfo (bom );
153-
154- addApplicationComponent (bom , manifest .getMainComponent ());
155- for (var c : manifest .getComponents ()) {
156- addComponent (bom , c );
157- }
158159 if (FORMAT_ALL .equalsIgnoreCase (format )) {
159160 if (outputFile != null ) {
160161 throw new IllegalArgumentException ("Can't use output file " + outputFile + " with format '"
161162 + FORMAT_ALL + "', since it implies generating multiple files" );
162163 }
163- final List <SbomResult > result = new ArrayList <>(SUPPORTED_FORMATS .size ());
164- for (String format : SUPPORTED_FORMATS ) {
165- result .add (persistSbom (bom , getOutputFile (format ), format ));
164+ Format [] formats = Format .values ();
165+ final List <SbomResult > result = new ArrayList <>(formats .length );
166+ for (Format format : formats ) {
167+ result .add (persistSbom (bom , getOutputFile (format .getExtension ()), format .getExtension ()));
166168 }
167169 return result ;
168170 }
169171 var outputFile = getOutputFile (format == null ? DEFAULT_FORMAT : format );
170172 return List .of (persistSbom (bom , outputFile , getFormat (outputFile )));
171173 }
172174
175+ private Bom createSbom () {
176+ ensureNotGenerated ();
177+ Objects .requireNonNull (manifest , "Manifest is null" );
178+ generated = true ;
179+
180+ var bom = new Bom ();
181+ bom .setMetadata (new Metadata ());
182+ addToolInfo (bom );
183+
184+ addApplicationComponent (bom , manifest .getMainComponent ());
185+ for (var c : manifest .getComponents ()) {
186+ addComponent (bom , c );
187+ }
188+ return bom ;
189+ }
190+
173191 private void addComponent (Bom bom , ApplicationComponent component ) {
174192 final org .cyclonedx .model .Component c = getComponent (component );
175193 bom .addComponent (c );
@@ -441,25 +459,7 @@ private static List<ArtifactCoords> sortAlphabetically(Collection<ArtifactCoords
441459 }
442460
443461 private SbomResult persistSbom (Bom bom , Path sbomFile , String format ) {
444-
445- var specVersion = getSchemaVersion ();
446- final String sbomContent ;
447- if (format .equalsIgnoreCase ("json" )) {
448- try {
449- sbomContent = BomGeneratorFactory .createJson (specVersion , bom ).toJsonString ();
450- } catch (Throwable e ) {
451- throw new RuntimeException ("Failed to generate an SBOM in JSON format" , e );
452- }
453- } else if (format .equalsIgnoreCase ("xml" )) {
454- try {
455- sbomContent = BomGeneratorFactory .createXml (specVersion , bom ).toXmlString ();
456- } catch (GeneratorException e ) {
457- throw new RuntimeException ("Failed to generate an SBOM in XML format" , e );
458- }
459- } else {
460- throw new RuntimeException (
461- "Unsupported SBOM artifact type " + format + ", supported types are json and xml" );
462- }
462+ final String sbomContent = formatSbom (bom , format );
463463
464464 var outputDir = sbomFile .getParent ();
465465 if (outputDir != null ) {
@@ -482,6 +482,33 @@ private SbomResult persistSbom(Bom bom, Path sbomFile, String format) {
482482 manifest .getRunnerPath ());
483483 }
484484
485+ private String formatSbom (Bom bom , String format ) {
486+ var specVersion = getSchemaVersion ();
487+ final String sbomContent ;
488+ if (format .equalsIgnoreCase ("json" )) {
489+ try {
490+ sbomContent = BomGeneratorFactory .createJson (specVersion , bom ).toJsonString ();
491+ } catch (Throwable e ) {
492+ throw new RuntimeException ("Failed to generate an SBOM in JSON format" , e );
493+ }
494+ } else if (format .equalsIgnoreCase ("xml" )) {
495+ try {
496+ sbomContent = BomGeneratorFactory .createXml (specVersion , bom ).toXmlString ();
497+ } catch (GeneratorException e ) {
498+ throw new RuntimeException ("Failed to generate an SBOM in XML format" , e );
499+ }
500+ } else {
501+ var msg = new StringBuilder ("Unsupported SBOM format " ).append (format );
502+ var supportedFormats = Format .values ();
503+ msg .append (". Supported formats are " ).append (supportedFormats [0 ].getExtension ());
504+ for (int i = 1 ; i < supportedFormats .length ; i ++) {
505+ msg .append (", " ).append (supportedFormats [i ].getExtension ());
506+ }
507+ throw new IllegalArgumentException (msg .toString ());
508+ }
509+ return sbomContent ;
510+ }
511+
485512 private Path getOutputFile (String defaultFormat ) {
486513 if (outputFile == null ) {
487514 var fileName = toSbomFileName (manifest .getRunnerPath ().getFileName ().toString (), defaultFormat );
0 commit comments