Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java
41159 views
1
/*
2
* Copyright (c) 2014, 2021, 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
26
package jdk.internal.jimage;
27
28
import java.nio.ByteBuffer;
29
import java.util.Objects;
30
31
/**
32
* @implNote This class needs to maintain JDK 8 source compatibility.
33
*
34
* It is used internally in the JDK to implement jimage/jrtfs access,
35
* but also compiled and delivered as part of the jrtfs.jar to support access
36
* to the jimage file provided by the shipped JDK by tools running on JDK 8.
37
*/
38
public class ImageLocation {
39
public static final int ATTRIBUTE_END = 0;
40
public static final int ATTRIBUTE_MODULE = 1;
41
public static final int ATTRIBUTE_PARENT = 2;
42
public static final int ATTRIBUTE_BASE = 3;
43
public static final int ATTRIBUTE_EXTENSION = 4;
44
public static final int ATTRIBUTE_OFFSET = 5;
45
public static final int ATTRIBUTE_COMPRESSED = 6;
46
public static final int ATTRIBUTE_UNCOMPRESSED = 7;
47
public static final int ATTRIBUTE_COUNT = 8;
48
49
protected final long[] attributes;
50
51
protected final ImageStrings strings;
52
53
public ImageLocation(long[] attributes, ImageStrings strings) {
54
this.attributes = Objects.requireNonNull(attributes);
55
this.strings = Objects.requireNonNull(strings);
56
}
57
58
ImageStrings getStrings() {
59
return strings;
60
}
61
62
static long[] decompress(ByteBuffer bytes, int offset) {
63
Objects.requireNonNull(bytes);
64
long[] attributes = new long[ATTRIBUTE_COUNT];
65
66
int limit = bytes.limit();
67
while (offset < limit) {
68
int data = bytes.get(offset++) & 0xFF;
69
if (data <= 0x7) { // ATTRIBUTE_END
70
break;
71
}
72
int kind = data >>> 3;
73
if (ATTRIBUTE_COUNT <= kind) {
74
throw new InternalError(
75
"Invalid jimage attribute kind: " + kind);
76
}
77
78
int length = (data & 0x7) + 1;
79
attributes[kind] = readValue(length, bytes, offset, limit);
80
offset += length;
81
}
82
return attributes;
83
}
84
85
public static byte[] compress(long[] attributes) {
86
Objects.requireNonNull(attributes);
87
ImageStream stream = new ImageStream(16);
88
89
for (int kind = ATTRIBUTE_END + 1; kind < ATTRIBUTE_COUNT; kind++) {
90
long value = attributes[kind];
91
92
if (value != 0) {
93
int n = (63 - Long.numberOfLeadingZeros(value)) >> 3;
94
stream.put((kind << 3) | n);
95
96
for (int i = n; i >= 0; i--) {
97
stream.put((int)(value >> (i << 3)));
98
}
99
}
100
}
101
102
stream.put(ATTRIBUTE_END << 3);
103
104
return stream.toArray();
105
}
106
107
public boolean verify(String name) {
108
return verify(name, attributes, strings);
109
}
110
111
/**
112
* A simpler verification would be {@code name.equals(getFullName())}, but
113
* by not creating the full name and enabling early returns we allocate
114
* fewer objects.
115
*/
116
static boolean verify(String name, long[] attributes, ImageStrings strings) {
117
Objects.requireNonNull(name);
118
final int length = name.length();
119
int index = 0;
120
int moduleOffset = (int)attributes[ATTRIBUTE_MODULE];
121
if (moduleOffset != 0 && length >= 1) {
122
int moduleLen = strings.match(moduleOffset, name, 1);
123
index = moduleLen + 1;
124
if (moduleLen < 0
125
|| length <= index
126
|| name.charAt(0) != '/'
127
|| name.charAt(index++) != '/') {
128
return false;
129
}
130
}
131
return verifyName(null, name, index, length, 0,
132
(int) attributes[ATTRIBUTE_PARENT],
133
(int) attributes[ATTRIBUTE_BASE],
134
(int) attributes[ATTRIBUTE_EXTENSION],
135
strings);
136
}
137
138
static boolean verify(String module, String name, ByteBuffer locations,
139
int locationOffset, ImageStrings strings) {
140
int moduleOffset = 0;
141
int parentOffset = 0;
142
int baseOffset = 0;
143
int extOffset = 0;
144
145
int limit = locations.limit();
146
while (locationOffset < limit) {
147
int data = locations.get(locationOffset++) & 0xFF;
148
if (data <= 0x7) { // ATTRIBUTE_END
149
break;
150
}
151
int kind = data >>> 3;
152
if (ATTRIBUTE_COUNT <= kind) {
153
throw new InternalError(
154
"Invalid jimage attribute kind: " + kind);
155
}
156
157
int length = (data & 0x7) + 1;
158
switch (kind) {
159
case ATTRIBUTE_MODULE:
160
moduleOffset = (int) readValue(length, locations, locationOffset, limit);
161
break;
162
case ATTRIBUTE_BASE:
163
baseOffset = (int) readValue(length, locations, locationOffset, limit);
164
break;
165
case ATTRIBUTE_PARENT:
166
parentOffset = (int) readValue(length, locations, locationOffset, limit);
167
break;
168
case ATTRIBUTE_EXTENSION:
169
extOffset = (int) readValue(length, locations, locationOffset, limit);
170
break;
171
}
172
locationOffset += length;
173
}
174
return verifyName(module, name, 0, name.length(),
175
moduleOffset, parentOffset, baseOffset, extOffset, strings);
176
}
177
178
private static long readValue(int length, ByteBuffer buffer, int offset, int limit) {
179
long value = 0;
180
for (int j = 0; j < length; j++) {
181
value <<= 8;
182
if (offset >= limit) {
183
throw new InternalError("Missing jimage attribute data");
184
}
185
value |= buffer.get(offset++) & 0xFF;
186
}
187
return value;
188
}
189
190
static boolean verify(String module, String name, long[] attributes,
191
ImageStrings strings) {
192
Objects.requireNonNull(module);
193
Objects.requireNonNull(name);
194
return verifyName(module, name, 0, name.length(),
195
(int) attributes[ATTRIBUTE_MODULE],
196
(int) attributes[ATTRIBUTE_PARENT],
197
(int) attributes[ATTRIBUTE_BASE],
198
(int) attributes[ATTRIBUTE_EXTENSION],
199
strings);
200
}
201
202
private static boolean verifyName(String module, String name, int index, int length,
203
int moduleOffset, int parentOffset, int baseOffset, int extOffset, ImageStrings strings) {
204
205
if (moduleOffset != 0) {
206
if (strings.match(moduleOffset, module, 0) != module.length()) {
207
return false;
208
}
209
}
210
if (parentOffset != 0) {
211
int parentLen = strings.match(parentOffset, name, index);
212
if (parentLen < 0) {
213
return false;
214
}
215
index += parentLen;
216
if (length <= index || name.charAt(index++) != '/') {
217
return false;
218
}
219
}
220
int baseLen = strings.match(baseOffset, name, index);
221
if (baseLen < 0) {
222
return false;
223
}
224
index += baseLen;
225
if (extOffset != 0) {
226
if (length <= index
227
|| name.charAt(index++) != '.') {
228
return false;
229
}
230
231
int extLen = strings.match(extOffset, name, index);
232
if (extLen < 0) {
233
return false;
234
}
235
index += extLen;
236
}
237
return length == index;
238
}
239
240
long getAttribute(int kind) {
241
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
242
throw new InternalError(
243
"Invalid jimage attribute kind: " + kind);
244
}
245
return attributes[kind];
246
}
247
248
String getAttributeString(int kind) {
249
if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) {
250
throw new InternalError(
251
"Invalid jimage attribute kind: " + kind);
252
}
253
return getStrings().get((int)attributes[kind]);
254
}
255
256
public String getModule() {
257
return getAttributeString(ATTRIBUTE_MODULE);
258
}
259
260
public int getModuleOffset() {
261
return (int)getAttribute(ATTRIBUTE_MODULE);
262
}
263
264
public String getBase() {
265
return getAttributeString(ATTRIBUTE_BASE);
266
}
267
268
public int getBaseOffset() {
269
return (int)getAttribute(ATTRIBUTE_BASE);
270
}
271
272
public String getParent() {
273
return getAttributeString(ATTRIBUTE_PARENT);
274
}
275
276
public int getParentOffset() {
277
return (int)getAttribute(ATTRIBUTE_PARENT);
278
}
279
280
public String getExtension() {
281
return getAttributeString(ATTRIBUTE_EXTENSION);
282
}
283
284
public int getExtensionOffset() {
285
return (int)getAttribute(ATTRIBUTE_EXTENSION);
286
}
287
288
public String getFullName() {
289
return getFullName(false);
290
}
291
292
public String getFullName(boolean modulesPrefix) {
293
StringBuilder builder = new StringBuilder();
294
295
if (getModuleOffset() != 0) {
296
if (modulesPrefix) {
297
builder.append("/modules");
298
}
299
300
builder.append('/');
301
builder.append(getModule());
302
builder.append('/');
303
}
304
305
if (getParentOffset() != 0) {
306
builder.append(getParent());
307
builder.append('/');
308
}
309
310
builder.append(getBase());
311
312
if (getExtensionOffset() != 0) {
313
builder.append('.');
314
builder.append(getExtension());
315
}
316
317
return builder.toString();
318
}
319
320
String buildName(boolean includeModule, boolean includeParent,
321
boolean includeName) {
322
StringBuilder builder = new StringBuilder();
323
324
if (includeModule && getModuleOffset() != 0) {
325
builder.append("/modules/");
326
builder.append(getModule());
327
}
328
329
if (includeParent && getParentOffset() != 0) {
330
builder.append('/');
331
builder.append(getParent());
332
}
333
334
if (includeName) {
335
if (includeModule || includeParent) {
336
builder.append('/');
337
}
338
339
builder.append(getBase());
340
341
if (getExtensionOffset() != 0) {
342
builder.append('.');
343
builder.append(getExtension());
344
}
345
}
346
347
return builder.toString();
348
}
349
350
public long getContentOffset() {
351
return getAttribute(ATTRIBUTE_OFFSET);
352
}
353
354
public long getCompressedSize() {
355
return getAttribute(ATTRIBUTE_COMPRESSED);
356
}
357
358
public long getUncompressedSize() {
359
return getAttribute(ATTRIBUTE_UNCOMPRESSED);
360
}
361
362
static ImageLocation readFrom(BasicImageReader reader, int offset) {
363
Objects.requireNonNull(reader);
364
long[] attributes = reader.getAttributes(offset);
365
ImageStringsReader strings = reader.getStrings();
366
367
return new ImageLocation(attributes, strings);
368
}
369
}
370
371