2020
2121import org .apache .commons .io .IOUtils ;
2222import org .cyclonedx .exception .ParseException ;
23- import org .cyclonedx .parsers .JsonParser ;
24- import org .cyclonedx .parsers .Parser ;
25- import org .cyclonedx .parsers .XmlParser ;
23+
2624import java .io .File ;
2725import java .io .IOException ;
2826import java .io .InputStream ;
2927import java .nio .charset .StandardCharsets ;
3028import java .nio .file .Files ;
29+ import java .util .Arrays ;
3130
3231public class BomParserFactory {
3332
3433 private BomParserFactory () {}
3534
3635 public static Parser createParser (final File file ) throws ParseException {
3736 try (final InputStream fis = Files .newInputStream (file .toPath ())) {
38- final byte [] bytes = IOUtils .toByteArray (fis , 1 );
39- return createParser (bytes );
37+ final byte [] prefix = new byte [4 ]; // potential 3-byte UTF-8 byte-order mark + 1 content byte
38+ final int actualPrefixLength = IOUtils .read (fis , prefix );
39+ return createParser (Arrays .copyOf (prefix , actualPrefixLength ));
4040 } catch (IOException e ) {
4141 throw new ParseException ("An error occurred creating parser from file" , e );
4242 }
4343 }
4444
4545 public static Parser createParser (final byte [] bytes ) throws ParseException {
46- if (bytes .length < 1 ) {
46+ final int offset = hasUtf8ByteOrderMark (bytes ) ? 3 : 0 ;
47+ if (bytes .length - offset < 1 ) {
4748 throw new ParseException ("Cannot create parser from empty byte array." );
4849 }
4950
50- if (bytes [0 ] == 123 ) {
51+ if (bytes [offset ] == ( byte ) '{' ) {
5152 return new JsonParser ();
52- } else if (bytes [0 ] == 60 ) {
53+ } else if (bytes [offset ] == ( byte ) '<' ) {
5354 return new XmlParser ();
5455 } else {
5556 throw new ParseException ("The specified BOM is not in a supported format. Supported formats are XML and JSON" );
5657 }
5758 }
5859
5960 public static boolean looksLikeCycloneDX (final byte [] bytes ) {
60- final String bomString = new String (bytes , StandardCharsets .UTF_8 );
61+ final int offset = hasUtf8ByteOrderMark (bytes ) ? 3 : 0 ;
62+ final String bomString = new String (bytes , offset , bytes .length - offset , StandardCharsets .UTF_8 );
6163 if (bomString .startsWith ("<?xml" ) && bomString .contains ("<bom" ) &&
6264 bomString .contains ("http://cyclonedx.org/schema/bom" )) {
6365 return true ;
@@ -66,4 +68,12 @@ public static boolean looksLikeCycloneDX(final byte[] bytes) {
6668 return bomString .startsWith ("{" ) && bomString .contains ("bomFormat" ) && bomString .contains ("CycloneDX" );
6769 }
6870 }
71+
72+ private static boolean hasUtf8ByteOrderMark (byte [] bytes ) {
73+ return bytes .length >= 3
74+ && bytes [0 ] == (byte ) 0xEF
75+ && bytes [1 ] == (byte ) 0xBB
76+ && bytes [2 ] == (byte ) 0xBF ;
77+ }
78+
6979}
0 commit comments