@@ -96,7 +96,7 @@ public PackageURL(final String type, final String namespace, final String name,
9696 this .type = toLowerCase (validateType (type ));
9797 this .namespace = validateNamespace (namespace );
9898 this .name = validateName (name );
99- this .version = validateVersion (version );
99+ this .version = validateVersion (type , version );
100100 this .qualifiers = parseQualifiers (qualifiers );
101101 this .subpath = validateSubpath (subpath );
102102 verifyTypeConstraints (this .type , this .namespace , this .name );
@@ -309,13 +309,25 @@ private String validateNamespace(final String[] values) throws MalformedPackageU
309309 final String tempNamespace = validatePath (values , false );
310310 String retVal ;
311311 switch (type ) {
312+ case StandardTypes .APK :
312313 case StandardTypes .BITBUCKET :
313- case StandardTypes .DEBIAN :
314+ case StandardTypes .COMPOSER :
315+ case StandardTypes .DEB :
314316 case StandardTypes .GITHUB :
315317 case StandardTypes .GOLANG :
318+ case StandardTypes .HEX :
319+ case StandardTypes .LUAROCKS :
320+ case StandardTypes .QPKG :
316321 case StandardTypes .RPM :
317322 retVal = tempNamespace != null ? toLowerCase (tempNamespace ) : null ;
318323 break ;
324+ case StandardTypes .MLFLOW :
325+ case StandardTypes .OCI :
326+ if (tempNamespace != null ) {
327+ throw new MalformedPackageURLException ("The PackageURL specified contains a namespace which is not allowed for type: " + type );
328+ }
329+ retVal = null ;
330+ break ;
319331 default :
320332 retVal = tempNamespace ;
321333 break ;
@@ -329,12 +341,21 @@ private String validateName(final String value) throws MalformedPackageURLExcept
329341 }
330342 String temp ;
331343 switch (type ) {
344+ case StandardTypes .APK :
332345 case StandardTypes .BITBUCKET :
333- case StandardTypes .DEBIAN :
346+ case StandardTypes .BITNAMI :
347+ case StandardTypes .COMPOSER :
348+ case StandardTypes .DEB :
334349 case StandardTypes .GITHUB :
335350 case StandardTypes .GOLANG :
351+ case StandardTypes .HEX :
352+ case StandardTypes .LUAROCKS :
353+ case StandardTypes .OCI :
336354 temp = toLowerCase (value );
337355 break ;
356+ case StandardTypes .PUB :
357+ temp = toLowerCase (value ).replaceAll ("[^a-z0-9_]" , "_" );
358+ break ;
338359 case StandardTypes .PYPI :
339360 temp = toLowerCase (value ).replace ('_' , '-' );
340361 break ;
@@ -345,14 +366,26 @@ private String validateName(final String value) throws MalformedPackageURLExcept
345366 return temp ;
346367 }
347368
348- private String validateVersion (final String value ) {
349- return value ;
369+ private String validateVersion (final String type , final String value ) {
370+ if (value == null ) {
371+ return null ;
372+ }
373+
374+ switch (type ) {
375+ case StandardTypes .HUGGINGFACE :
376+ case StandardTypes .LUAROCKS :
377+ case StandardTypes .OCI :
378+ return toLowerCase (value );
379+ default :
380+ return value ;
381+ }
350382 }
351383
352384 private Map <String , String > validateQualifiers (final Map <String , String > values ) throws MalformedPackageURLException {
353385 if (values == null || values .isEmpty ()) {
354386 return null ;
355387 }
388+
356389 for (Map .Entry <String , String > entry : values .entrySet ()) {
357390 validateKey (entry .getKey ());
358391 final String value = entry .getValue ();
@@ -654,7 +687,7 @@ private void parse(final String purl) throws MalformedPackageURLException {
654687 // version is optional - check for existence
655688 index = remainder .lastIndexOf ('@' );
656689 if (index >= start ) {
657- this .version = validateVersion (percentDecode (remainder .substring (index + 1 )));
690+ this .version = validateVersion (this . type , percentDecode (remainder .substring (index + 1 )));
658691 remainder = remainder .substring (0 , index );
659692 }
660693
@@ -818,24 +851,48 @@ public int hashCode() {
818851 *
819852 * @since 1.0.0
820853 */
821- public static class StandardTypes {
854+ public static final class StandardTypes {
855+ public static final String ALPM = "alpm" ;
856+ public static final String APK = "apk" ;
822857 public static final String BITBUCKET = "bitbucket" ;
858+ public static final String BITNAMI = "bitnami" ;
823859 public static final String CARGO = "cargo" ;
860+ public static final String COCOAPODS = "cocoapods" ;
824861 public static final String COMPOSER = "composer" ;
825- public static final String DEBIAN = "deb" ;
862+ public static final String CONAN = "conan" ;
863+ public static final String CONDA = "conda" ;
864+ public static final String CPAN = "cpan" ;
865+ public static final String CRAN = "cran" ;
866+ public static final String DEB = "deb" ;
826867 public static final String DOCKER = "docker" ;
827868 public static final String GEM = "gem" ;
828869 public static final String GENERIC = "generic" ;
829870 public static final String GITHUB = "github" ;
830871 public static final String GOLANG = "golang" ;
872+ public static final String HACKAGE = "hackage" ;
831873 public static final String HEX = "hex" ;
874+ public static final String HUGGINGFACE = "huggingface" ;
875+ public static final String LUAROCKS = "luarocks" ;
832876 public static final String MAVEN = "maven" ;
877+ public static final String MLFLOW = "mlflow" ;
878+ public static final String NIX = "nix" ;
833879 public static final String NPM = "npm" ;
834880 public static final String NUGET = "nuget" ;
881+ public static final String OCI = "oci" ;
882+ public static final String PUB = "pub" ;
835883 public static final String PYPI = "pypi" ;
884+ public static final String QPKG = "qpkg" ;
836885 public static final String RPM = "rpm" ;
837- public static final String NIXPKGS = "nixpkgs" ;
838- public static final String HACKAGE = "hackage" ;
886+ public static final String SWID = "swid" ;
887+ public static final String SWIFT = "swift" ;
888+ @ Deprecated
889+ public static final String DEBIAN = "deb" ;
890+ @ Deprecated
891+ public static final String NIXPKGS = "nix" ;
892+
893+ private StandardTypes () {
894+
895+ }
839896 }
840897
841898}
0 commit comments