Skip to content

Commit 0b3b2b6

Browse files
committed
Merge remote-tracking branch 'upstream/master' into deprecated-and-since
2 parents b4d3429 + f16a2eb commit 0b3b2b6

File tree

1 file changed

+70
-75
lines changed

1 file changed

+70
-75
lines changed

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

Lines changed: 70 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,52 @@ public final class PackageURL implements Serializable {
6060

6161
private static final char PERCENT_CHAR = '%';
6262

63+
/**
64+
* The PackageURL scheme constant
65+
*/
66+
public static final String SCHEME = "pkg";
67+
68+
/**
69+
* The PackageURL scheme ({@code "pkg"}) constant followed by a colon ({@code ':'}).
70+
*/
71+
private static final String SCHEME_PART = SCHEME + ':';
72+
73+
/**
74+
* The package "type" or package "protocol" such as maven, npm, nuget, gem, pypi, etc.
75+
* Required.
76+
*/
77+
private String type;
78+
79+
/**
80+
* The name prefix such as a Maven groupid, a Docker image owner, a GitHub user or organization.
81+
* Optional and type-specific.
82+
*/
83+
private @Nullable String namespace;
84+
85+
/**
86+
* The name of the package.
87+
* Required.
88+
*/
89+
private String name;
90+
91+
/**
92+
* The version of the package.
93+
* Optional.
94+
*/
95+
private @Nullable String version;
96+
97+
/**
98+
* Extra qualifying data for a package such as an OS, architecture, a distro, etc.
99+
* Optional and type-specific.
100+
*/
101+
private @Nullable Map<String, String> qualifiers;
102+
103+
/**
104+
* Extra subpath within a package, relative to the package root.
105+
* Optional.
106+
*/
107+
private @Nullable String subpath;
108+
63109
/**
64110
* Constructs a new PackageURL object by parsing the specified string.
65111
*
@@ -130,60 +176,14 @@ public PackageURL(
130176
final @Nullable String subpath)
131177
throws MalformedPackageURLException {
132178
this.type = toLowerCase(validateType(requireNonNull(type, "type")));
133-
this.namespace = validateNamespace(namespace);
134-
this.name = validateName(requireNonNull(name, "name"));
135-
this.version = validateVersion(type, version);
179+
this.namespace = validateNamespace(this.type, namespace);
180+
this.name = validateName(this.type, requireNonNull(name, "name"));
181+
this.version = validateVersion(this.type, version);
136182
this.qualifiers = parseQualifiers(qualifiers);
137183
this.subpath = validateSubpath(subpath);
138184
verifyTypeConstraints(this.type, this.namespace, this.name);
139185
}
140186

141-
/**
142-
* The PackageURL scheme constant
143-
*/
144-
public static final String SCHEME = "pkg";
145-
146-
/**
147-
* The PackageURL scheme ({@code "pkg"}) constant followed by a colon ({@code ':'}).
148-
*/
149-
private static final String SCHEME_PART = SCHEME + ':';
150-
151-
/**
152-
* The package "type" or package "protocol" such as maven, npm, nuget, gem, pypi, etc.
153-
* Required.
154-
*/
155-
private String type;
156-
157-
/**
158-
* The name prefix such as a Maven groupId, a Docker image owner, a GitHub user or organization.
159-
* Optional and type-specific.
160-
*/
161-
private @Nullable String namespace;
162-
163-
/**
164-
* The name of the package.
165-
* Required.
166-
*/
167-
private String name;
168-
169-
/**
170-
* The version of the package.
171-
* Optional.
172-
*/
173-
private @Nullable String version;
174-
175-
/**
176-
* Extra qualifying data for a package such as an OS, architecture, a distro, etc.
177-
* Optional and type-specific.
178-
*/
179-
private @Nullable Map<String, String> qualifiers;
180-
181-
/**
182-
* Extra subpath within a package, relative to the package root.
183-
* Optional.
184-
*/
185-
private @Nullable String subpath;
186-
187187
/**
188188
* Converts this {@link PackageURL} to a {@link PackageURLBuilder}.
189189
*
@@ -260,7 +260,7 @@ public Map<String, String> getQualifiers() {
260260
return subpath;
261261
}
262262

263-
private void validateScheme(final String value) throws MalformedPackageURLException {
263+
private static void validateScheme(final String value) throws MalformedPackageURLException {
264264
if (!SCHEME.equals(value)) {
265265
throw new MalformedPackageURLException(
266266
"The PackageURL scheme '" + value + "' is invalid. It should be '" + SCHEME + "'");
@@ -305,14 +305,16 @@ private static void validateChars(String value, IntPredicate predicate, String c
305305
}
306306
}
307307

308-
private @Nullable String validateNamespace(final @Nullable String value) throws MalformedPackageURLException {
308+
private static @Nullable String validateNamespace(final String type, final @Nullable String value)
309+
throws MalformedPackageURLException {
309310
if (isEmpty(value)) {
310311
return null;
311312
}
312-
return validateNamespace(value.split("/"));
313+
return validateNamespace(type, value.split("/"));
313314
}
314315

315-
private @Nullable String validateNamespace(final String[] values) throws MalformedPackageURLException {
316+
private static @Nullable String validateNamespace(final String type, final String[] values)
317+
throws MalformedPackageURLException {
316318
if (values.length == 0) {
317319
return null;
318320
}
@@ -346,7 +348,7 @@ private static void validateChars(String value, IntPredicate predicate, String c
346348
return retVal;
347349
}
348350

349-
private String validateName(final String value) throws MalformedPackageURLException {
351+
private static String validateName(final String type, final String value) throws MalformedPackageURLException {
350352
if (value.isEmpty()) {
351353
throw new MalformedPackageURLException("The PackageURL name specified is invalid");
352354
}
@@ -377,7 +379,7 @@ private String validateName(final String value) throws MalformedPackageURLExcept
377379
return temp;
378380
}
379381

380-
private @Nullable String validateVersion(final String type, final @Nullable String value) {
382+
private static @Nullable String validateVersion(final String type, final @Nullable String value) {
381383
if (value == null) {
382384
return null;
383385
}
@@ -392,7 +394,7 @@ private String validateName(final String value) throws MalformedPackageURLExcept
392394
}
393395
}
394396

395-
private @Nullable Map<String, String> validateQualifiers(final @Nullable Map<String, String> values)
397+
private static @Nullable Map<String, String> validateQualifiers(final @Nullable Map<String, String> values)
396398
throws MalformedPackageURLException {
397399
if (values == null || values.isEmpty()) {
398400
return null;
@@ -422,7 +424,7 @@ private static void validateValue(final String key, final @Nullable String value
422424
}
423425
}
424426

425-
private @Nullable String validateSubpath(final @Nullable String value) throws MalformedPackageURLException {
427+
private static @Nullable String validateSubpath(final @Nullable String value) throws MalformedPackageURLException {
426428
if (isEmpty(value)) {
427429
return null;
428430
}
@@ -574,20 +576,13 @@ private static String toLowerCase(String s) {
574576
return new String(chars);
575577
}
576578

577-
private static int indexOfPercentChar(final byte[] bytes, final int start) {
578-
return IntStream.range(start, bytes.length)
579+
private static int indexOfFirstPercentChar(final byte[] bytes) {
580+
return IntStream.range(0, bytes.length)
579581
.filter(i -> isPercent(bytes[i]))
580582
.findFirst()
581583
.orElse(-1);
582584
}
583585

584-
private static int indexOfUnsafeChar(final byte[] bytes, final int start) {
585-
return IntStream.range(start, bytes.length)
586-
.filter(i -> shouldEncode(bytes[i]))
587-
.findFirst()
588-
.orElse(-1);
589-
}
590-
591586
private static byte percentDecode(final byte[] bytes, final int start) {
592587
if (start + 2 >= bytes.length) {
593588
throw new ValidationException("Incomplete percent encoding at offset " + start + " with value '"
@@ -621,7 +616,7 @@ static String percentDecode(final String source) {
621616
}
622617

623618
byte[] bytes = source.getBytes(StandardCharsets.UTF_8);
624-
int i = indexOfPercentChar(bytes, 0);
619+
int i = indexOfFirstPercentChar(bytes);
625620

626621
if (i == -1) {
627622
return source;
@@ -764,11 +759,11 @@ private void parse(final String purl) throws MalformedPackageURLException {
764759
// The 'remainder' should now consist of an optional namespace and the name
765760
index = remainder.lastIndexOf('/');
766761
if (index <= start) {
767-
this.name = validateName(percentDecode(remainder.substring(start)));
762+
this.name = validateName(this.type, percentDecode(remainder.substring(start)));
768763
} else {
769-
this.name = validateName(percentDecode(remainder.substring(index + 1)));
764+
this.name = validateName(this.type, percentDecode(remainder.substring(index + 1)));
770765
remainder = remainder.substring(0, index);
771-
this.namespace = validateNamespace(parsePath(remainder.substring(start), false));
766+
this.namespace = validateNamespace(this.type, parsePath(remainder.substring(start), false));
772767
}
773768
verifyTypeConstraints(this.type, this.namespace, this.name);
774769
} catch (URISyntaxException e) {
@@ -782,7 +777,7 @@ private void parse(final String purl) throws MalformedPackageURLException {
782777
* @param namespace the purl namespace
783778
* @throws MalformedPackageURLException if constraints are not met
784779
*/
785-
private void verifyTypeConstraints(String type, @Nullable String namespace, @Nullable String name)
780+
private static void verifyTypeConstraints(String type, @Nullable String namespace, @Nullable String name)
786781
throws MalformedPackageURLException {
787782
if (StandardTypes.MAVEN.equals(type)) {
788783
if (isEmpty(namespace) || isEmpty(name)) {
@@ -792,7 +787,7 @@ private void verifyTypeConstraints(String type, @Nullable String namespace, @Nul
792787
}
793788
}
794789

795-
private @Nullable Map<String, String> parseQualifiers(final @Nullable Map<String, String> qualifiers)
790+
private static @Nullable Map<String, String> parseQualifiers(final @Nullable Map<String, String> qualifiers)
796791
throws MalformedPackageURLException {
797792
if (qualifiers == null || qualifiers.isEmpty()) {
798793
return null;
@@ -812,7 +807,7 @@ private void verifyTypeConstraints(String type, @Nullable String namespace, @Nul
812807
}
813808

814809
@SuppressWarnings("StringSplitter") // reason: surprising behavior is okay in this case
815-
private @Nullable Map<String, String> parseQualifiers(final String encodedString)
810+
private static @Nullable Map<String, String> parseQualifiers(final String encodedString)
816811
throws MalformedPackageURLException {
817812
try {
818813
final TreeMap<String, String> results = Arrays.stream(encodedString.split("&"))
@@ -836,14 +831,14 @@ private void verifyTypeConstraints(String type, @Nullable String namespace, @Nul
836831
}
837832
}
838833

839-
private String[] parsePath(final String path, final boolean isSubpath) {
834+
private static String[] parsePath(final String path, final boolean isSubpath) {
840835
return Arrays.stream(path.split("/"))
841836
.filter(segment -> !segment.isEmpty() && !(isSubpath && (".".equals(segment) || "..".equals(segment))))
842837
.map(PackageURL::percentDecode)
843838
.toArray(String[]::new);
844839
}
845840

846-
private String encodePath(final String path) {
841+
private static String encodePath(final String path) {
847842
return Arrays.stream(path.split("/")).map(PackageURL::percentEncode).collect(Collectors.joining("/"));
848843
}
849844

0 commit comments

Comments
 (0)