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