|
1 /* |
|
2 * Copyright (c) 2015, 2017, 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.nio.ByteBuffer; |
|
31 import java.util.stream.Stream; |
|
32 |
|
33 import jdk.internal.org.objectweb.asm.ClassWriter; |
|
34 import jdk.internal.org.objectweb.asm.Opcodes; |
|
35 |
|
36 import static jdk.internal.module.ClassFileAttributes.*; |
|
37 import static jdk.internal.module.ClassFileConstants.ACC_MODULE; |
|
38 |
|
39 /** |
|
40 * Utility class to write a ModuleDescriptor as a module-info.class. |
|
41 */ |
|
42 |
|
43 public final class ModuleInfoWriter { |
|
44 |
|
45 private ModuleInfoWriter() { } |
|
46 |
|
47 /** |
|
48 * Writes the given module descriptor to a module-info.class file, |
|
49 * returning it in a byte array. |
|
50 */ |
|
51 private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) { |
|
52 ClassWriter cw = new ClassWriter(0); |
|
53 cw.visit(Opcodes.V1_9, ACC_MODULE, "module-info", null, null, null); |
|
54 cw.visitAttribute(new ModuleAttribute(md)); |
|
55 |
|
56 // for tests: write the ModulePackages attribute when there are packages |
|
57 // that aren't exported or open |
|
58 Stream<String> exported = md.exports().stream() |
|
59 .map(ModuleDescriptor.Exports::source); |
|
60 Stream<String> open = md.opens().stream() |
|
61 .map(ModuleDescriptor.Opens::source); |
|
62 long exportedOrOpen = Stream.concat(exported, open).distinct().count(); |
|
63 if (md.packages().size() > exportedOrOpen) |
|
64 cw.visitAttribute(new ModulePackagesAttribute(md.packages())); |
|
65 |
|
66 // write ModuleMainClass if the module has a main class |
|
67 md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc))); |
|
68 |
|
69 // write ModuleTarget if there is a target platform |
|
70 if (target != null) { |
|
71 cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform())); |
|
72 } |
|
73 |
|
74 cw.visitEnd(); |
|
75 return cw.toByteArray(); |
|
76 } |
|
77 |
|
78 /** |
|
79 * Writes a module descriptor to the given output stream as a |
|
80 * module-info.class. |
|
81 */ |
|
82 public static void write(ModuleDescriptor descriptor, |
|
83 ModuleTarget target, |
|
84 OutputStream out) |
|
85 throws IOException |
|
86 { |
|
87 byte[] bytes = toModuleInfo(descriptor, target); |
|
88 out.write(bytes); |
|
89 } |
|
90 |
|
91 /** |
|
92 * Writes a module descriptor to the given output stream as a |
|
93 * module-info.class. |
|
94 */ |
|
95 public static void write(ModuleDescriptor descriptor, OutputStream out) |
|
96 throws IOException |
|
97 { |
|
98 write(descriptor, null, out); |
|
99 } |
|
100 |
|
101 /** |
|
102 * Returns a {@code ByteBuffer} containing the given module descriptor |
|
103 * in module-info.class format. |
|
104 */ |
|
105 public static ByteBuffer toByteBuffer(ModuleDescriptor descriptor) { |
|
106 byte[] bytes = toModuleInfo(descriptor, null); |
|
107 return ByteBuffer.wrap(bytes); |
|
108 } |
|
109 } |