1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.bcel.classfile;
21
22 import java.io.DataInput;
23 import java.io.DataOutputStream;
24 import java.io.IOException;
25 import java.util.Arrays;
26
27 import org.apache.bcel.Const;
28 import org.apache.bcel.util.Args;
29
30
31
32
33
34
35
36
37 public final class Module extends Attribute {
38
39
40
41
42
43
44 public static final String EXTENSION = ".jmod";
45
46 private static String getClassNameAtIndex(final ConstantPool cp, final int index, final boolean compactClassName) {
47 final String className = cp.getConstantString(index, Const.CONSTANT_Class);
48 if (compactClassName) {
49 return Utility.compactClassName(className, false);
50 }
51 return className;
52 }
53 private final int moduleNameIndex;
54 private final int moduleFlags;
55
56 private final int moduleVersionIndex;
57 private ModuleRequires[] requiresTable;
58 private ModuleExports[] exportsTable;
59 private ModuleOpens[] opensTable;
60 private final int usesCount;
61 private final int[] usesIndex;
62
63 private ModuleProvides[] providesTable;
64
65
66
67
68
69
70
71
72
73
74 Module(final int nameIndex, final int length, final DataInput dataInput, final ConstantPool constantPool) throws IOException {
75 super(Const.ATTR_MODULE, nameIndex, length, constantPool);
76
77 moduleNameIndex = dataInput.readUnsignedShort();
78 moduleFlags = dataInput.readUnsignedShort();
79 moduleVersionIndex = dataInput.readUnsignedShort();
80
81 final int requiresCount = dataInput.readUnsignedShort();
82 requiresTable = new ModuleRequires[requiresCount];
83 for (int i = 0; i < requiresCount; i++) {
84 requiresTable[i] = new ModuleRequires(dataInput);
85 }
86
87 final int exportsCount = dataInput.readUnsignedShort();
88 exportsTable = new ModuleExports[exportsCount];
89 for (int i = 0; i < exportsCount; i++) {
90 exportsTable[i] = new ModuleExports(dataInput);
91 }
92
93 final int opensCount = dataInput.readUnsignedShort();
94 opensTable = new ModuleOpens[opensCount];
95 for (int i = 0; i < opensCount; i++) {
96 opensTable[i] = new ModuleOpens(dataInput);
97 }
98
99 usesIndex = ClassParser.readU2U2Table(dataInput);
100 usesCount = usesIndex.length;
101
102 final int providesCount = dataInput.readUnsignedShort();
103 providesTable = new ModuleProvides[providesCount];
104 for (int i = 0; i < providesCount; i++) {
105 providesTable[i] = new ModuleProvides(dataInput);
106 }
107 }
108
109
110
111
112
113
114
115 @Override
116 public void accept(final Visitor v) {
117 v.visitModule(this);
118 }
119
120
121
122
123 @Override
124 public Attribute copy(final ConstantPool constantPool) {
125 final Module c = (Module) clone();
126
127 c.requiresTable = new ModuleRequires[requiresTable.length];
128 Arrays.setAll(c.requiresTable, i -> requiresTable[i].copy());
129
130 c.exportsTable = new ModuleExports[exportsTable.length];
131 Arrays.setAll(c.exportsTable, i -> exportsTable[i].copy());
132
133 c.opensTable = new ModuleOpens[opensTable.length];
134 Arrays.setAll(c.opensTable, i -> opensTable[i].copy());
135
136 c.providesTable = new ModuleProvides[providesTable.length];
137 Arrays.setAll(c.providesTable, i -> providesTable[i].copy());
138
139 c.setConstantPool(constantPool);
140 return c;
141 }
142
143
144
145
146
147
148
149 @Override
150 public void dump(final DataOutputStream file) throws IOException {
151 super.dump(file);
152
153 file.writeShort(moduleNameIndex);
154 file.writeShort(moduleFlags);
155 file.writeShort(moduleVersionIndex);
156
157 file.writeShort(Args.requireU2(requiresTable.length, "requiresTable.length"));
158 for (final ModuleRequires entry : requiresTable) {
159 entry.dump(file);
160 }
161
162 file.writeShort(Args.requireU2(exportsTable.length, "exportsTable.length"));
163 for (final ModuleExports entry : exportsTable) {
164 entry.dump(file);
165 }
166
167 file.writeShort(Args.requireU2(opensTable.length, "opensTable.length"));
168 for (final ModuleOpens entry : opensTable) {
169 entry.dump(file);
170 }
171
172 file.writeShort(Args.requireU2(usesIndex.length, "usesIndex.length"));
173 for (final int entry : usesIndex) {
174 file.writeShort(entry);
175 }
176
177 file.writeShort(Args.requireU2(providesTable.length, "providesTable.length"));
178 for (final ModuleProvides entry : providesTable) {
179 entry.dump(file);
180 }
181 }
182
183
184
185
186
187
188
189 public ModuleExports[] getExportsTable() {
190 return exportsTable;
191 }
192
193
194
195
196
197
198
199 public int getModuleFlags() {
200 return moduleFlags;
201 }
202
203
204
205
206
207
208
209
210 public String getModuleName(final ConstantPool cp) {
211 return cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module);
212 }
213
214
215
216
217
218
219
220 public ModuleOpens[] getOpensTable() {
221 return opensTable;
222 }
223
224
225
226
227
228
229
230 public ModuleProvides[] getProvidesTable() {
231 return providesTable;
232 }
233
234
235
236
237
238
239
240 public ModuleRequires[] getRequiresTable() {
241 return requiresTable;
242 }
243
244
245
246
247
248
249
250
251
252 public String[] getUsedClassNames(final ConstantPool constantPool, final boolean compactClassName) {
253 final String[] usedClassNames = new String[usesCount];
254 for (int i = 0; i < usesCount; i++) {
255 usedClassNames[i] = getClassNameAtIndex(constantPool, usesIndex[i], compactClassName);
256 }
257 return usedClassNames;
258 }
259
260
261
262
263
264
265
266
267 public String getVersion(final ConstantPool cp) {
268 return moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8);
269 }
270
271
272
273
274 @Override
275 public String toString() {
276 final ConstantPool cp = super.getConstantPool();
277 final StringBuilder buf = new StringBuilder();
278 buf.append("Module:\n");
279 buf.append(" name: ").append(Utility.pathToPackage(getModuleName(cp))).append("\n");
280 buf.append(" flags: ").append(String.format("%04x", moduleFlags)).append("\n");
281 final String version = getVersion(cp);
282 buf.append(" version: ").append(version).append("\n");
283
284 buf.append(" requires(").append(requiresTable.length).append("):\n");
285 for (final ModuleRequires module : requiresTable) {
286 buf.append(" ").append(module.toString(cp)).append("\n");
287 }
288
289 buf.append(" exports(").append(exportsTable.length).append("):\n");
290 for (final ModuleExports module : exportsTable) {
291 buf.append(" ").append(module.toString(cp)).append("\n");
292 }
293
294 buf.append(" opens(").append(opensTable.length).append("):\n");
295 for (final ModuleOpens module : opensTable) {
296 buf.append(" ").append(module.toString(cp)).append("\n");
297 }
298
299 buf.append(" uses(").append(usesIndex.length).append("):\n");
300 for (final int index : usesIndex) {
301 final String className = getClassNameAtIndex(cp, index, true);
302 buf.append(" ").append(className).append("\n");
303 }
304
305 buf.append(" provides(").append(providesTable.length).append("):\n");
306 for (final ModuleProvides module : providesTable) {
307 buf.append(" ").append(module.toString(cp)).append("\n");
308 }
309
310 return buf.substring(0, buf.length() - 1);
311 }
312 }