1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.internal.module; 26 27 import java.io.IOException; 28 import java.io.OutputStream; 29 import java.lang.module.ModuleDescriptor; 30 import java.lang.module.ModuleDescriptor.Version; 31 import java.nio.ByteBuffer; 32 import java.util.Optional; 33 34 import jdk.internal.org.objectweb.asm.ClassWriter; 35 import jdk.internal.org.objectweb.asm.Opcodes; 36 37 import static jdk.internal.module.ClassFileAttributes.*; 38 import static jdk.internal.module.ClassFileConstants.ACC_MODULE; 39 40 /** 41 * Utility class to write a ModuleDescriptor as a module-info.class. 42 */ 43 44 public final class ModuleInfoWriter { 45 46 private ModuleInfoWriter() { } 47 48 /** 49 * Writes the given module descriptor to a module-info.class file, 50 * returning it in a byte array. 51 */ 52 private static byte[] toModuleInfo(ModuleDescriptor descriptor) { 53 54 ClassWriter cw = new ClassWriter(0); 55 56 String name = descriptor.name().replace('.', '/') + "/module-info"; 57 cw.visit(Opcodes.V1_8, ACC_MODULE, name, null, null, null); 58 59 cw.visitAttribute(new ModuleAttribute(descriptor)); 60 cw.visitAttribute(new ConcealedPackagesAttribute(descriptor.conceals())); 61 62 Optional<Version> oversion = descriptor.version(); 63 if (oversion.isPresent()) 64 cw.visitAttribute(new VersionAttribute(oversion.getWhenPresent())); 65 66 Optional<String> omain = descriptor.mainClass(); 67 if (omain.isPresent()) 68 cw.visitAttribute(new MainClassAttribute(omain.getWhenPresent())); 69 70 // write the TargetPlatform attribute if have any of OS name/arch/version 71 String osName = descriptor.osName().orElse(null); 72 String osArch = descriptor.osArch().orElse(null); 73 String osVersion = descriptor.osVersion().orElse(null); 74 if (osName != null || osArch != null || osVersion != null) { 75 cw.visitAttribute(new TargetPlatformAttribute(osName, 76 osArch, 77 osVersion)); 78 } 79 80 cw.visitEnd(); 81 82 return cw.toByteArray(); 83 } 84 85 /** 86 * Writes a module descriptor to the given output stream as a 87 * module-info.class. 88 */ 89 public static void write(ModuleDescriptor descriptor, OutputStream out) 90 throws IOException 91 { 92 byte[] bytes = toModuleInfo(descriptor); 93 out.write(bytes); 94 } 95 96 /** 97 * Returns a {@code ByteBuffer} containing the given module descriptor 98 * in module-info.class format. 99 */ 100 public static ByteBuffer toByteBuffer(ModuleDescriptor descriptor) { 101 byte[] bytes = toModuleInfo(descriptor); 102 return ByteBuffer.wrap(bytes); 103 } 104 105 }