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