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 dataInput, final ConstantPool constantPool) throws IOException {
74 super(Const.ATTR_MODULE, nameIndex, length, constantPool);
75
76 moduleNameIndex = dataInput.readUnsignedShort();
77 moduleFlags = dataInput.readUnsignedShort();
78 moduleVersionIndex = dataInput.readUnsignedShort();
79
80 final int requiresCount = dataInput.readUnsignedShort();
81 requiresTable = new ModuleRequires[requiresCount];
82 for (int i = 0; i < requiresCount; i++) {
83 requiresTable[i] = new ModuleRequires(dataInput);
84 }
85
86 final int exportsCount = dataInput.readUnsignedShort();
87 exportsTable = new ModuleExports[exportsCount];
88 for (int i = 0; i < exportsCount; i++) {
89 exportsTable[i] = new ModuleExports(dataInput);
90 }
91
92 final int opensCount = dataInput.readUnsignedShort();
93 opensTable = new ModuleOpens[opensCount];
94 for (int i = 0; i < opensCount; i++) {
95 opensTable[i] = new ModuleOpens(dataInput);
96 }
97
98 usesIndex = ClassParser.readU2U2Table(dataInput);
99 usesCount = usesIndex.length;
100
101 final int providesCount = dataInput.readUnsignedShort();
102 providesTable = new ModuleProvides[providesCount];
103 for (int i = 0; i < providesCount; i++) {
104 providesTable[i] = new ModuleProvides(dataInput);
105 }
106 }
107
108
109
110
111
112
113
114 @Override
115 public void accept(final Visitor v) {
116 v.visitModule(this);
117 }
118
119
120
121
122 @Override
123 public Attribute copy(final ConstantPool constantPool) {
124 final Module c = (Module) clone();
125
126 c.requiresTable = new ModuleRequires[requiresTable.length];
127 Arrays.setAll(c.requiresTable, i -> requiresTable[i].copy());
128
129 c.exportsTable = new ModuleExports[exportsTable.length];
130 Arrays.setAll(c.exportsTable, i -> exportsTable[i].copy());
131
132 c.opensTable = new ModuleOpens[opensTable.length];
133 Arrays.setAll(c.opensTable, i -> opensTable[i].copy());
134
135 c.providesTable = new ModuleProvides[providesTable.length];
136 Arrays.setAll(c.providesTable, i -> providesTable[i].copy());
137
138 c.setConstantPool(constantPool);
139 return c;
140 }
141
142
143
144
145
146
147
148 @Override
149 public void dump(final DataOutputStream file) throws IOException {
150 super.dump(file);
151
152 file.writeShort(moduleNameIndex);
153 file.writeShort(moduleFlags);
154 file.writeShort(moduleVersionIndex);
155
156 file.writeShort(requiresTable.length);
157 for (final ModuleRequires entry : requiresTable) {
158 entry.dump(file);
159 }
160
161 file.writeShort(exportsTable.length);
162 for (final ModuleExports entry : exportsTable) {
163 entry.dump(file);
164 }
165
166 file.writeShort(opensTable.length);
167 for (final ModuleOpens entry : opensTable) {
168 entry.dump(file);
169 }
170
171 file.writeShort(usesIndex.length);
172 for (final int entry : usesIndex) {
173 file.writeShort(entry);
174 }
175
176 file.writeShort(providesTable.length);
177 for (final ModuleProvides entry : providesTable) {
178 entry.dump(file);
179 }
180 }
181
182
183
184
185
186 public ModuleExports[] getExportsTable() {
187 return exportsTable;
188 }
189
190
191
192
193
194
195
196 public int getModuleFlags() {
197 return moduleFlags;
198 }
199
200
201
202
203
204
205
206
207 public String getModuleName(final ConstantPool cp) {
208 return cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module);
209 }
210
211
212
213
214
215 public ModuleOpens[] getOpensTable() {
216 return opensTable;
217 }
218
219
220
221
222
223 public ModuleProvides[] getProvidesTable() {
224 return providesTable;
225 }
226
227
228
229
230
231 public ModuleRequires[] getRequiresTable() {
232 return requiresTable;
233 }
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
258 public String getVersion(final ConstantPool cp) {
259 return moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8);
260 }
261
262
263
264
265 @Override
266 public String toString() {
267 final ConstantPool cp = super.getConstantPool();
268 final StringBuilder buf = new StringBuilder();
269 buf.append("Module:\n");
270 buf.append(" name: ").append(Utility.pathToPackage(getModuleName(cp))).append("\n");
271 buf.append(" flags: ").append(String.format("%04x", moduleFlags)).append("\n");
272 final String version = getVersion(cp);
273 buf.append(" version: ").append(version).append("\n");
274
275 buf.append(" requires(").append(requiresTable.length).append("):\n");
276 for (final ModuleRequires module : requiresTable) {
277 buf.append(" ").append(module.toString(cp)).append("\n");
278 }
279
280 buf.append(" exports(").append(exportsTable.length).append("):\n");
281 for (final ModuleExports module : exportsTable) {
282 buf.append(" ").append(module.toString(cp)).append("\n");
283 }
284
285 buf.append(" opens(").append(opensTable.length).append("):\n");
286 for (final ModuleOpens module : opensTable) {
287 buf.append(" ").append(module.toString(cp)).append("\n");
288 }
289
290 buf.append(" uses(").append(usesIndex.length).append("):\n");
291 for (final int index : usesIndex) {
292 final String className = getClassNameAtIndex(cp, index, true);
293 buf.append(" ").append(className).append("\n");
294 }
295
296 buf.append(" provides(").append(providesTable.length).append("):\n");
297 for (final ModuleProvides module : providesTable) {
298 buf.append(" ").append(module.toString(cp)).append("\n");
299 }
300
301 return buf.substring(0, buf.length() - 1);
302 }
303 }