< prev index next >

src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java

Print this page
rev 47453 : imported patch jdk-new-asm-update.patch

@@ -29,23 +29,23 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.module.ModuleDescriptor.Version;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import jdk.internal.org.objectweb.asm.Attribute;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassVisitor;
 import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.ModuleVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.commons.ModuleHashesAttribute;
+import jdk.internal.org.objectweb.asm.commons.ModuleResolutionAttribute;
+import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
 
-import static jdk.internal.module.ClassFileAttributes.*;
-
 /**
  * Utility class to extend a module-info.class with additional attributes.
  */
 
 public final class ModuleInfoExtender {

@@ -131,47 +131,10 @@
         this.moduleResolution = mres;
         return this;
     }
 
     /**
-     * A ClassVisitor that supports adding class file attributes. If an
-     * attribute already exists then the first occurrence of the attribute
-     * is replaced.
-     */
-    private static class AttributeAddingClassVisitor extends ClassVisitor {
-        private Map<String, Attribute> attrs = new HashMap<>();
-
-        AttributeAddingClassVisitor(int api, ClassVisitor cv) {
-            super(api, cv);
-        }
-
-        void addAttribute(Attribute attr) {
-            attrs.put(attr.type, attr);
-        }
-
-        @Override
-        public void visitAttribute(Attribute attr) {
-            String name = attr.type;
-            Attribute replacement = attrs.get(name);
-            if (replacement != null) {
-                attr = replacement;
-                attrs.remove(name);
-            }
-            super.visitAttribute(attr);
-        }
-
-        /**
-         * Adds any remaining attributes that weren't replaced to the
-         * class file.
-         */
-        void finish() {
-            attrs.values().forEach(a -> super.visitAttribute(a));
-            attrs.clear();
-        }
-    }
-
-    /**
      * Outputs the modified module-info.class to the given output stream.
      * Once this method has been called then the Extender object should
      * be discarded.
      */
     public void write(OutputStream out) throws IOException {

@@ -183,42 +146,90 @@
      * Returns the bytes of the modified module-info.class.
      * Once this method has been called then the Extender object should
      * be discarded.
      */
     public byte[] toByteArray() throws IOException {
-        ClassWriter cw
-            = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+                                         + ClassWriter.COMPUTE_FRAMES);
 
-        AttributeAddingClassVisitor cv
-            = new AttributeAddingClassVisitor(Opcodes.ASM5, cw);
-
         ClassReader cr = new ClassReader(in);
 
-        if (packages != null)
-            cv.addAttribute(new ModulePackagesAttribute(packages));
-        if (mainClass != null)
-            cv.addAttribute(new ModuleMainClassAttribute(mainClass));
-        if (targetPlatform != null)
-            cv.addAttribute(new ModuleTargetAttribute(targetPlatform));
-        if (hashes != null)
-            cv.addAttribute(new ModuleHashesAttribute(hashes));
-        if (moduleResolution != null)
-            cv.addAttribute(new ModuleResolutionAttribute(moduleResolution.value()));
+        ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
+            @Override
+            public ModuleVisitor visitModule(String name, int flags, String version) {
+                Version v = ModuleInfoExtender.this.version;
+                String vs = (v != null) ? v.toString() : version;
+                ModuleVisitor mv = super.visitModule(name, flags, vs);
 
-        List<Attribute> attrs = new ArrayList<>();
+                // ModuleMainClass attribute
+                if (mainClass != null) {
+                    mv.visitMainClass(mainClass.replace('.', '/'));
+                }
 
-        // prototypes of attributes that should be parsed
-        attrs.add(new ModuleAttribute(version));
-        attrs.add(new ModulePackagesAttribute());
-        attrs.add(new ModuleMainClassAttribute());
+                // ModulePackages attribute
+                if (packages != null) {
+                    packages.forEach(pn -> mv.visitPackage(pn.replace('.', '/')));
+                }
+
+                return new ModuleVisitor(Opcodes.ASM6, mv) {
+                    public void visitMainClass(String existingMainClass) {
+                        // skip main class if there is a new value
+                        if (mainClass == null) {
+                            super.visitMainClass(existingMainClass);
+                        }
+                    }
+                    public void visitPackage(String existingPackage) {
+                        // skip packages if there is a new set of packages
+                        if (packages == null) {
+                            super.visitPackage(existingPackage);
+                        }
+                    }
+                };
+            }
+            @Override
+            public void visitAttribute(Attribute attr) {
+                String name = attr.type;
+                // drop existing attributes if there are replacements
+                if (name.equals(ClassFileConstants.MODULE_TARGET)
+                    && targetPlatform != null)
+                    return;
+                if (name.equals(ClassFileConstants.MODULE_RESOLUTION)
+                    && moduleResolution != null)
+                    return;
+                if (name.equals(ClassFileConstants.MODULE_HASHES)
+                    && hashes != null)
+                    return;
+
+                super.visitAttribute(attr);
+
+            }
+        };
+
+        List<Attribute> attrs = new ArrayList<>();
         attrs.add(new ModuleTargetAttribute());
+        attrs.add(new ModuleResolutionAttribute());
         attrs.add(new ModuleHashesAttribute());
-
         cr.accept(cv, attrs.toArray(new Attribute[0]), 0);
 
-        // add any attributes that didn't replace previous attributes
-        cv.finish();
+        // add ModuleTarget, ModuleResolution and ModuleHashes attributes
+        if (targetPlatform != null) {
+            cw.visitAttribute(new ModuleTargetAttribute(targetPlatform));
+        }
+        if (moduleResolution != null) {
+            int flags = moduleResolution.value();
+            cw.visitAttribute(new ModuleResolutionAttribute(flags));
+        }
+        if (hashes != null) {
+            String algorithm = hashes.algorithm();
+            List<String> names = new ArrayList<>();
+            List<byte[]> values = new ArrayList<>();
+            for (String name : hashes.names()) {
+                names.add(name);
+                values.add(hashes.hashFor(name));
+            }
+            cw.visitAttribute(new ModuleHashesAttribute(algorithm, names, values));
+        }
 
         return cw.toByteArray();
     }
 
     /**
< prev index next >