下面列出了java.lang.module.ModuleReference#descriptor ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Creates a {@code Loader} in a loader pool that loads classes/resources
* from one module.
*/
public Loader(ResolvedModule resolvedModule,
LoaderPool pool,
ClassLoader parent)
{
super("Loader-" + resolvedModule.name(), parent);
this.pool = pool;
this.parent = parent;
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
String mn = descriptor.name();
this.nameToModule = Map.of(mn, mref);
Map<String, LoadedModule> localPackageToModule = new HashMap<>();
LoadedModule lm = new LoadedModule(mref);
descriptor.packages().forEach(pn -> localPackageToModule.put(pn, lm));
this.localPackageToModule = localPackageToModule;
this.acc = AccessController.getContext();
}
/**
* Creates a {@code Loader} that loads classes/resources from a collection
* of modules.
*
* @throws IllegalArgumentException
* If two or more modules have the same package
*/
public Loader(Collection<ResolvedModule> modules, ClassLoader parent) {
super(parent);
this.pool = null;
this.parent = parent;
Map<String, ModuleReference> nameToModule = new HashMap<>();
Map<String, LoadedModule> localPackageToModule = new HashMap<>();
for (ResolvedModule resolvedModule : modules) {
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
nameToModule.put(descriptor.name(), mref);
descriptor.packages().forEach(pn -> {
LoadedModule lm = new LoadedModule(mref);
if (localPackageToModule.put(pn, lm) != null)
throw new IllegalArgumentException("Package "
+ pn + " in more than one module");
});
}
this.nameToModule = nameToModule;
this.localPackageToModule = localPackageToModule;
this.acc = AccessController.getContext();
}
public Module toModule(ModuleReference mref) {
try {
String mn = mref.descriptor().name();
URI location = mref.location().orElseThrow(FileNotFoundException::new);
ModuleDescriptor md = mref.descriptor();
Module.Builder builder = new Module.Builder(md, system.find(mn).isPresent());
final ClassFileReader reader;
if (location.getScheme().equals("jrt")) {
reader = system.getClassReader(mn);
} else {
reader = ClassFileReader.newInstance(Paths.get(location), version);
}
builder.classes(reader);
builder.location(location);
return builder.build();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/**
* Creates a {@code Loader} in a loader pool that loads classes/resources
* from one module.
*/
public Loader(ResolvedModule resolvedModule,
LoaderPool pool,
ClassLoader parent)
{
super("Loader-" + resolvedModule.name(), parent);
this.pool = pool;
this.parent = parent;
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
String mn = descriptor.name();
this.nameToModule = Map.of(mn, mref);
Map<String, LoadedModule> localPackageToModule = new HashMap<>();
LoadedModule lm = new LoadedModule(mref);
descriptor.packages().forEach(pn -> localPackageToModule.put(pn, lm));
this.localPackageToModule = localPackageToModule;
this.acc = AccessController.getContext();
}
/**
* Creates a {@code Loader} that loads classes/resources from a collection
* of modules.
*
* @throws IllegalArgumentException
* If two or more modules have the same package
*/
public Loader(Collection<ResolvedModule> modules, ClassLoader parent) {
super(parent);
this.pool = null;
this.parent = parent;
Map<String, ModuleReference> nameToModule = new HashMap<>();
Map<String, LoadedModule> localPackageToModule = new HashMap<>();
for (ResolvedModule resolvedModule : modules) {
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
nameToModule.put(descriptor.name(), mref);
descriptor.packages().forEach(pn -> {
LoadedModule lm = new LoadedModule(mref);
if (localPackageToModule.put(pn, lm) != null)
throw new IllegalArgumentException("Package "
+ pn + " in more than one module");
});
}
this.nameToModule = nameToModule;
this.localPackageToModule = localPackageToModule;
this.acc = AccessController.getContext();
}
/**
* Returns true if the given module opens the given package
* unconditionally.
*
* @implNote This method currently iterates over each of the open
* packages. This will be replaced once the ModuleDescriptor.Opens
* API is updated.
*/
private boolean isOpen(ModuleReference mref, String pn) {
ModuleDescriptor descriptor = mref.descriptor();
if (descriptor.isOpen() || descriptor.isAutomatic())
return true;
for (ModuleDescriptor.Opens opens : descriptor.opens()) {
String source = opens.source();
if (!opens.isQualified() && source.equals(pn)) {
return true;
}
}
return false;
}
/**
* Returns true if the given module opens the given package
* unconditionally.
*
* @implNote This method currently iterates over each of the open
* packages. This will be replaced once the ModuleDescriptor.Opens
* API is updated.
*/
private boolean isOpen(ModuleReference mref, String pn) {
ModuleDescriptor descriptor = mref.descriptor();
if (descriptor.isOpen() || descriptor.isAutomatic())
return true;
for (ModuleDescriptor.Opens opens : descriptor.opens()) {
String source = opens.source();
if (!opens.isQualified() && source.equals(pn)) {
return true;
}
}
return false;
}
/**
* Prints the module location and name.
*/
private void printModule(ModuleReference mref) {
mref.location()
.filter(uri -> !isJrt(uri))
.ifPresent(uri -> out.print(uri + " "));
ModuleDescriptor descriptor = mref.descriptor();
out.print(descriptor.name());
if (descriptor.isAutomatic())
out.print(" automatic");
out.println();
}
/**
* Prints a single line with the module name, version and modifiers
*/
private static void showModule(ModuleReference mref) {
ModuleDescriptor md = mref.descriptor();
ostream.print(md.toNameAndVersion());
mref.location()
.filter(uri -> !isJrt(uri))
.ifPresent(uri -> ostream.format(" %s", uri));
if (md.isOpen())
ostream.print(" open");
if (md.isAutomatic())
ostream.print(" automatic");
ostream.println();
}
/**
* Returns true if the given module opens the given package
* unconditionally.
*
* @implNote This method currently iterates over each of the open
* packages. This will be replaced once the ModuleDescriptor.Opens
* API is updated.
*/
private boolean isOpen(ModuleReference mref, String pn) {
ModuleDescriptor descriptor = mref.descriptor();
if (descriptor.isOpen() || descriptor.isAutomatic())
return true;
for (ModuleDescriptor.Opens opens : descriptor.opens()) {
String source = opens.source();
if (!opens.isQualified() && source.equals(pn)) {
return true;
}
}
return false;
}
/**
* Returns true if the given module opens the given package
* unconditionally.
*
* @implNote This method currently iterates over each of the open
* packages. This will be replaced once the ModuleDescriptor.Opens
* API is updated.
*/
private boolean isOpen(ModuleReference mref, String pn) {
ModuleDescriptor descriptor = mref.descriptor();
if (descriptor.isOpen() || descriptor.isAutomatic())
return true;
for (ModuleDescriptor.Opens opens : descriptor.opens()) {
String source = opens.source();
if (!opens.isQualified() && source.equals(pn)) {
return true;
}
}
return false;
}
/**
* Prints a single line with the module name, version and modifiers
*/
private static void showModule(ModuleReference mref) {
ModuleDescriptor md = mref.descriptor();
ostream.print(md.toNameAndVersion());
mref.location()
.filter(uri -> !isJrt(uri))
.ifPresent(uri -> ostream.format(" %s", uri));
if (md.isOpen())
ostream.print(" open");
if (md.isAutomatic())
ostream.print(" automatic");
ostream.println();
}
/**
* Prints the module location and name.
*/
private void printModule(ModuleReference mref) {
mref.location()
.filter(uri -> !isJrt(uri))
.ifPresent(uri -> ostream.print(uri + " "));
ModuleDescriptor descriptor = mref.descriptor();
ostream.print(descriptor.name());
if (descriptor.isAutomatic())
ostream.print(" automatic");
ostream.println();
}
/**
* Basic test of a multi-release JAR.
*/
public void testBasic() throws Exception {
String name = "m1";
ModuleDescriptor descriptor = ModuleDescriptor.newModule(name)
.requires("java.base")
.build();
Path jar = new JarBuilder(name)
.moduleInfo("module-info.class", descriptor)
.resource("p/Main.class")
.resource("p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")
.build();
// find the module
ModuleFinder finder = ModuleFinder.of(jar);
Optional<ModuleReference> omref = finder.find(name);
assertTrue((omref.isPresent()));
ModuleReference mref = omref.get();
// check module packages
descriptor = mref.descriptor();
Set<String> packages = descriptor.packages();
assertTrue(packages.contains("p"));
if (MULTI_RELEASE) {
assertTrue(packages.size() == 2);
assertTrue(packages.contains("p.internal"));
} else {
assertTrue(packages.size() == 1);
}
}
/**
* Test a multi-release JAR with a module-info.class in the versioned
* section of the JAR.
*/
public void testModuleInfoInVersionedSection() throws Exception {
String name = "m1";
ModuleDescriptor descriptor1 = ModuleDescriptor.newModule(name)
.requires("java.base")
.build();
// module descriptor for versioned section
ModuleDescriptor descriptor2 = ModuleDescriptor.newModule(name)
.requires("java.base")
.requires("jdk.unsupported")
.build();
Path jar = new JarBuilder(name)
.moduleInfo(MODULE_INFO, descriptor1)
.resource("p/Main.class")
.resource("p/Helper.class")
.moduleInfo("META-INF/versions/" + VERSION + "/" + MODULE_INFO, descriptor2)
.resource("META-INF/versions/" + VERSION + "/p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")
.build();
// find the module
ModuleFinder finder = ModuleFinder.of(jar);
Optional<ModuleReference> omref = finder.find(name);
assertTrue((omref.isPresent()));
ModuleReference mref = omref.get();
// ensure that the right module-info.class is loaded
ModuleDescriptor descriptor = mref.descriptor();
assertEquals(descriptor.name(), name);
if (MULTI_RELEASE) {
assertEquals(descriptor.requires(), descriptor2.requires());
} else {
assertEquals(descriptor.requires(), descriptor1.requires());
}
}
/**
* Test multi-release JAR as an automatic module.
*/
public void testAutomaticModule() throws Exception {
String name = "m";
Path jar = new JarBuilder(name)
.resource("p/Main.class")
.resource("p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")
.build();
// find the module
ModuleFinder finder = ModuleFinder.of(jar);
Optional<ModuleReference> omref = finder.find(name);
assertTrue((omref.isPresent()));
ModuleReference mref = omref.get();
// check module packages
ModuleDescriptor descriptor = mref.descriptor();
Set<String> packages = descriptor.packages();
if (MULTI_RELEASE) {
assertTrue(packages.size() == 2);
assertTrue(packages.contains("p.internal"));
} else {
assertTrue(packages.size() == 1);
}
}
/**
* Test JAR files with the Automatic-Module-Name attribute
*/
@Test(dataProvider = "modulenames")
public void testAutomaticModuleNameAttribute(String name, String vs)
throws IOException
{
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attrs.put(new Attributes.Name("Automatic-Module-Name"), name);
Path dir = Files.createTempDirectory(USER_DIR, "mods");
String jar;
if (vs == null) {
jar = "m.jar";
} else {
jar = "m-" + vs + ".jar";
}
createDummyJarFile(dir.resolve(jar), man);
ModuleFinder finder = ModuleFinder.of(dir);
assertTrue(finder.findAll().size() == 1);
assertTrue(finder.find(name).isPresent());
ModuleReference mref = finder.find(name).get();
ModuleDescriptor descriptor = mref.descriptor();
assertEquals(descriptor.name(), name);
assertEquals(descriptor.version()
.map(ModuleDescriptor.Version::toString)
.orElse(null), vs);
}
private static void checkArtifactModuleName(Log log, String moduleName, ModuleReference moduleReference, ArtifactDescriptor resolvedArtifact) {
var descriptor = moduleReference.descriptor();
if (descriptor.isAutomatic()) {
return;
}
var artifactModuleName = descriptor.name();
if (!artifactModuleName.equals(moduleName)) {
log.info(null, __ -> "WARNING! artifact module name " + artifactModuleName + " (" + resolvedArtifact + ") declared in the module-info is different from declared module name " + moduleName);
}
}
ModuleSummary(ModuleReference mref, Path jmod) throws IOException {
this.name = mref.descriptor().name();
this.descriptor = mref.descriptor();
this.jmodInfo = new JmodInfo(jmod);
}
private static void rewrite(ModuleReference rootModule, LinkedHashSet<String> dependencies, LinkedHashSet<String> requires, Set<String> packages, ModuleFinder finder, Path destination) throws IOException {
// create a map old package name -> new package name
var rootModuleName = rootModule.descriptor().name();
var internalRootModuleName = rootModuleName.replace('.', '/');
var internalPackageNameMap = packages.stream()
.map(name -> name.replace('.', '/'))
.collect(toUnmodifiableMap(name -> name, name -> internalRootModuleName + '/' + name));
//System.out.println(internalPackageNameMap);
var newPackages = new HashSet<String>();
Path path = destination.resolve(rootModuleName + ".jar");
Files.createDirectories(path.getParent());
try(var output = Files.newOutputStream(path);
var outputStream = new JarOutputStream(output)) {
// rewrite all the classes of the dependencies
var entryNames = new HashSet<>();
for(var dependency: dependencies) {
var reference = finder.find(dependency).orElseThrow();
try(var reader = reference.open()) {
for(String filename: (Iterable<String>)reader.list()::iterator) {
//System.out.println("filename " + filename);
if (filename.equals("module-info.class") || // skip module-info
filename.endsWith("/") || // skip all directories
filename.startsWith("META-INF")) { // skip META-INF
continue;
}
if (!entryNames.add(filename)) {
System.out.println("duplicate entry " + filename + " skip it !");
continue;
}
try(var inputStream = reader.open(filename).orElseThrow(() -> new IOException("can not read " + filename))) {
if (!filename.endsWith(".class")) { // only rewrite .class
// otherwise copy the resources
getPackage(filename).ifPresent(newPackages::add);
outputStream.putNextEntry(new JarEntry(filename));
inputStream.transferTo(outputStream);
continue;
}
var newFilename = interpolateInternalName(internalPackageNameMap, filename);
getPackage(newFilename).ifPresent(newPackages::add);
outputStream.putNextEntry(new JarEntry(newFilename));
outputStream.write(rewriteBytecode(internalPackageNameMap, inputStream.readAllBytes()));
}
}
}
}
// then insert the new module-info and interpolate it
outputStream.putNextEntry(new JarEntry("module-info.class"));
var builder = ModuleDescriptor.newOpenModule(rootModuleName);
var rootModuleDescriptor = rootModule.descriptor();
rootModuleDescriptor.version().ifPresent(builder::version);
requires.forEach(builder::requires);
rootModuleDescriptor.exports().forEach(builder::exports);
rootModuleDescriptor.opens().forEach(builder::opens);
builder.packages(rootModuleDescriptor.packages());
dependencies.stream()
.flatMap(name -> finder.find(name).stream())
.map(ModuleReference::descriptor)
.forEach(descriptor -> {
descriptor.provides().forEach(provides -> {
builder.provides(
interpolateClassName(internalPackageNameMap, provides.service()),
provides.providers().stream().map(provider -> interpolateClassName(internalPackageNameMap, provider)).collect(toUnmodifiableList())
);
});
descriptor.uses().forEach(uses -> builder.uses(interpolateClassName(internalPackageNameMap, uses)));
});
builder.packages(newPackages);
var moduleDescriptor = builder.build();
outputStream.write(ModuleHelper.moduleDescriptorToBinary(moduleDescriptor));
}
}