diff --git a/build.xml b/build.xml index 8a3c2e2312d3e4a5818bb91cd2a83f50ece225cb..0bfcecfbea8dcc10049c8030ebcaa40e3a3da978 100644 --- a/build.xml +++ b/build.xml @@ -138,11 +138,11 @@ - + + - diff --git a/src/org/objectweb/asm/tools/ModuleInfoBndPlugin.java b/src/org/objectweb/asm/tools/ModuleInfoBndPlugin.java index f6eeb4ab96023306b15ce74655ca481edcdc07b8..18afb62cac98146ddf175419828abac98e1706cb 100644 --- a/src/org/objectweb/asm/tools/ModuleInfoBndPlugin.java +++ b/src/org/objectweb/asm/tools/ModuleInfoBndPlugin.java @@ -27,88 +27,73 @@ // THE POSSIBILITY OF SUCH DAMAGE. package org.objectweb.asm.tools; -import java.io.PrintWriter; - -import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ModuleVisitor; import org.objectweb.asm.Opcodes; -import org.objectweb.asm.util.TraceClassVisitor; 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.osgi.Jar; import aQute.bnd.service.AnalyzerPlugin; +/** + * 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"; - //private static final String MODULE_PROVIDES = "Module-Provides"; - //private static final String MODULE_USES = "Module-Uses"; public boolean analyzeJar(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)); - String requireModules = analyzer.getProperty(MODULE_REQUIRES); - String exportPackages = - analyzer.getProperty(MODULE_EXPORTS, analyzer.getProperty(Constants.EXPORT_PACKAGE)); - - //System.out.println(moduleName); - //System.out.println(moduleVersion); - //System.out.println(requireModules); - //System.out.println(exportPackages); - - ClassWriter writer = new ClassWriter(0); - writer.visit(Opcodes.V9, Opcodes.ACC_MODULE, "module-info", null, null, null); - - ModuleVisitor mv = writer.visitModule(moduleName, Opcodes.ACC_OPEN, moduleVersion); + ModuleVisitor moduleVisitor = + classWriter.visitModule(moduleName, Opcodes.ACC_OPEN, moduleVersion); - // requires - mv.visitRequire("java.base", Opcodes.ACC_MANDATED, null); + 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"); - mv.visitRequire( + moduleVisitor.visitRequire( requireName, (isTransitive ? Opcodes.ACC_TRANSITIVE : 0) | (isStatic ? Opcodes.ACC_STATIC_PHASE : 0), null); } } + moduleVisitor.visitRequire("java.base", Opcodes.ACC_MANDATED, null); - // exports + 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); + throw new IllegalStateException("Unsupported wildcard packages " + packageName); } - mv.visitExport(packageName.replace('.', '/'), 0); + moduleVisitor.visitExport(packageName.replace('.', '/'), 0); } } + moduleVisitor.visitEnd(); + classWriter.visitEnd(); - mv.visitEnd(); - - writer.visitEnd(); - byte[] bytecode = writer.toByteArray(); - - // debug - //ClassReader reader = new ClassReader(bytecode); - //reader.accept(new TraceClassVisitor(new PrintWriter(System.out)), 0); - - Jar jar = analyzer.getJar(); - EmbeddedResource moduleInfo = new EmbeddedResource(bytecode, System.currentTimeMillis()); - jar.putResource("module-info.class", moduleInfo); - + analyzer + .getJar() + .putResource( + "module-info.class", + new EmbeddedResource(classWriter.toByteArray(), System.currentTimeMillis())); return false; } } diff --git a/src/org/objectweb/asm/tools/Retrofitter.java b/src/org/objectweb/asm/tools/Retrofitter.java index e71bab707c127b328814e45f48f76aee94a013d7..0fcea64c7864335d369ee91cf4e665ecc212998a 100644 --- a/src/org/objectweb/asm/tools/Retrofitter.java +++ b/src/org/objectweb/asm/tools/Retrofitter.java @@ -50,7 +50,9 @@ import org.objectweb.asm.Type; /** * A command line tool to transform classes in order to make them compatible with Java 1.5, and to - * check that they use only the JDK 1.5 API and JDK 1.5 classfile features. + * check that they use only the JDK 1.5 API and JDK 1.5 class file features. The original classes + * can either be transformed "in place", or be copied first to destination directory and transformed + * here (leaving the original classes unchanged). * * @author Eric Bruneton * @author Eugene Kuleshov @@ -72,13 +74,14 @@ public class Retrofitter { * Transforms the classes from a source directory into a destination directory to make them * compatible with the JDK 1.5, and checks that they only use the JDK 1.5 API. * - * @param args First argument: name of the .txt.gz file specifying the JDK 1.5 API. Second - * argument: source directory. Third argument: destination directory. + * @param args First argument: source directory. Optional second argument: destination directory. + * If the second argument is provided classes are copied to this destination directory and + * transformed there. Otherwise they are transformed "in place" in the source directory. * @throws IOException if a file can't be read or written. */ public static void main(final String[] args) throws IOException { - File api = new File(args[0]); - InputStream inputStream = new GZIPInputStream(new FileInputStream(api)); + InputStream inputStream = + new GZIPInputStream(ClassLoader.getSystemResourceAsStream("jdk1.5.0.12.txt.gz")); BufferedReader reader = new LineNumberReader(new InputStreamReader(inputStream)); while (true) { String line = reader.readLine(); @@ -95,19 +98,20 @@ public class Retrofitter { } } - File src = new File(args[1]); - File dst = new File(args[2]); + File src = new File(args[0]); + File dst = args.length > 1 ? new File(args[1]) : null; if (!retrofit(src, dst)) { System.exit(1); } } /** - * Transforms the source class file, or if it is a directory, its files (recursively), into the - * destination file or directory, in order to make them compatible with the JDK 1.5. + * 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 destination file or directory + * @param dst optional destination file or directory * @return true if all the source classes use only the JDK 1.5 API. * @throws IOException */ @@ -116,32 +120,30 @@ public class Retrofitter { boolean result = true; File[] files = src.listFiles(); if (files == null) { - throw new IOException("unable to read files of " + src); + throw new IOException("Unable to read files of " + src); } for (int i = 0; i < files.length; ++i) { - result &= retrofit(files[i], new File(dst, files[i].getName())); + result &= retrofit(files[i], dst == null ? null : new File(dst, files[i].getName())); } return result; } else if (src.getName().endsWith(".class")) { - if (!dst.exists() || dst.lastModified() < src.lastModified()) { + if (dst == null || !dst.exists() || dst.lastModified() < src.lastModified()) { ClassReader classReader = new ClassReader(new FileInputStream(src)); ClassWriter classWriter = new ClassWriter(0); // No actual retrofit to do since we compile with target=1.5. ClassVerifier classVerifier = new ClassVerifier(classWriter); classReader.accept(classVerifier, 0); - if (!classVerifier.ok) { - return false; - } - if (!dst.getParentFile().exists() && !dst.getParentFile().mkdirs()) { + if (dst != null && !dst.getParentFile().exists() && !dst.getParentFile().mkdirs()) { throw new IOException("Cannot create directory " + dst.getParentFile()); } - OutputStream os = new FileOutputStream(dst); + OutputStream os = new FileOutputStream(dst == null ? src : dst); try { os.write(classWriter.toByteArray()); } finally { os.close(); } + return classVerifier.ok; } return true; } else {