Generate module-info without bnd-plugin
This commit is contained in:
parent
b20f0db2d6
commit
d4756bd2ef
614
0001-Generate-the-module-info-classes-without-Bnd.-Delete.patch
Normal file
614
0001-Generate-the-module-info-classes-without-Bnd.-Delete.patch
Normal file
@ -0,0 +1,614 @@
|
|||||||
|
From 5921eb2a141f0dcc83c6a5d7dcd5035a30c5edfc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Bruneton <ebruneton@free.fr>
|
||||||
|
Date: Sun, 31 Jul 2022 12:21:41 +0000
|
||||||
|
Subject: [PATCH] Generate the module info classes without Bnd. Delete the Bnd
|
||||||
|
plugin.
|
||||||
|
|
||||||
|
---
|
||||||
|
.../asm/tools/ModuleInfoBndPlugin.java | 99 ------
|
||||||
|
.../org/objectweb/asm/tools/Retrofitter.java | 336 +++++++++++++-----
|
||||||
|
4 files changed, 267 insertions(+), 206 deletions(-)
|
||||||
|
delete mode 100644 tools/bnd-module-plugin/src/main/java/org/objectweb/asm/tools/ModuleInfoBndPlugin.java
|
||||||
|
|
||||||
|
diff --git a/tools/bnd-module-plugin/src/main/java/org/objectweb/asm/tools/ModuleInfoBndPlugin.java b/tools/bnd-module-plugin/src/main/java/org/objectweb/asm/tools/ModuleInfoBndPlugin.java
|
||||||
|
deleted file mode 100644
|
||||||
|
index ee91bdc1..00000000
|
||||||
|
--- a/tools/bnd-module-plugin/src/main/java/org/objectweb/asm/tools/ModuleInfoBndPlugin.java
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,99 +0,0 @@
|
||||||
|
-// ASM: a very small and fast Java bytecode manipulation framework
|
||||||
|
-// Copyright (c) 2000-2011 INRIA, France Telecom
|
||||||
|
-// All rights reserved.
|
||||||
|
-//
|
||||||
|
-// Redistribution and use in source and binary forms, with or without
|
||||||
|
-// modification, are permitted provided that the following conditions
|
||||||
|
-// are met:
|
||||||
|
-// 1. Redistributions of source code must retain the above copyright
|
||||||
|
-// notice, this list of conditions and the following disclaimer.
|
||||||
|
-// 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
-// notice, this list of conditions and the following disclaimer in the
|
||||||
|
-// documentation and/or other materials provided with the distribution.
|
||||||
|
-// 3. Neither the name of the copyright holders nor the names of its
|
||||||
|
-// contributors may be used to endorse or promote products derived from
|
||||||
|
-// this software without specific prior written permission.
|
||||||
|
-//
|
||||||
|
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
-// THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
-package org.objectweb.asm.tools;
|
||||||
|
-
|
||||||
|
-import aQute.bnd.header.Attrs;
|
||||||
|
-import aQute.bnd.header.Parameters;
|
||||||
|
-import aQute.bnd.osgi.Analyzer;
|
||||||
|
-import aQute.bnd.osgi.Constants;
|
||||||
|
-import aQute.bnd.osgi.EmbeddedResource;
|
||||||
|
-import aQute.bnd.service.AnalyzerPlugin;
|
||||||
|
-import org.objectweb.asm.ClassWriter;
|
||||||
|
-import org.objectweb.asm.ModuleVisitor;
|
||||||
|
-import org.objectweb.asm.Opcodes;
|
||||||
|
-
|
||||||
|
-/**
|
||||||
|
- * An biz.aQute.bnd plugin to generate a module-info class from the name, version, requires and
|
||||||
|
- * export properties of the bundle.
|
||||||
|
- *
|
||||||
|
- * @author Remi Forax
|
||||||
|
- */
|
||||||
|
-public class ModuleInfoBndPlugin implements AnalyzerPlugin {
|
||||||
|
- private static final String MODULE_NAME = "Module-Name";
|
||||||
|
- private static final String MODULE_VERSION = "Module-Version";
|
||||||
|
- private static final String MODULE_REQUIRES = "Module-Requires";
|
||||||
|
- private static final String MODULE_EXPORTS = "Module-Exports";
|
||||||
|
-
|
||||||
|
- @Override
|
||||||
|
- public boolean analyzeJar(final Analyzer analyzer) throws Exception {
|
||||||
|
- ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
- classWriter.visit(Opcodes.V9, Opcodes.ACC_MODULE, "module-info", null, null, null);
|
||||||
|
- String moduleName =
|
||||||
|
- analyzer.getProperty(MODULE_NAME, analyzer.getProperty(Constants.BUNDLE_SYMBOLICNAME));
|
||||||
|
- String moduleVersion =
|
||||||
|
- analyzer.getProperty(MODULE_VERSION, analyzer.getProperty(Constants.BUNDLE_VERSION));
|
||||||
|
- ModuleVisitor moduleVisitor =
|
||||||
|
- classWriter.visitModule(moduleName, Opcodes.ACC_OPEN, moduleVersion);
|
||||||
|
-
|
||||||
|
- String requireModules = analyzer.getProperty(MODULE_REQUIRES);
|
||||||
|
- if (requireModules != null) {
|
||||||
|
- Parameters requireParams = analyzer.parseHeader(requireModules);
|
||||||
|
- for (String requireName : requireParams.keySet()) {
|
||||||
|
- Attrs attrs = requireParams.get(requireName);
|
||||||
|
- boolean isTransitive = attrs.containsKey("transitive");
|
||||||
|
- boolean isStatic = attrs.containsKey("static");
|
||||||
|
- moduleVisitor.visitRequire(
|
||||||
|
- requireName,
|
||||||
|
- (isTransitive ? Opcodes.ACC_TRANSITIVE : 0) | (isStatic ? Opcodes.ACC_STATIC_PHASE : 0),
|
||||||
|
- null);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- moduleVisitor.visitRequire("java.base", Opcodes.ACC_MANDATED, null);
|
||||||
|
-
|
||||||
|
- String exportPackages =
|
||||||
|
- analyzer.getProperty(MODULE_EXPORTS, analyzer.getProperty(Constants.EXPORT_PACKAGE));
|
||||||
|
- if (exportPackages != null) {
|
||||||
|
- Parameters exportParams = analyzer.parseHeader(exportPackages);
|
||||||
|
- for (String packageName : exportParams.keySet()) {
|
||||||
|
- if (packageName.endsWith("*")) {
|
||||||
|
- throw new IllegalStateException("Unsupported wildcard packages " + packageName);
|
||||||
|
- }
|
||||||
|
- moduleVisitor.visitExport(packageName.replace('.', '/'), 0);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- moduleVisitor.visitEnd();
|
||||||
|
- classWriter.visitEnd();
|
||||||
|
-
|
||||||
|
- analyzer
|
||||||
|
- .getJar()
|
||||||
|
- .putResource(
|
||||||
|
- "module-info.class",
|
||||||
|
- new EmbeddedResource(classWriter.toByteArray(), System.currentTimeMillis()));
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
diff --git a/tools/retrofitter/src/main/java/org/objectweb/asm/tools/Retrofitter.java b/tools/retrofitter/src/main/java/org/objectweb/asm/tools/Retrofitter.java
|
||||||
|
index 2d017ed2..b3d51e63 100644
|
||||||
|
--- a/tools/retrofitter/src/main/java/org/objectweb/asm/tools/Retrofitter.java
|
||||||
|
+++ b/tools/retrofitter/src/main/java/org/objectweb/asm/tools/Retrofitter.java
|
||||||
|
@@ -27,22 +27,33 @@
|
||||||
|
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
package org.objectweb.asm.tools;
|
||||||
|
|
||||||
|
+import static java.lang.String.format;
|
||||||
|
+import static java.util.stream.Collectors.toSet;
|
||||||
|
+
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.LineNumberReader;
|
||||||
|
-import java.io.OutputStream;
|
||||||
|
+import java.lang.module.ModuleDescriptor;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
+import java.nio.file.Path;
|
||||||
|
+import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
+import java.util.List;
|
||||||
|
+import java.util.Set;
|
||||||
|
+import java.util.stream.Stream;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassVisitor;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
+import org.objectweb.asm.FieldVisitor;
|
||||||
|
import org.objectweb.asm.Handle;
|
||||||
|
+import org.objectweb.asm.Label;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
+import org.objectweb.asm.ModuleVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
@@ -57,6 +68,12 @@ import org.objectweb.asm.Type;
|
||||||
|
*/
|
||||||
|
public class Retrofitter {
|
||||||
|
|
||||||
|
+ /** The name of the module-info file. */
|
||||||
|
+ private static final String MODULE_INFO = "module-info.class";
|
||||||
|
+
|
||||||
|
+ /** The name of the java.base module. */
|
||||||
|
+ private static final String JAVA_BASE_MODULE = "java.base";
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* The fields and methods of the JDK 1.5 API. Each string has the form
|
||||||
|
* "<owner><name><descriptor>".
|
||||||
|
@@ -68,12 +85,158 @@ public class Retrofitter {
|
||||||
|
*/
|
||||||
|
private final HashMap<String, String> jdkHierarchy = new HashMap<>();
|
||||||
|
|
||||||
|
+ /** The internal names of the packages exported by the retrofitted classes. */
|
||||||
|
+ private final HashSet<String> exports = new HashSet<>();
|
||||||
|
+
|
||||||
|
+ /** The internal names of the packages imported by the retrofitted classes. */
|
||||||
|
+ private final HashSet<String> imports = new HashSet<>();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Transforms the class files in the given directory, in place, in order to make them compatible
|
||||||
|
+ * with the JDK 1.5. Also generates a module-info class in this directory, with the given module
|
||||||
|
+ * version.
|
||||||
|
+ *
|
||||||
|
+ * @param args a directory containing compiled classes and the ASM release version.
|
||||||
|
+ * @throws IOException if a file can't be read or written.
|
||||||
|
+ */
|
||||||
|
+ public static void main(final String[] args) throws IOException {
|
||||||
|
+ if (args.length == 2) {
|
||||||
|
+ new Retrofitter().retrofit(new File(args[0]), args[1]);
|
||||||
|
+ } else {
|
||||||
|
+ System.err.println("Usage: Retrofitter <classes directory> <ASM release version>"); // NOPMD
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Transforms the class files in the given directory, in place, in order to make them compatible
|
||||||
|
+ * with the JDK 1.5. Also generates a module-info class in this directory, with the given module
|
||||||
|
+ * version.
|
||||||
|
+ *
|
||||||
|
+ * @param classesDir a directory containing compiled classes.
|
||||||
|
+ * @param version the module-info version.
|
||||||
|
+ * @throws IOException if a file can't be read or written.
|
||||||
|
+ */
|
||||||
|
+ public void retrofit(final File classesDir, final String version) throws IOException {
|
||||||
|
+ for (File classFile : getAllClasses(classesDir, new ArrayList<File>())) {
|
||||||
|
+ ClassReader classReader = new ClassReader(Files.newInputStream(classFile.toPath()));
|
||||||
|
+ ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
+ classReader.accept(new ClassRetrofitter(classWriter), ClassReader.SKIP_FRAMES);
|
||||||
|
+ Files.write(classFile.toPath(), classWriter.toByteArray());
|
||||||
|
+ }
|
||||||
|
+ generateModuleInfoClass(classesDir, version);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
- * Constructs a new {@link Retrofitter}.
|
||||||
|
+ * Verify that the class files in the given directory only use JDK 1.5 APIs, and that a
|
||||||
|
+ * module-info class is present with the expected content.
|
||||||
|
*
|
||||||
|
- * @throws IOException if the JDK API description file can't be read.
|
||||||
|
+ * @param classesDir a directory containing compiled classes.
|
||||||
|
+ * @param expectedVersion the expected module-info version.
|
||||||
|
+ * @param expectedExports the expected module-info exported packages.
|
||||||
|
+ * @param expectedRequires the expected module-info required modules.
|
||||||
|
+ * @throws IOException if a file can't be read.
|
||||||
|
+ * @throws IllegalArgumentException if the module-info class does not have the expected content.
|
||||||
|
*/
|
||||||
|
- public Retrofitter() throws IOException {
|
||||||
|
+ public void verify(
|
||||||
|
+ final File classesDir,
|
||||||
|
+ final String expectedVersion,
|
||||||
|
+ final List<String> expectedExports,
|
||||||
|
+ final List<String> expectedRequires)
|
||||||
|
+ throws IOException {
|
||||||
|
+ if (jdkApi.isEmpty()) {
|
||||||
|
+ readJdkApi();
|
||||||
|
+ }
|
||||||
|
+ for (File classFile : getAllClasses(classesDir, new ArrayList<File>())) {
|
||||||
|
+ if (!classFile.getName().equals(MODULE_INFO)) {
|
||||||
|
+ new ClassReader(Files.newInputStream(classFile.toPath())).accept(new ClassVerifier(), 0);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ verifyModuleInfoClass(
|
||||||
|
+ classesDir,
|
||||||
|
+ expectedVersion,
|
||||||
|
+ new HashSet<String>(expectedExports),
|
||||||
|
+ Stream.concat(expectedRequires.stream(), Stream.of(JAVA_BASE_MODULE)).collect(toSet()));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private List<File> getAllClasses(final File file, final List<File> allClasses)
|
||||||
|
+ throws IOException {
|
||||||
|
+ if (file.isDirectory()) {
|
||||||
|
+ File[] children = file.listFiles();
|
||||||
|
+ if (children == null) {
|
||||||
|
+ throw new IOException("Unable to read files of " + file);
|
||||||
|
+ }
|
||||||
|
+ for (File child : children) {
|
||||||
|
+ getAllClasses(child, allClasses);
|
||||||
|
+ }
|
||||||
|
+ } else if (file.getName().endsWith(".class")) {
|
||||||
|
+ allClasses.add(file);
|
||||||
|
+ }
|
||||||
|
+ return allClasses;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private void generateModuleInfoClass(final File dstDir, final String version) throws IOException {
|
||||||
|
+ ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
+ classWriter.visit(Opcodes.V9, Opcodes.ACC_MODULE, "module-info", null, null, null);
|
||||||
|
+ ArrayList<String> moduleNames = new ArrayList<>();
|
||||||
|
+ for (String exportName : exports) {
|
||||||
|
+ if (isAsmModule(exportName)) {
|
||||||
|
+ moduleNames.add(exportName);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (moduleNames.size() != 1) {
|
||||||
|
+ throw new IllegalArgumentException("Module name can't be infered from classes");
|
||||||
|
+ }
|
||||||
|
+ ModuleVisitor moduleVisitor =
|
||||||
|
+ classWriter.visitModule(moduleNames.get(0), Opcodes.ACC_OPEN, version);
|
||||||
|
+
|
||||||
|
+ for (String importName : imports) {
|
||||||
|
+ if (isAsmModule(importName) && !exports.contains(importName)) {
|
||||||
|
+ moduleVisitor.visitRequire(importName.replace('/', '.'), Opcodes.ACC_TRANSITIVE, null);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ moduleVisitor.visitRequire(JAVA_BASE_MODULE, Opcodes.ACC_MANDATED, null);
|
||||||
|
+
|
||||||
|
+ for (String exportName : exports) {
|
||||||
|
+ moduleVisitor.visitExport(exportName, 0);
|
||||||
|
+ }
|
||||||
|
+ moduleVisitor.visitEnd();
|
||||||
|
+ classWriter.visitEnd();
|
||||||
|
+ Files.write(Path.of(dstDir.getAbsolutePath(), MODULE_INFO), classWriter.toByteArray());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private void verifyModuleInfoClass(
|
||||||
|
+ final File dstDir,
|
||||||
|
+ final String expectedVersion,
|
||||||
|
+ final Set<String> expectedExports,
|
||||||
|
+ final Set<String> expectedRequires)
|
||||||
|
+ throws IOException {
|
||||||
|
+ ModuleDescriptor module =
|
||||||
|
+ ModuleDescriptor.read(Files.newInputStream(Path.of(dstDir.getAbsolutePath(), MODULE_INFO)));
|
||||||
|
+ String version = module.version().map(ModuleDescriptor.Version::toString).orElse("");
|
||||||
|
+ if (!version.equals(expectedVersion)) {
|
||||||
|
+ throw new IllegalArgumentException(
|
||||||
|
+ format("Wrong module-info version '%s' (expected '%s')", version, expectedVersion));
|
||||||
|
+ }
|
||||||
|
+ Set<String> exports =
|
||||||
|
+ module.exports().stream().map(ModuleDescriptor.Exports::source).collect(toSet());
|
||||||
|
+ if (!exports.equals(expectedExports)) {
|
||||||
|
+ throw new IllegalArgumentException(
|
||||||
|
+ format("Wrong module-info exports %s (expected %s)", exports, expectedExports));
|
||||||
|
+ }
|
||||||
|
+ Set<String> requires =
|
||||||
|
+ module.requires().stream().map(ModuleDescriptor.Requires::name).collect(toSet());
|
||||||
|
+ if (!requires.equals(expectedRequires)) {
|
||||||
|
+ throw new IllegalArgumentException(
|
||||||
|
+ format("Wrong module-info requires %s (expected %s)", requires, expectedRequires));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private static boolean isAsmModule(final String packageName) {
|
||||||
|
+ return packageName.startsWith("org/objectweb/asm")
|
||||||
|
+ && !packageName.equals("org/objectweb/asm/signature");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private void readJdkApi() throws IOException {
|
||||||
|
try (InputStream inputStream =
|
||||||
|
new GZIPInputStream(
|
||||||
|
Retrofitter.class.getClassLoader().getResourceAsStream("jdk1.5.0.12.txt.gz"));
|
||||||
|
@@ -97,56 +260,8 @@ public class Retrofitter {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- /**
|
||||||
|
- * Transforms the source class file, or if it is a directory, its files (recursively), in place,
|
||||||
|
- * in order to make them compatible with the JDK 1.5.
|
||||||
|
- *
|
||||||
|
- * @param src source file or directory.
|
||||||
|
- * @throws IOException if the source files can't be read or written.
|
||||||
|
- */
|
||||||
|
- public void retrofit(final File src) throws IOException {
|
||||||
|
- retrofit(src, null);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /**
|
||||||
|
- * Transforms the source class file, or if it is a directory, its files (recursively), either in
|
||||||
|
- * place or into the destination file or directory, in order to make them compatible with the JDK
|
||||||
|
- * 1.5.
|
||||||
|
- *
|
||||||
|
- * @param src source file or directory.
|
||||||
|
- * @param dst optional destination file or directory.
|
||||||
|
- * @throws IOException if the source or destination file can't be read or written.
|
||||||
|
- */
|
||||||
|
- public void retrofit(final File src, final File dst) throws IOException {
|
||||||
|
- if (src.isDirectory()) {
|
||||||
|
- File[] files = src.listFiles();
|
||||||
|
- if (files == null) {
|
||||||
|
- throw new IOException("Unable to read files of " + src);
|
||||||
|
- }
|
||||||
|
- for (File file : files) {
|
||||||
|
- retrofit(file, dst == null ? null : new File(dst, file.getName()));
|
||||||
|
- }
|
||||||
|
- } else if (src.getName().endsWith(".class")) {
|
||||||
|
- if (dst == null || !dst.exists() || dst.lastModified() < src.lastModified()) {
|
||||||
|
- ClassReader classReader = new ClassReader(Files.newInputStream(src.toPath()));
|
||||||
|
- ClassWriter classWriter = new ClassWriter(0);
|
||||||
|
- ClassVerifier classVerifier = new ClassVerifier(classWriter);
|
||||||
|
- ClassRetrofitter classRetrofitter = new ClassRetrofitter(classVerifier);
|
||||||
|
- classReader.accept(classRetrofitter, ClassReader.SKIP_FRAMES);
|
||||||
|
-
|
||||||
|
- if (dst != null && !dst.getParentFile().exists() && !dst.getParentFile().mkdirs()) {
|
||||||
|
- throw new IOException("Cannot create directory " + dst.getParentFile());
|
||||||
|
- }
|
||||||
|
- try (OutputStream outputStream =
|
||||||
|
- Files.newOutputStream((dst == null ? src : dst).toPath())) {
|
||||||
|
- outputStream.write(classWriter.toByteArray());
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
/** A ClassVisitor that retrofits classes to 1.5 version. */
|
||||||
|
- static class ClassRetrofitter extends ClassVisitor {
|
||||||
|
+ class ClassRetrofitter extends ClassVisitor {
|
||||||
|
|
||||||
|
public ClassRetrofitter(final ClassVisitor classVisitor) {
|
||||||
|
super(/* latest api =*/ Opcodes.ASM8, classVisitor);
|
||||||
|
@@ -160,9 +275,21 @@ public class Retrofitter {
|
||||||
|
final String signature,
|
||||||
|
final String superName,
|
||||||
|
final String[] interfaces) {
|
||||||
|
+ addPackageReferences(Type.getObjectType(name), /* export = */ true);
|
||||||
|
super.visit(Opcodes.V1_5, access, name, signature, superName, interfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ @Override
|
||||||
|
+ public FieldVisitor visitField(
|
||||||
|
+ final int access,
|
||||||
|
+ final String name,
|
||||||
|
+ final String descriptor,
|
||||||
|
+ final String signature,
|
||||||
|
+ final Object value) {
|
||||||
|
+ addPackageReferences(Type.getType(descriptor), /* export = */ false);
|
||||||
|
+ return super.visitField(access, name, descriptor, signature, value);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(
|
||||||
|
final int access,
|
||||||
|
@@ -170,9 +297,17 @@ public class Retrofitter {
|
||||||
|
final String descriptor,
|
||||||
|
final String signature,
|
||||||
|
final String[] exceptions) {
|
||||||
|
+ addPackageReferences(Type.getType(descriptor), /* export = */ false);
|
||||||
|
return new MethodVisitor(
|
||||||
|
api, super.visitMethod(access, name, descriptor, signature, exceptions)) {
|
||||||
|
|
||||||
|
+ @Override
|
||||||
|
+ public void visitFieldInsn(
|
||||||
|
+ final int opcode, final String owner, final String name, final String descriptor) {
|
||||||
|
+ addPackageReferences(Type.getType(descriptor), /* export = */ false);
|
||||||
|
+ super.visitFieldInsn(opcode, owner, name, descriptor);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
public void visitMethodInsn(
|
||||||
|
final int opcode,
|
||||||
|
@@ -180,6 +315,7 @@ public class Retrofitter {
|
||||||
|
final String name,
|
||||||
|
final String descriptor,
|
||||||
|
final boolean isInterface) {
|
||||||
|
+ addPackageReferences(Type.getType(descriptor), /* export = */ false);
|
||||||
|
// Remove the addSuppressed() method calls generated for try-with-resources statements.
|
||||||
|
// This method is not defined in JDK1.5.
|
||||||
|
if (owner.equals("java/lang/Throwable")
|
||||||
|
@@ -190,8 +326,52 @@ public class Retrofitter {
|
||||||
|
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void visitTypeInsn(final int opcode, final String type) {
|
||||||
|
+ addPackageReferences(Type.getObjectType(type), /* export = */ false);
|
||||||
|
+ super.visitTypeInsn(opcode, type);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) {
|
||||||
|
+ addPackageReferences(Type.getType(descriptor), /* export = */ false);
|
||||||
|
+ super.visitMultiANewArrayInsn(descriptor, numDimensions);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void visitTryCatchBlock(
|
||||||
|
+ final Label start, final Label end, final Label handler, final String type) {
|
||||||
|
+ if (type != null) {
|
||||||
|
+ addPackageReferences(Type.getObjectType(type), /* export = */ false);
|
||||||
|
+ }
|
||||||
|
+ super.visitTryCatchBlock(start, end, handler, type);
|
||||||
|
+ }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ private void addPackageReferences(final Type type, final boolean export) {
|
||||||
|
+ switch (type.getSort()) {
|
||||||
|
+ case Type.ARRAY:
|
||||||
|
+ addPackageReferences(type.getElementType(), export);
|
||||||
|
+ break;
|
||||||
|
+ case Type.METHOD:
|
||||||
|
+ for (Type argumentType : type.getArgumentTypes()) {
|
||||||
|
+ addPackageReferences(argumentType, export);
|
||||||
|
+ }
|
||||||
|
+ addPackageReferences(type.getReturnType(), export);
|
||||||
|
+ break;
|
||||||
|
+ case Type.OBJECT:
|
||||||
|
+ String internalName = type.getInternalName();
|
||||||
|
+ int lastSlashIndex = internalName.lastIndexOf('/');
|
||||||
|
+ if (lastSlashIndex != -1) {
|
||||||
|
+ (export ? exports : imports).add(internalName.substring(0, lastSlashIndex));
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -199,18 +379,18 @@ public class Retrofitter {
|
||||||
|
*/
|
||||||
|
class ClassVerifier extends ClassVisitor {
|
||||||
|
|
||||||
|
- /** The name of the visited class. */
|
||||||
|
+ /** The internal name of the visited class. */
|
||||||
|
String className;
|
||||||
|
|
||||||
|
/** The name of the currently visited method. */
|
||||||
|
String currentMethodName;
|
||||||
|
|
||||||
|
- public ClassVerifier(final ClassVisitor classVisitor) {
|
||||||
|
+ public ClassVerifier() {
|
||||||
|
// Make sure use we don't use Java 9 or higher classfile features.
|
||||||
|
// We also want to make sure we don't use Java 6, 7 or 8 classfile
|
||||||
|
// features (invokedynamic), but this can't be done in the same way.
|
||||||
|
// Instead, we use manual checks below.
|
||||||
|
- super(Opcodes.ASM4, classVisitor);
|
||||||
|
+ super(Opcodes.ASM4, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@@ -222,10 +402,9 @@ public class Retrofitter {
|
||||||
|
final String superName,
|
||||||
|
final String[] interfaces) {
|
||||||
|
if ((version & 0xFFFF) > Opcodes.V1_5) {
|
||||||
|
- throw new IllegalArgumentException("ERROR: " + name + " version is newer than 1.5");
|
||||||
|
+ throw new IllegalArgumentException(format("ERROR: %d version is newer than 1.5", version));
|
||||||
|
}
|
||||||
|
className = name;
|
||||||
|
- super.visit(version, access, name, signature, superName, interfaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@@ -243,7 +422,6 @@ public class Retrofitter {
|
||||||
|
public void visitFieldInsn(
|
||||||
|
final int opcode, final String owner, final String name, final String descriptor) {
|
||||||
|
check(owner, name);
|
||||||
|
- super.visitFieldInsn(opcode, owner, name, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@@ -254,7 +432,6 @@ public class Retrofitter {
|
||||||
|
final String descriptor,
|
||||||
|
final boolean isInterface) {
|
||||||
|
check(owner, name + descriptor);
|
||||||
|
- super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@@ -263,21 +440,16 @@ public class Retrofitter {
|
||||||
|
int sort = ((Type) value).getSort();
|
||||||
|
if (sort == Type.METHOD) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
- "ERROR: ldc with a MethodType called in "
|
||||||
|
- + className
|
||||||
|
- + ' '
|
||||||
|
- + currentMethodName
|
||||||
|
- + " is not available in JDK 1.5");
|
||||||
|
+ format(
|
||||||
|
+ "ERROR: ldc with a MethodType called in %s %s is not available in JDK 1.5",
|
||||||
|
+ className, currentMethodName));
|
||||||
|
}
|
||||||
|
} else if (value instanceof Handle) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
- "ERROR: ldc with a MethodHandle called in "
|
||||||
|
- + className
|
||||||
|
- + ' '
|
||||||
|
- + currentMethodName
|
||||||
|
- + " is not available in JDK 1.5");
|
||||||
|
+ format(
|
||||||
|
+ "ERROR: ldc with a MethodHandle called in %s %s is not available in JDK 1.5",
|
||||||
|
+ className, currentMethodName));
|
||||||
|
}
|
||||||
|
- super.visitLdcInsn(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@@ -287,11 +459,9 @@ public class Retrofitter {
|
||||||
|
final Handle bootstrapMethodHandle,
|
||||||
|
final Object... bootstrapMethodArguments) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
- "ERROR: invokedynamic called in "
|
||||||
|
- + className
|
||||||
|
- + ' '
|
||||||
|
- + currentMethodName
|
||||||
|
- + " is not available in JDK 1.5");
|
||||||
|
+ format(
|
||||||
|
+ "ERROR: invokedynamic called in %s %s is not available in JDK 1.5",
|
||||||
|
+ className, currentMethodName));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@@ -302,7 +472,7 @@ public class Retrofitter {
|
||||||
|
* @param owner A class name.
|
||||||
|
* @param member A field name or a method name and descriptor.
|
||||||
|
*/
|
||||||
|
- void check(final String owner, final String member) {
|
||||||
|
+ private void check(final String owner, final String member) {
|
||||||
|
if (owner.startsWith("java/")) {
|
||||||
|
String currentOwner = owner;
|
||||||
|
while (currentOwner != null) {
|
||||||
|
@@ -312,15 +482,9 @@ public class Retrofitter {
|
||||||
|
currentOwner = jdkHierarchy.get(currentOwner);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
- "ERROR: "
|
||||||
|
- + owner
|
||||||
|
- + ' '
|
||||||
|
- + member
|
||||||
|
- + " called in "
|
||||||
|
- + className
|
||||||
|
- + ' '
|
||||||
|
- + currentMethodName
|
||||||
|
- + " is not defined in the JDK 1.5 API");
|
||||||
|
+ format(
|
||||||
|
+ "ERROR: %s %s called in %s %s is not defined in the JDK 1.5 API",
|
||||||
|
+ owner, member, className, currentMethodName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.37.1
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Name: objectweb-asm
|
Name: objectweb-asm
|
||||||
Version: 9.3
|
Version: 9.3
|
||||||
Release: 2%{?dist}
|
Release: 3%{?dist}
|
||||||
Summary: Java bytecode manipulation and analysis framework
|
Summary: Java bytecode manipulation and analysis framework
|
||||||
License: BSD
|
License: BSD
|
||||||
URL: https://asm.ow2.org/
|
URL: https://asm.ow2.org/
|
||||||
@ -20,11 +20,21 @@ Source6: https://repo1.maven.org/maven2/org/ow2/asm/asm-tree/%{version}/a
|
|||||||
Source7: https://repo1.maven.org/maven2/org/ow2/asm/asm-util/%{version}/asm-util-%{version}.pom
|
Source7: https://repo1.maven.org/maven2/org/ow2/asm/asm-util/%{version}/asm-util-%{version}.pom
|
||||||
# The source contains binary jars that cannot be verified for licensing and could be proprietary
|
# The source contains binary jars that cannot be verified for licensing and could be proprietary
|
||||||
Source9: generate-tarball.sh
|
Source9: generate-tarball.sh
|
||||||
|
Source10: tools-retrofitter.pom
|
||||||
|
|
||||||
|
# This patch makes it possible to generate module-info.class files without
|
||||||
|
# needing to use bnd-maven-plugin during the build. The replacement is an added
|
||||||
|
# main method that has to be invoked manually.
|
||||||
|
# Patch already applied in upstream master
|
||||||
|
# https://gitlab.ow2.org/asm/asm/-/commit/5921eb2a141f0dcc83c6a5d7dcd5035a30c5edfc
|
||||||
|
Patch1: 0001-Generate-the-module-info-classes-without-Bnd.-Delete.patch
|
||||||
|
|
||||||
%if %{with bootstrap}
|
%if %{with bootstrap}
|
||||||
BuildRequires: javapackages-bootstrap
|
BuildRequires: javapackages-bootstrap
|
||||||
%else
|
%else
|
||||||
BuildRequires: maven-local
|
BuildRequires: maven-local
|
||||||
|
BuildRequires: mvn(org.apache.maven.plugins:maven-antrun-plugin)
|
||||||
|
BuildRequires: mvn(org.ow2.asm:asm)
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
# Explicit javapackages-tools requires since asm-processor script uses
|
# Explicit javapackages-tools requires since asm-processor script uses
|
||||||
@ -47,20 +57,28 @@ This package provides %{summary}.
|
|||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q
|
||||||
|
|
||||||
|
%patch1 -p1
|
||||||
|
|
||||||
# A custom parent pom to aggregate the build
|
# A custom parent pom to aggregate the build
|
||||||
cp -p %{SOURCE1} pom.xml
|
cp -p %{SOURCE1} pom.xml
|
||||||
|
%pom_xpath_set pom:project/pom:version %{version}
|
||||||
|
|
||||||
|
cp -p %{SOURCE10} tools/retrofitter/pom.xml
|
||||||
|
|
||||||
# Insert poms into modules
|
# Insert poms into modules
|
||||||
for pom in asm asm-analysis asm-commons asm-test asm-tree asm-util; do
|
for pom in asm asm-analysis asm-commons asm-test asm-tree asm-util; do
|
||||||
cp -p $RPM_SOURCE_DIR/${pom}-%{version}.pom $pom/pom.xml
|
cp -p ${RPM_SOURCE_DIR}/${pom}-%{version}.pom ${pom}/pom.xml
|
||||||
%pom_remove_parent $pom
|
%pom_add_dep org.ow2.asm:tools-retrofitter::provided ${pom}
|
||||||
|
%pom_add_plugin org.apache.maven.plugins:maven-antrun-plugin ${pom}
|
||||||
|
%pom_set_parent org.ow2.asm:asm-aggregator:%{version} ${pom}
|
||||||
|
%pom_xpath_inject pom:parent '<relativePath>..</relativePath>' ${pom}
|
||||||
done
|
done
|
||||||
|
|
||||||
# No need to ship the custom parent pom
|
|
||||||
%mvn_package :asm-aggregator __noinstall
|
|
||||||
# Don't ship the test framework to avoid runtime dep on junit
|
# Don't ship the test framework to avoid runtime dep on junit
|
||||||
%mvn_package :asm-test __noinstall
|
%mvn_package :asm-test __noinstall
|
||||||
|
|
||||||
|
%mvn_package :tools-retrofitter __noinstall
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%mvn_build -f -- -Dmaven.compiler.source=1.8 -Dmaven.compiler.target=1.8
|
%mvn_build -f -- -Dmaven.compiler.source=1.8 -Dmaven.compiler.target=1.8
|
||||||
|
|
||||||
@ -77,6 +95,10 @@ done
|
|||||||
%license LICENSE.txt
|
%license LICENSE.txt
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Aug 29 2022 Marian Koncek <mkoncek@redhat.com> - 9.3-3
|
||||||
|
- Generate module-info without bnd-plugin
|
||||||
|
- Resolves: rhbz#2106272
|
||||||
|
|
||||||
* Fri Jul 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 9.3-2
|
* Fri Jul 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 9.3-2
|
||||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
|
||||||
|
|
||||||
|
38
parent.pom
38
parent.pom
@ -5,15 +5,51 @@
|
|||||||
|
|
||||||
<groupId>org.ow2.asm</groupId>
|
<groupId>org.ow2.asm</groupId>
|
||||||
<artifactId>asm-aggregator</artifactId>
|
<artifactId>asm-aggregator</artifactId>
|
||||||
<version>1</version>
|
<version></version>
|
||||||
|
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>asm</module>
|
<module>asm</module>
|
||||||
<module>asm-analysis</module>
|
<module>asm-analysis</module>
|
||||||
<module>asm-commons</module>
|
<module>asm-commons</module>
|
||||||
<module>asm-tree</module>
|
<module>asm-tree</module>
|
||||||
<module>asm-util</module>
|
<module>asm-util</module>
|
||||||
|
<module>tools/retrofitter</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-antrun-plugin</artifactId>
|
||||||
|
<version>any</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>process-classes</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<target>
|
||||||
|
<java classname="org.objectweb.asm.tools.Retrofitter" failonerror="true">
|
||||||
|
<arg value="${project.build.directory}/classes"/>
|
||||||
|
<arg value="${project.version}"/>
|
||||||
|
<classpath>
|
||||||
|
<path refid="maven.compile.classpath"/>
|
||||||
|
</classpath>
|
||||||
|
</java>
|
||||||
|
</target>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
19
tools-retrofitter.pom
Normal file
19
tools-retrofitter.pom
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
|
||||||
|
xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
<artifactId>tools-retrofitter</artifactId>
|
||||||
|
<version>any</version>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
<artifactId>asm</artifactId>
|
||||||
|
<version>any</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
Loading…
Reference in New Issue
Block a user