8304163: Move jdk.internal.module.ModuleInfoWriter to the test library

Reviewed-by: jpai, alanb
This commit is contained in:
Mandy Chung 2023-03-20 17:30:24 +00:00
parent 4c8c9935eb
commit 622f239448
17 changed files with 135 additions and 63 deletions

View file

@ -1,234 +0,0 @@
/*
* Copyright (c) 2015, 2020, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.module;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.constant.ClassDesc;
import java.lang.module.ModuleDescriptor;
import java.lang.reflect.AccessFlag;
import java.nio.ByteBuffer;
import java.util.Map;
import jdk.internal.classfile.Classfile;
import jdk.internal.classfile.java.lang.constant.PackageDesc;
import jdk.internal.classfile.attribute.ModuleAttribute;
import jdk.internal.classfile.attribute.ModuleExportInfo;
import jdk.internal.classfile.attribute.ModuleMainClassAttribute;
import jdk.internal.classfile.attribute.ModuleOpenInfo;
import jdk.internal.classfile.attribute.ModulePackagesAttribute;
import jdk.internal.classfile.attribute.ModuleResolutionAttribute;
import jdk.internal.classfile.attribute.ModuleRequireInfo;
import jdk.internal.classfile.attribute.ModuleTargetAttribute;
import jdk.internal.classfile.constantpool.ModuleEntry;
/**
* Utility class to write a ModuleDescriptor as a module-info.class.
*/
public final class ModuleInfoWriter {
private static final Map<ModuleDescriptor.Modifier, Integer>
MODULE_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Modifier.OPEN, Classfile.ACC_OPEN,
ModuleDescriptor.Modifier.SYNTHETIC, Classfile.ACC_SYNTHETIC,
ModuleDescriptor.Modifier.MANDATED, Classfile.ACC_MANDATED
);
private static final Map<ModuleDescriptor.Requires.Modifier, Integer>
REQUIRES_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Requires.Modifier.TRANSITIVE, Classfile.ACC_TRANSITIVE,
ModuleDescriptor.Requires.Modifier.STATIC, Classfile.ACC_STATIC_PHASE,
ModuleDescriptor.Requires.Modifier.SYNTHETIC, Classfile.ACC_SYNTHETIC,
ModuleDescriptor.Requires.Modifier.MANDATED, Classfile.ACC_MANDATED
);
private static final Map<ModuleDescriptor.Exports.Modifier, Integer>
EXPORTS_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Exports.Modifier.SYNTHETIC, Classfile.ACC_SYNTHETIC,
ModuleDescriptor.Exports.Modifier.MANDATED, Classfile.ACC_MANDATED
);
private static final Map<ModuleDescriptor.Opens.Modifier, Integer>
OPENS_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Opens.Modifier.SYNTHETIC, Classfile.ACC_SYNTHETIC,
ModuleDescriptor.Opens.Modifier.MANDATED, Classfile.ACC_MANDATED
);
private ModuleInfoWriter() { }
/**
* Writes the given module descriptor to a module-info.class file,
* returning it in a byte array.
*/
private static byte[] toModuleInfo(ModuleDescriptor md,
ModuleResolution mres,
ModuleTarget target) {
//using low-level module building to avoid validation in ModuleDesc and allow invalid names
return Classfile.build(ClassDesc.of("module-info"), clb -> {
clb.withFlags(AccessFlag.MODULE);
var cp = clb.constantPool();
clb.with(ModuleAttribute.of(cp.moduleEntry(cp.utf8Entry(md.name())), mb -> {
mb.moduleFlags(md.modifiers().stream()
.mapToInt(mm -> MODULE_MODS_TO_FLAGS.getOrDefault(mm, 0))
.reduce(0, (x, y) -> (x | y)));
md.rawVersion().ifPresent(vs -> mb.moduleVersion(vs));
// requires
for (ModuleDescriptor.Requires r : md.requires()) {
int flags = r.modifiers().stream()
.mapToInt(REQUIRES_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
mb.requires(ModuleRequireInfo.of(
cp.moduleEntry(cp.utf8Entry(r.name())),
flags,
r.rawCompiledVersion().map(cp::utf8Entry).orElse(null)));
}
// exports
for (ModuleDescriptor.Exports e : md.exports()) {
int flags = e.modifiers().stream()
.mapToInt(EXPORTS_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
var targets = e.targets().stream().map(mn -> cp.moduleEntry(cp.utf8Entry(mn)))
.toArray(ModuleEntry[]::new);
mb.exports(ModuleExportInfo.of(
cp.packageEntry(cp.utf8Entry(e.source())),
flags,
targets));
}
// opens
for (ModuleDescriptor.Opens opens : md.opens()) {
int flags = opens.modifiers().stream()
.mapToInt(OPENS_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
var targets = opens.targets().stream().map(mn -> cp.moduleEntry(cp.utf8Entry(mn)))
.toArray(ModuleEntry[]::new);
mb.opens(ModuleOpenInfo.of(
cp.packageEntry(cp.utf8Entry(opens.source())),
flags,
targets));
}
// uses
md.uses().stream().map(ClassDesc::of).forEach(mb::uses);
// provides
for (ModuleDescriptor.Provides p : md.provides()) {
mb.provides(ClassDesc.of(p.service()),
p.providers().stream()
.map(ClassDesc::of)
.toArray(ClassDesc[]::new));
}
}));
// packages
var packages = md.packages().stream().sorted().map(PackageDesc::of).toList();
if (!packages.isEmpty()) {
clb.with(ModulePackagesAttribute.ofNames(packages));
}
// ModuleMainClass attribute
md.mainClass().ifPresent(mc ->
clb.with(ModuleMainClassAttribute.of(ClassDesc.of(mc))));
// write ModuleResolution attribute if specified
if (mres != null) {
clb.with(ModuleResolutionAttribute.of(mres.value()));
}
// write ModuleTarget attribute if there is a target platform
if (target != null && !target.targetPlatform().isEmpty()) {
clb.with(ModuleTargetAttribute.of(target.targetPlatform()));
}
});
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
*/
public static void write(ModuleDescriptor descriptor,
ModuleResolution mres,
ModuleTarget target,
OutputStream out)
throws IOException
{
byte[] bytes = toModuleInfo(descriptor, mres, target);
out.write(bytes);
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
*/
public static void write(ModuleDescriptor descriptor,
ModuleResolution mres,
OutputStream out)
throws IOException
{
write(descriptor, mres, null, out);
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
*/
public static void write(ModuleDescriptor descriptor,
ModuleTarget target,
OutputStream out)
throws IOException
{
write(descriptor, null, target, out);
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
*/
public static void write(ModuleDescriptor descriptor, OutputStream out)
throws IOException
{
write(descriptor, null, null, out);
}
/**
* Returns a byte array containing the given module descriptor in
* module-info.class format.
*/
public static byte[] toBytes(ModuleDescriptor descriptor) {
return toModuleInfo(descriptor, null, null);
}
/**
* Returns a {@code ByteBuffer} containing the given module descriptor
* in module-info.class format.
*/
public static ByteBuffer toByteBuffer(ModuleDescriptor descriptor) {
byte[] bytes = toModuleInfo(descriptor, null, null);
return ByteBuffer.wrap(bytes);
}
}