Skip to content

Commit

Permalink
Fix URL handling issue (#766)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukehutch committed May 8, 2023
1 parent 1907341 commit 4113c9e
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -312,60 +312,55 @@ public boolean addClasspathEntry(final Object pathElement, final ClassLoader cla
if (pathElementStr.isEmpty()) {
return false;
}
URL pathElementURL;
URL pathElementURL = null;
boolean hasWildcardSuffix = false;
try {
pathElementURL = pathElement instanceof URL ? (URL) pathElement
: pathElement instanceof URI ? ((URI) pathElement).toURL()
: pathElement instanceof Path ? ((Path) pathElement).toUri().toURL()
: pathElement instanceof File ? ((File) pathElement).toURI().toURL() : null;
if (pathElementURL == null) {
// Fallback -- call toString() on the path element, then try converting to a URL
final String pathElementToStr = pathElement.toString();
if (pathElementToStr.endsWith("/*") || pathElementToStr.endsWith("\\*")) {
hasWildcardSuffix = true;
pathElementStr = pathElementToStr.substring(0, pathElementToStr.length() - 2);
// Leave pathElementURL null, so that wildcards can be handled below
} else if (pathElementToStr.equals("*")) {
hasWildcardSuffix = true;
pathElementStr = "";
// Leave pathElementURL null, so that wildcards can be handled below
} else {
final boolean hasJarScheme = pathElementToStr.startsWith("jar:");
int startIdx = hasJarScheme ? 4 : 0;
final Matcher m1 = schemeMatcher.matcher(pathElementToStr.substring(startIdx));
String scheme = "";
if (m1.find()) {
scheme = m1.group();
startIdx += scheme.length();
}
final String urlStr = (pathElementToStr.contains("!/") || hasJarScheme ? "jar:" : "")
+ (scheme.isEmpty() ? "file:" : scheme)
// Escape '%' characters (#255)
+ pathElementToStr.substring(startIdx).replace("%", "%25");
// Fallback -- call toString() on the path element, then try converting to a URL
if (pathElementStr.endsWith("/*") || pathElementStr.endsWith("\\*")) {
hasWildcardSuffix = true;
pathElementStr = pathElementStr.substring(0, pathElementStr.length() - 2);
// Leave pathElementURL null, so that wildcards can be handled below
} else if (pathElementStr.equals("*")) {
hasWildcardSuffix = true;
pathElementStr = "";
// Leave pathElementURL null, so that wildcards can be handled below
} else {
final Matcher m1 = schemeMatcher.matcher(pathElementStr);
if (m1.find()) {
// Path element string is URL with scheme other than `[jar:]file:`, so need to actually
// parse URL, since the scheme may be a custom scheme
try {
pathElementURL = pathElement instanceof URL ? (URL) pathElement
: pathElement instanceof URI ? ((URI) pathElement).toURL()
: pathElement instanceof Path ? ((Path) pathElement).toUri().toURL()
: pathElement instanceof File ? ((File) pathElement).toURI().toURL()
: null;
} catch (final MalformedURLException | IllegalArgumentException | IOError | SecurityException e2) {
// Fall through
}
if (pathElementURL == null) {
final String urlStr = pathElementStr.replace("%", "%25");
try {
pathElementURL = new URL(urlStr);
} catch (final MalformedURLException e) {
try {
pathElementURL = new File(pathElementToStr).toURI().toURL();
pathElementURL = new File(urlStr).toURI().toURL();
} catch (final MalformedURLException | IllegalArgumentException | IOError
| SecurityException e1) {
if (log != null) {
log.log("Failed to convert classpath element to URL, "
+ "Try prepending \"file:\" to create a URL (" + e1 + "): "
+ pathElementStr);
}
// Final fallback -- try just using the raw string as a URL
pathElementURL = new URL(pathElementToStr);
try {
pathElementURL = new URL(pathElementStr);
} catch (final MalformedURLException e2) {
// Fall through
}
}
}
}
if (pathElementURL == null) {
if (log != null) {
log.log("Failed to convert classpath element to URL: " + pathElement);
}
}
}
} catch (final MalformedURLException | IllegalArgumentException | IOError | SecurityException e2) {
if (log != null) {
log.log("Cannot convert to URL (" + e2 + "): " + pathElement);
}
pathElementURL = null;
}
if (pathElementURL != null || pathElement instanceof URI || pathElement instanceof File
|| pathElement instanceof Path) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.github.classgraph.issues.issue766;

import static org.assertj.core.api.Assertions.assertThat;

import java.net.URL;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;

import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;

public class ClassgraphIssue766 {

@Test
public void testURLs() {
final URL url = ClassgraphIssue766.class.getResource("/issue766/ProjectWithAnnotations.iar");

final String fileUrl = "file:" + url.getPath();
final String jarFileUrl = "jar:file:" + url.getPath();
final String jarUrl = "jar:///" + url.getPath();

assertThat(scan("javax.annotation.ManagedBean", fileUrl)).containsOnly("ch.ivyteam.test.MyManagedBean");
assertThat(scan("javax.annotation.ManagedBean", jarFileUrl)).containsOnly("ch.ivyteam.test.MyManagedBean");
assertThat(scan("javax.annotation.ManagedBean", jarUrl)).containsOnly("ch.ivyteam.test.MyManagedBean");
}

public static Set<String> scan(final String annotation, final String url) {
final ClassGraph classGraph = new ClassGraph()
.overrideClasspath(Set.of(url)).disableNestedJarScanning().enableAnnotationInfo();
try (ScanResult result = classGraph.scan()) {
return result.getClassesWithAnnotation(annotation).getStandardClasses().getNames().stream()
.collect(Collectors.toSet());
}
}
}
Binary file not shown.

0 comments on commit 4113c9e

Please sign in to comment.