8332226: "Invalid package name:" from source launcher
Reviewed-by: alanb
This commit is contained in:
parent
5a2ba952b1
commit
f16265d69b
src/jdk.compiler/share/classes/com/sun/tools/javac/launcher
test/langtools/tools/javac/launcher
@ -32,6 +32,7 @@ import com.sun.tools.javac.resources.LauncherProperties.Errors;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.module.InvalidModuleDescriptorException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@ -39,6 +40,10 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.lang.model.SourceVersion;
|
||||
|
||||
/**
|
||||
* Describes a launch-able Java compilation unit.
|
||||
@ -113,25 +118,62 @@ public record ProgramDescriptor(
|
||||
}
|
||||
|
||||
public Set<String> computePackageNames() {
|
||||
try (var stream = Files.find(sourceRootPath, 99, (path, attr) -> attr.isDirectory())) {
|
||||
var names = new TreeSet<String>();
|
||||
stream.filter(ProgramDescriptor::containsAtLeastOneRegularFile)
|
||||
.map(sourceRootPath::relativize)
|
||||
.map(Path::toString)
|
||||
.filter(string -> !string.isEmpty())
|
||||
.map(string -> string.replace(File.separatorChar, '.'))
|
||||
.forEach(names::add);
|
||||
return names;
|
||||
} catch (IOException exception) {
|
||||
throw new UncheckedIOException(exception);
|
||||
return explodedPackages(sourceRootPath);
|
||||
}
|
||||
|
||||
// -- exploded directories --> based on jdk.internal.module.ModulePath
|
||||
|
||||
private static Set<String> explodedPackages(Path dir) {
|
||||
String separator = dir.getFileSystem().getSeparator();
|
||||
try (Stream<Path> stream = Files.find(dir, Integer.MAX_VALUE,
|
||||
(path, attrs) -> attrs.isRegularFile() && !isHidden(path))) {
|
||||
return stream.map(dir::relativize)
|
||||
.map(path -> toPackageName(path, separator))
|
||||
.flatMap(Optional::stream)
|
||||
.collect(Collectors.toSet());
|
||||
} catch (IOException x) {
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean containsAtLeastOneRegularFile(Path directory) {
|
||||
try (var stream = Files.newDirectoryStream(directory, Files::isRegularFile)) {
|
||||
return stream.iterator().hasNext();
|
||||
} catch (IOException exception) {
|
||||
throw new UncheckedIOException(exception);
|
||||
/**
|
||||
* Maps the relative path of an entry in an exploded module to a package
|
||||
* name.
|
||||
*
|
||||
* @throws InvalidModuleDescriptorException if the name is a class file in
|
||||
* the top-level directory (and it's not module-info.class)
|
||||
*/
|
||||
private static Optional<String> toPackageName(Path file, String separator) {
|
||||
assert file.getRoot() == null;
|
||||
|
||||
Path parent = file.getParent();
|
||||
if (parent == null) {
|
||||
String name = file.toString();
|
||||
if (name.endsWith(".class") && !name.equals("module-info.class")) {
|
||||
String msg = name + " found in top-level directory"
|
||||
+ " (unnamed package not allowed in module)";
|
||||
throw new InvalidModuleDescriptorException(msg);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String pn = parent.toString().replace(separator, ".");
|
||||
if (SourceVersion.isName(pn)) {
|
||||
return Optional.of(pn);
|
||||
} else {
|
||||
// not a valid package name
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given file exists and is a hidden file
|
||||
*/
|
||||
private static boolean isHidden(Path file) {
|
||||
try {
|
||||
return Files.isHidden(file);
|
||||
} catch (IOException ioe) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8304400
|
||||
* @bug 8304400 8332226
|
||||
* @summary Test source launcher running Java programs contained in one module
|
||||
* @modules jdk.compiler/com.sun.tools.javac.launcher
|
||||
* @run junit ModuleSourceLauncherTests
|
||||
@ -112,6 +112,8 @@ class ModuleSourceLauncherTests {
|
||||
Files.writeString(barFolder.resolve("Bar.java"), "package bar; public record Bar() {}");
|
||||
var bazFolder = Files.createDirectories(base.resolve("baz"));
|
||||
Files.writeString(bazFolder.resolve("baz.txt"), "baz");
|
||||
var badFolder = Files.createDirectories(base.resolve(".bad"));
|
||||
Files.writeString(badFolder.resolve("bad.txt"), "bad");
|
||||
|
||||
Files.writeString(base.resolve("module-info.java"),
|
||||
"""
|
||||
@ -140,8 +142,11 @@ class ModuleSourceLauncherTests {
|
||||
assertEquals("m", module.getName());
|
||||
var reference = module.getLayer().configuration().findModule(module.getName()).orElseThrow().reference();
|
||||
try (var reader = reference.open()) {
|
||||
var actual = reader.list().toList();
|
||||
assertLinesMatch(
|
||||
"""
|
||||
.bad/
|
||||
.bad/bad.txt
|
||||
bar/
|
||||
bar/Bar.class
|
||||
bar/Bar.java
|
||||
@ -152,8 +157,8 @@ class ModuleSourceLauncherTests {
|
||||
foo/Main.java
|
||||
module-info.class
|
||||
module-info.java
|
||||
""".lines(),
|
||||
reader.list());
|
||||
""".lines().toList(),
|
||||
actual, "Actual lines -> " + actual);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user