Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/test/functional/cmdLineTests/shareClassTests/utils/src/CustomCLs/CustomTokenClassLoader.java
6005 views
1
/*******************************************************************************
2
* Copyright (c) 2005, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
package CustomCLs;
23
24
import java.io.ByteArrayOutputStream;
25
import java.io.File;
26
import java.io.FileInputStream;
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.net.JarURLConnection;
30
import java.net.MalformedURLException;
31
import java.net.URL;
32
import java.security.CodeSource;
33
import java.security.SecureClassLoader;
34
import java.util.Hashtable;
35
import java.util.jar.Attributes;
36
import java.util.jar.JarEntry;
37
import java.util.jar.JarFile;
38
import java.util.jar.Manifest;
39
import java.util.jar.Attributes.Name;
40
41
import com.ibm.oti.shared.HelperAlreadyDefinedException;
42
import com.ibm.oti.shared.Shared;
43
import com.ibm.oti.shared.SharedClassHelperFactory;
44
import com.ibm.oti.shared.SharedClassTokenHelper;
45
import com.ibm.oti.shared.SharedClassURLClasspathHelper;
46
import com.ibm.oti.shared.SharedClassURLHelper;
47
48
/**
49
* @author Matthew Kilner
50
*/
51
public class CustomTokenClassLoader extends SecureClassLoader {
52
53
URL[] urls, orgUrls;
54
55
private Hashtable jarCache = new Hashtable(32);
56
int loaderType;
57
58
SharedClassTokenHelper scHelper;
59
60
CustomLoaderMetaDataCache[] metaDataArray;
61
62
String token = null;
63
64
boolean checkCache = true;
65
66
public CustomTokenClassLoader(URL[] passedUrls, ClassLoader parent){
67
super(parent);
68
loaderType = ClassLoaderType.CACHEDURL.ord;
69
int urlLength = passedUrls.length;
70
urls = new URL[urlLength];
71
orgUrls = new URL[urlLength];
72
for (int i=0; i < urlLength; i++) {
73
try {
74
urls[i] = createSearchURL(passedUrls[i]);
75
} catch (MalformedURLException e) {}
76
orgUrls[i] = passedUrls[i];
77
}
78
metaDataArray = new CustomLoaderMetaDataCache[urls.length];
79
initMetaData();
80
SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();
81
if(schFactory != null){
82
try{
83
scHelper = schFactory.getTokenHelper(this);
84
} catch (Exception e){
85
e.printStackTrace();
86
}
87
}
88
}
89
90
public CustomTokenClassLoader(URL[] passedUrls){
91
super();
92
loaderType = ClassLoaderType.CACHEDURL.ord;
93
int urlLength = passedUrls.length;
94
urls = new URL[urlLength];
95
orgUrls = new URL[urlLength];
96
for (int i=0; i < urlLength; i++) {
97
try {
98
urls[i] = createSearchURL(passedUrls[i]);
99
} catch (MalformedURLException e) {}
100
orgUrls[i] = passedUrls[i];
101
}
102
metaDataArray = new CustomLoaderMetaDataCache[urls.length];
103
initMetaData();
104
SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();
105
if(schFactory != null){
106
try{
107
scHelper = schFactory.getTokenHelper(this);
108
} catch (Exception e){
109
e.printStackTrace();
110
}
111
}
112
}
113
114
public void setToken(String setTo){
115
token = setTo;
116
}
117
118
public boolean getHelper(){
119
SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();
120
SharedClassTokenHelper newHelper = null;
121
try{
122
newHelper = schFactory.getTokenHelper(this);
123
} catch (Exception e){
124
return false;
125
}
126
127
if(newHelper.equals(scHelper)){
128
return true;
129
} else {
130
return false;
131
}
132
}
133
134
public void getURLClasspathHelper()throws HelperAlreadyDefinedException {
135
SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();
136
SharedClassURLClasspathHelper newHelper = null;
137
newHelper = schFactory.getURLClasspathHelper(this, urls);
138
}
139
140
public void getURLHelper()throws Exception {
141
SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();
142
SharedClassURLHelper newHelper = null;
143
newHelper = schFactory.getURLHelper(this);
144
}
145
146
public boolean duplicateStore(String name){
147
Class clazz = null;
148
try{
149
clazz = this.loadClass(name);
150
} catch (ClassNotFoundException e){
151
e.printStackTrace();
152
}
153
if (clazz != null){
154
int indexFoundAt = locateClass(name);
155
if(indexFoundAt != -1){
156
scHelper.storeSharedClass(token, clazz);
157
return true;
158
}
159
}
160
return false;
161
}
162
163
private void initMetaData(){
164
for(int loopIndex = 0; loopIndex < metaDataArray.length; loopIndex++){
165
metaDataArray[loopIndex] = null;
166
}
167
}
168
169
private URL createSearchURL(URL url) throws MalformedURLException {
170
if (url == null) return url;
171
String protocol = url.getProtocol();
172
173
if (isDirectory(url) || protocol.equals("jar")) {
174
return url;
175
} else {
176
return new URL("jar", "", -1, url.toString() + "!/");
177
}
178
}
179
180
private static boolean isDirectory(URL url) {
181
String file = url.getFile();
182
return (file.length() > 0 && file.charAt(file.length()-1) == '/');
183
}
184
185
public Class findClass(String name) throws ClassNotFoundException {
186
Class clazz = null;
187
int indexFoundAt = locateClass(name);
188
if(checkCache){
189
if(scHelper != null){
190
byte[] classBytes = scHelper.findSharedClass(token, name);
191
if(classBytes != null){
192
if(metaDataArray[indexFoundAt] != null){
193
checkPackage(name, indexFoundAt);
194
CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];
195
CodeSource codeSource = metadata.codeSource;
196
clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);
197
}
198
}
199
}
200
}
201
if(clazz == null) {
202
if(indexFoundAt != -1){
203
try{
204
byte[] classBytes = loadClassBytes(name, indexFoundAt);
205
checkPackage(name, indexFoundAt);
206
CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];
207
CodeSource codeSource = metadata.codeSource;
208
clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);
209
if(clazz != null){
210
scHelper.storeSharedClass(token, clazz);
211
}
212
} catch (Exception e){
213
e.printStackTrace();
214
}
215
}
216
if(clazz == null){
217
throw new ClassNotFoundException(name);
218
}
219
}
220
return clazz;
221
}
222
223
private void checkPackage(String name, int urlIndex){
224
int index = name.lastIndexOf('.');
225
if(index != -1){
226
String packageString = name.substring(0, index);
227
Manifest manifest = metaDataArray[urlIndex].manifest;
228
CodeSource codeSource = metaDataArray[urlIndex].codeSource;
229
synchronized(this){
230
Package packageInst = getPackage(packageString);
231
if(packageInst == null){
232
if (manifest != null){
233
definePackage(packageString, manifest, codeSource.getLocation());
234
} else {
235
definePackage(packageString, null, null, null, null, null, null, null);
236
}
237
} else {
238
boolean exception = false;
239
if (manifest != null) {
240
String dirName = packageString.replace('.', '/') + "/";
241
if (isSealed(manifest, dirName))
242
exception = !packageInst.isSealed(codeSource.getLocation());
243
} else
244
exception = packageInst.isSealed();
245
if (exception)
246
throw new SecurityException(com.ibm.oti.util.Msg.getString("Package exception"));
247
}
248
}
249
}
250
}
251
252
private static byte[] getBytes(InputStream is, boolean readAvailable) throws IOException {
253
if (readAvailable) {
254
byte[] buf = new byte[is.available()];
255
is.read(buf, 0, buf.length);
256
is.close();
257
return buf;
258
}
259
byte[] buf = new byte[4096];
260
int size = is.available();
261
if (size < 1024) size = 1024;
262
ByteArrayOutputStream bos = new ByteArrayOutputStream(size);
263
int count;
264
while ((count = is.read(buf)) > 0)
265
bos.write(buf, 0, count);
266
return bos.toByteArray();
267
}
268
269
private byte[] loadClassBytes(String className, int urlIndex){
270
byte[] bytes = null;
271
String name = className.replace('.','/').concat(".class");
272
URL classLocation = urls[urlIndex];
273
if(classLocation.getProtocol().equals("jar")){
274
JarFile jf = (JarFile)jarCache.get(classLocation);
275
JarEntry entry = jf.getJarEntry(name);
276
try{
277
InputStream stream = jf.getInputStream(entry);
278
bytes = getBytes(stream, true);
279
} catch (Exception e){
280
e.printStackTrace();
281
}
282
} else {
283
String filename = classLocation.getFile();
284
String host = classLocation.getHost();
285
if (host != null && host.length() > 0) {
286
filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).
287
append("//").append(host).append(filename).append(name).toString();
288
} else {
289
filename = new StringBuffer(filename.length() + name.length()).
290
append(filename).append(name).toString();
291
}
292
File file = new File(filename);
293
// Don't throw exceptions for speed
294
if (file.exists()) {
295
try{
296
FileInputStream stream = new FileInputStream(file);
297
bytes = getBytes(stream, true);
298
} catch(Exception e){
299
e.printStackTrace();
300
}
301
}
302
}
303
return bytes;
304
}
305
306
private int locateClass(String className){
307
int classAtEntry = -1;
308
String name = className.replace('.','/').concat(".class");
309
for(int index = 0; index < urls.length; index ++){
310
URL currentUrl = urls[index];
311
if(currentUrl.getProtocol().equals("jar")){
312
JarEntry entry = null;
313
JarFile jf = (JarFile)jarCache.get(currentUrl);
314
if(jf == null){
315
/* First time we have encountered this jar.
316
* Lets cache its metaData.
317
*/
318
try{
319
URL jarFileUrl = ((JarURLConnection)currentUrl.openConnection()).getJarFileURL();
320
JarURLConnection jarUrlConnection = (JarURLConnection)new URL("jar", "", jarFileUrl.toExternalForm() + "!/").openConnection();
321
try{
322
jf = jarUrlConnection.getJarFile();
323
}catch(Exception e){
324
}
325
if(jf != null){
326
jarCache.put(currentUrl, jf);
327
}
328
} catch (Exception e){
329
e.printStackTrace();
330
}
331
if(jf != null){
332
Manifest manifest = null;
333
java.security.cert.Certificate[] certs = null;
334
URL csUrl = currentUrl;
335
CodeSource codeSource;
336
try{
337
manifest = jf.getManifest();
338
} catch(Exception e){
339
e.printStackTrace();
340
}
341
entry = jf.getJarEntry(name);
342
if(entry != null){
343
certs = entry.getCertificates();
344
}
345
codeSource = new CodeSource(csUrl, certs);
346
CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();
347
metaData.manifest = manifest;
348
metaData.codeSource = codeSource;
349
metaDataArray[index] = metaData;
350
}
351
}
352
if(entry == null && jf != null){
353
entry = jf.getJarEntry(name);
354
}
355
if(entry != null){
356
/* We have the first match on the class path, return the current url index */
357
return index;
358
}
359
} else {
360
String filename = currentUrl.getFile();
361
String host = currentUrl.getHost();
362
if (host != null && host.length() > 0) {
363
filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).
364
append("//").append(host).append(filename).append(name).toString();
365
} else {
366
filename = new StringBuffer(filename.length() + name.length()).
367
append(filename).append(name).toString();
368
}
369
File file = new File(filename);
370
// Don't throw exceptions for speed
371
if (file.exists()) {
372
if(metaDataArray[index] == null){
373
java.security.cert.Certificate[] certs = null;
374
CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();
375
metaData.manifest = null;
376
metaData.codeSource = new CodeSource(currentUrl, certs);
377
metaDataArray[index] = metaData;
378
}
379
return index;
380
}
381
}
382
}
383
return classAtEntry;
384
}
385
386
private boolean isSealed(Manifest manifest, String dirName) {
387
Attributes mainAttributes = manifest.getMainAttributes();
388
String value = mainAttributes.getValue(Attributes.Name.SEALED);
389
boolean sealed = value != null &&
390
value.toLowerCase().equals ("true");
391
Attributes attributes = manifest.getAttributes(dirName);
392
if (attributes != null) {
393
value = attributes.getValue(Attributes.Name.SEALED);
394
if (value != null)
395
sealed = value.toLowerCase().equals("true");
396
}
397
return sealed;
398
}
399
400
protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException {
401
String path = name.replace('.','/').concat("/");
402
String[] attrs = new String[7];
403
URL sealedAtURL = null;
404
405
Attributes attr = man.getAttributes(path);
406
Attributes mainAttr = man.getMainAttributes();
407
408
if(attr != null){
409
attrs[0] = attr.getValue(Name.SPECIFICATION_TITLE);
410
attrs[1] = attr.getValue(Name.SPECIFICATION_VERSION);
411
attrs[2] = attr.getValue(Name.SPECIFICATION_VENDOR);
412
attrs[3] = attr.getValue(Name.IMPLEMENTATION_TITLE);
413
attrs[4] = attr.getValue(Name.IMPLEMENTATION_VERSION);
414
attrs[5] = attr.getValue(Name.IMPLEMENTATION_VENDOR);
415
attrs[6] = attr.getValue(Name.SEALED);
416
}
417
418
if(mainAttr != null){
419
if (attrs[0] == null) {
420
attrs[0] = mainAttr.getValue(Name.SPECIFICATION_TITLE);
421
}
422
if (attrs[1] == null) {
423
attrs[1] = mainAttr.getValue(Name.SPECIFICATION_VERSION);
424
}
425
if (attrs[2] == null) {
426
attrs[2] = mainAttr.getValue(Name.SPECIFICATION_VENDOR);
427
}
428
if (attrs[3] == null) {
429
attrs[3] = mainAttr.getValue(Name.IMPLEMENTATION_TITLE);
430
}
431
if (attrs[4] == null) {
432
attrs[4] = mainAttr.getValue(Name.IMPLEMENTATION_VERSION);
433
}
434
if (attrs[5] == null) {
435
attrs[5] = mainAttr.getValue(Name.IMPLEMENTATION_VENDOR);
436
}
437
if (attrs[6] == null) {
438
attrs[6] = mainAttr.getValue(Name.SEALED);
439
}
440
}
441
if ("true".equalsIgnoreCase(attrs[6])){
442
sealedAtURL = url;
443
}
444
return definePackage(name, attrs[0], attrs[1], attrs[2], attrs[3], attrs[4], attrs[5], sealedAtURL);
445
}
446
447
public boolean isClassInSharedCache(String token, String className){
448
byte[] sharedClass = null;
449
if (scHelper!=null) {
450
sharedClass = scHelper.findSharedClass(token, className);
451
if (sharedClass !=null){
452
return true;
453
} else {
454
return false;
455
}
456
}
457
System.out.println("CustomTokenClassLoader::isClassInSharedCache scHelper is null");
458
return false;
459
}
460
461
public Class getClassFromCache(String name){
462
Class clazz = null;
463
byte[] classBytes = scHelper.findSharedClass(token, name);
464
if(classBytes != null){
465
CodeSource cs = null;
466
clazz = defineClass(name, classBytes, 0, classBytes.length, cs);
467
}
468
return clazz;
469
}
470
471
public Class loadClassNoCache(String name) {
472
Class clazz = null;
473
checkCache = false;
474
try{
475
clazz = this.loadClass(name);
476
}catch(ClassNotFoundException e){
477
e.printStackTrace();
478
}
479
checkCache = true;
480
return clazz;
481
}
482
483
}
484
485