Skip to content

Commit b3878de

Browse files
authored
fix: add missing standard purl types (#163)
1 parent 0ca1184 commit b3878de

File tree

2 files changed

+85
-13
lines changed

2 files changed

+85
-13
lines changed

src/main/java/com/github/packageurl/PackageURL.java

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

src/test/java/com/github/packageurl/PackageURLTest.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,23 +322,38 @@ public void testConstructorWithEmptyKey() throws MalformedPackageURLException {
322322

323323
@Test
324324
public void testStandardTypes() {
325+
Assert.assertEquals("alpm", PackageURL.StandardTypes.ALPM);
326+
Assert.assertEquals("apk", PackageURL.StandardTypes.APK);
325327
Assert.assertEquals("bitbucket", PackageURL.StandardTypes.BITBUCKET);
328+
Assert.assertEquals("bitnami", PackageURL.StandardTypes.BITNAMI);
329+
Assert.assertEquals("cocoapods", PackageURL.StandardTypes.COCOAPODS);
326330
Assert.assertEquals("cargo", PackageURL.StandardTypes.CARGO);
327331
Assert.assertEquals("composer", PackageURL.StandardTypes.COMPOSER);
328-
Assert.assertEquals("deb", PackageURL.StandardTypes.DEBIAN);
332+
Assert.assertEquals("conan", PackageURL.StandardTypes.CONAN);
333+
Assert.assertEquals("conda", PackageURL.StandardTypes.CONDA);
334+
Assert.assertEquals("cpan", PackageURL.StandardTypes.CPAN);
335+
Assert.assertEquals("cran", PackageURL.StandardTypes.CRAN);
336+
Assert.assertEquals("deb", PackageURL.StandardTypes.DEB);
329337
Assert.assertEquals("docker", PackageURL.StandardTypes.DOCKER);
330338
Assert.assertEquals("gem", PackageURL.StandardTypes.GEM);
331339
Assert.assertEquals("generic", PackageURL.StandardTypes.GENERIC);
332340
Assert.assertEquals("github", PackageURL.StandardTypes.GITHUB);
333341
Assert.assertEquals("golang", PackageURL.StandardTypes.GOLANG);
342+
Assert.assertEquals("hackage", PackageURL.StandardTypes.HACKAGE);
334343
Assert.assertEquals("hex", PackageURL.StandardTypes.HEX);
344+
Assert.assertEquals("huggingface", PackageURL.StandardTypes.HUGGINGFACE);
345+
Assert.assertEquals("luarocks", PackageURL.StandardTypes.LUAROCKS);
335346
Assert.assertEquals("maven", PackageURL.StandardTypes.MAVEN);
347+
Assert.assertEquals("mlflow", PackageURL.StandardTypes.MLFLOW);
336348
Assert.assertEquals("npm", PackageURL.StandardTypes.NPM);
337349
Assert.assertEquals("nuget", PackageURL.StandardTypes.NUGET);
350+
Assert.assertEquals("qpkg", PackageURL.StandardTypes.QPKG);
351+
Assert.assertEquals("oci", PackageURL.StandardTypes.OCI);
352+
Assert.assertEquals("pub", PackageURL.StandardTypes.PUB);
338353
Assert.assertEquals("pypi", PackageURL.StandardTypes.PYPI);
339354
Assert.assertEquals("rpm", PackageURL.StandardTypes.RPM);
340-
Assert.assertEquals("nixpkgs", PackageURL.StandardTypes.NIXPKGS);
341-
Assert.assertEquals("hackage", PackageURL.StandardTypes.HACKAGE);
355+
Assert.assertEquals("swid", PackageURL.StandardTypes.SWID);
356+
Assert.assertEquals("swift", PackageURL.StandardTypes.SWIFT);
342357
}
343358

344359
@Test

0 commit comments

Comments
 (0)