Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/applet/AppletClassLoader.java
38829 views
1
/*
2
* Copyright (c) 1995, 2013, 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 sun.applet;
27
28
import java.lang.NullPointerException;
29
import java.net.URL;
30
import java.net.URLClassLoader;
31
import java.net.SocketPermission;
32
import java.net.URLConnection;
33
import java.net.MalformedURLException;
34
import java.net.InetAddress;
35
import java.net.UnknownHostException;
36
import java.io.EOFException;
37
import java.io.File;
38
import java.io.FilePermission;
39
import java.io.IOException;
40
import java.io.BufferedInputStream;
41
import java.io.InputStream;
42
import java.util.Enumeration;
43
import java.util.HashMap;
44
import java.util.NoSuchElementException;
45
import java.security.AccessController;
46
import java.security.AccessControlContext;
47
import java.security.PrivilegedAction;
48
import java.security.PrivilegedExceptionAction;
49
import java.security.PrivilegedActionException;
50
import java.security.CodeSource;
51
import java.security.Permission;
52
import java.security.PermissionCollection;
53
import sun.awt.AppContext;
54
import sun.awt.SunToolkit;
55
import sun.misc.IOUtils;
56
import sun.net.www.ParseUtil;
57
import sun.security.util.SecurityConstants;
58
59
/**
60
* This class defines the class loader for loading applet classes and
61
* resources. It extends URLClassLoader to search the applet code base
62
* for the class or resource after checking any loaded JAR files.
63
*/
64
public class AppletClassLoader extends URLClassLoader {
65
private URL base; /* applet code base URL */
66
private CodeSource codesource; /* codesource for the base URL */
67
private AccessControlContext acc;
68
private boolean exceptionStatus = false;
69
70
private final Object threadGroupSynchronizer = new Object();
71
private final Object grabReleaseSynchronizer = new Object();
72
73
private boolean codebaseLookup = true;
74
private volatile boolean allowRecursiveDirectoryRead = true;
75
76
/*
77
* Creates a new AppletClassLoader for the specified base URL.
78
*/
79
protected AppletClassLoader(URL base) {
80
super(new URL[0]);
81
this.base = base;
82
this.codesource =
83
new CodeSource(base, (java.security.cert.Certificate[]) null);
84
acc = AccessController.getContext();
85
}
86
87
public void disableRecursiveDirectoryRead() {
88
allowRecursiveDirectoryRead = false;
89
}
90
91
92
/**
93
* Set the codebase lookup flag.
94
*/
95
void setCodebaseLookup(boolean codebaseLookup) {
96
this.codebaseLookup = codebaseLookup;
97
}
98
99
/*
100
* Returns the applet code base URL.
101
*/
102
URL getBaseURL() {
103
return base;
104
}
105
106
/*
107
* Returns the URLs used for loading classes and resources.
108
*/
109
public URL[] getURLs() {
110
URL[] jars = super.getURLs();
111
URL[] urls = new URL[jars.length + 1];
112
System.arraycopy(jars, 0, urls, 0, jars.length);
113
urls[urls.length - 1] = base;
114
return urls;
115
}
116
117
/*
118
* Adds the specified JAR file to the search path of loaded JAR files.
119
* Changed modifier to protected in order to be able to overwrite addJar()
120
* in PluginClassLoader.java
121
*/
122
protected void addJar(String name) throws IOException {
123
URL url;
124
try {
125
url = new URL(base, name);
126
} catch (MalformedURLException e) {
127
throw new IllegalArgumentException("name");
128
}
129
addURL(url);
130
// DEBUG
131
//URL[] urls = getURLs();
132
//for (int i = 0; i < urls.length; i++) {
133
// System.out.println("url[" + i + "] = " + urls[i]);
134
//}
135
}
136
137
/*
138
* Override loadClass so that class loading errors can be caught in
139
* order to print better error messages.
140
*/
141
public synchronized Class loadClass(String name, boolean resolve)
142
throws ClassNotFoundException
143
{
144
// First check if we have permission to access the package. This
145
// should go away once we've added support for exported packages.
146
int i = name.lastIndexOf('.');
147
if (i != -1) {
148
SecurityManager sm = System.getSecurityManager();
149
if (sm != null)
150
sm.checkPackageAccess(name.substring(0, i));
151
}
152
try {
153
return super.loadClass(name, resolve);
154
} catch (ClassNotFoundException e) {
155
//printError(name, e.getException());
156
throw e;
157
} catch (RuntimeException e) {
158
//printError(name, e);
159
throw e;
160
} catch (Error e) {
161
//printError(name, e);
162
throw e;
163
}
164
}
165
166
/*
167
* Finds the applet class with the specified name. First searches
168
* loaded JAR files then the applet code base for the class.
169
*/
170
protected Class findClass(String name) throws ClassNotFoundException {
171
172
int index = name.indexOf(";");
173
String cookie = "";
174
if(index != -1) {
175
cookie = name.substring(index, name.length());
176
name = name.substring(0, index);
177
}
178
179
// check loaded JAR files
180
try {
181
return super.findClass(name);
182
} catch (ClassNotFoundException e) {
183
}
184
185
// Otherwise, try loading the class from the code base URL
186
187
// 4668479: Option to turn off codebase lookup in AppletClassLoader
188
// during resource requests. [stanley.ho]
189
if (codebaseLookup == false)
190
throw new ClassNotFoundException(name);
191
192
// final String path = name.replace('.', '/').concat(".class").concat(cookie);
193
String encodedName = ParseUtil.encodePath(name.replace('.', '/'), false);
194
final String path = (new StringBuffer(encodedName)).append(".class").append(cookie).toString();
195
try {
196
byte[] b = (byte[]) AccessController.doPrivileged(
197
new PrivilegedExceptionAction() {
198
public Object run() throws IOException {
199
try {
200
URL finalURL = new URL(base, path);
201
202
// Make sure the codebase won't be modified
203
if (base.getProtocol().equals(finalURL.getProtocol()) &&
204
base.getHost().equals(finalURL.getHost()) &&
205
base.getPort() == finalURL.getPort()) {
206
return getBytes(finalURL);
207
}
208
else {
209
return null;
210
}
211
} catch (Exception e) {
212
return null;
213
}
214
}
215
}, acc);
216
217
if (b != null) {
218
return defineClass(name, b, 0, b.length, codesource);
219
} else {
220
throw new ClassNotFoundException(name);
221
}
222
} catch (PrivilegedActionException e) {
223
throw new ClassNotFoundException(name, e.getException());
224
}
225
}
226
227
/**
228
* Returns the permissions for the given codesource object.
229
* The implementation of this method first calls super.getPermissions,
230
* to get the permissions
231
* granted by the super class, and then adds additional permissions
232
* based on the URL of the codesource.
233
* <p>
234
* If the protocol is "file"
235
* and the path specifies a file, permission is granted to read all files
236
* and (recursively) all files and subdirectories contained in
237
* that directory. This is so applets with a codebase of
238
* file:/blah/some.jar can read in file:/blah/, which is needed to
239
* be backward compatible. We also add permission to connect back to
240
* the "localhost".
241
*
242
* @param codesource the codesource
243
* @throws NullPointerException if {@code codesource} is {@code null}.
244
* @return the permissions granted to the codesource
245
*/
246
protected PermissionCollection getPermissions(CodeSource codesource)
247
{
248
final PermissionCollection perms = super.getPermissions(codesource);
249
250
URL url = codesource.getLocation();
251
252
String path = null;
253
Permission p;
254
255
try {
256
p = url.openConnection().getPermission();
257
} catch (java.io.IOException ioe) {
258
p = null;
259
}
260
261
if (p instanceof FilePermission) {
262
path = p.getName();
263
} else if ((p == null) && (url.getProtocol().equals("file"))) {
264
path = url.getFile().replace('/', File.separatorChar);
265
path = ParseUtil.decode(path);
266
}
267
268
if (path != null) {
269
final String rawPath = path;
270
if (!path.endsWith(File.separator)) {
271
int endIndex = path.lastIndexOf(File.separatorChar);
272
if (endIndex != -1) {
273
path = path.substring(0, endIndex + 1) + "-";
274
perms.add(new FilePermission(path,
275
SecurityConstants.FILE_READ_ACTION));
276
}
277
}
278
final File f = new File(rawPath);
279
final boolean isDirectory = f.isDirectory();
280
// grant codebase recursive read permission
281
// this should only be granted to non-UNC file URL codebase and
282
// the codesource path must either be a directory, or a file
283
// that ends with .jar or .zip
284
if (allowRecursiveDirectoryRead && (isDirectory ||
285
rawPath.toLowerCase().endsWith(".jar") ||
286
rawPath.toLowerCase().endsWith(".zip"))) {
287
288
Permission bperm;
289
try {
290
bperm = base.openConnection().getPermission();
291
} catch (java.io.IOException ioe) {
292
bperm = null;
293
}
294
if (bperm instanceof FilePermission) {
295
String bpath = bperm.getName();
296
if (bpath.endsWith(File.separator)) {
297
bpath += "-";
298
}
299
perms.add(new FilePermission(bpath,
300
SecurityConstants.FILE_READ_ACTION));
301
} else if ((bperm == null) && (base.getProtocol().equals("file"))) {
302
String bpath = base.getFile().replace('/', File.separatorChar);
303
bpath = ParseUtil.decode(bpath);
304
if (bpath.endsWith(File.separator)) {
305
bpath += "-";
306
}
307
perms.add(new FilePermission(bpath, SecurityConstants.FILE_READ_ACTION));
308
}
309
310
}
311
}
312
return perms;
313
}
314
315
/*
316
* Returns the contents of the specified URL as an array of bytes.
317
*/
318
private static byte[] getBytes(URL url) throws IOException {
319
URLConnection uc = url.openConnection();
320
if (uc instanceof java.net.HttpURLConnection) {
321
java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc;
322
int code = huc.getResponseCode();
323
if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) {
324
throw new IOException("open HTTP connection failed.");
325
}
326
}
327
int len = uc.getContentLength();
328
329
// Fixed #4507227: Slow performance to load
330
// class and resources. [stanleyh]
331
//
332
// Use buffered input stream [stanleyh]
333
InputStream in = new BufferedInputStream(uc.getInputStream());
334
335
byte[] b;
336
try {
337
b = IOUtils.readAllBytes(in);
338
if (len != -1 && b.length != len)
339
throw new EOFException("Expected:" + len + ", read:" + b.length);
340
} finally {
341
in.close();
342
}
343
return b;
344
}
345
346
// Object for synchronization around getResourceAsStream()
347
private Object syncResourceAsStream = new Object();
348
private Object syncResourceAsStreamFromJar = new Object();
349
350
// Flag to indicate getResourceAsStream() is in call
351
private boolean resourceAsStreamInCall = false;
352
private boolean resourceAsStreamFromJarInCall = false;
353
354
/**
355
* Returns an input stream for reading the specified resource.
356
*
357
* The search order is described in the documentation for {@link
358
* #getResource(String)}.<p>
359
*
360
* @param name the resource name
361
* @return an input stream for reading the resource, or <code>null</code>
362
* if the resource could not be found
363
* @since JDK1.1
364
*/
365
public InputStream getResourceAsStream(String name)
366
{
367
368
if (name == null) {
369
throw new NullPointerException("name");
370
}
371
372
try
373
{
374
InputStream is = null;
375
376
// Fixed #4507227: Slow performance to load
377
// class and resources. [stanleyh]
378
//
379
// The following is used to avoid calling
380
// AppletClassLoader.findResource() in
381
// super.getResourceAsStream(). Otherwise,
382
// unnecessary connection will be made.
383
//
384
synchronized(syncResourceAsStream)
385
{
386
resourceAsStreamInCall = true;
387
388
// Call super class
389
is = super.getResourceAsStream(name);
390
391
resourceAsStreamInCall = false;
392
}
393
394
// 4668479: Option to turn off codebase lookup in AppletClassLoader
395
// during resource requests. [stanley.ho]
396
if (codebaseLookup == true && is == null)
397
{
398
// If resource cannot be obtained,
399
// try to download it from codebase
400
URL url = new URL(base, ParseUtil.encodePath(name, false));
401
is = url.openStream();
402
}
403
404
return is;
405
}
406
catch (Exception e)
407
{
408
return null;
409
}
410
}
411
412
413
/**
414
* Returns an input stream for reading the specified resource from the
415
* the loaded jar files.
416
*
417
* The search order is described in the documentation for {@link
418
* #getResource(String)}.<p>
419
*
420
* @param name the resource name
421
* @return an input stream for reading the resource, or <code>null</code>
422
* if the resource could not be found
423
* @since JDK1.1
424
*/
425
public InputStream getResourceAsStreamFromJar(String name) {
426
427
if (name == null) {
428
throw new NullPointerException("name");
429
}
430
431
try {
432
InputStream is = null;
433
synchronized(syncResourceAsStreamFromJar) {
434
resourceAsStreamFromJarInCall = true;
435
// Call super class
436
is = super.getResourceAsStream(name);
437
resourceAsStreamFromJarInCall = false;
438
}
439
440
return is;
441
} catch (Exception e) {
442
return null;
443
}
444
}
445
446
447
/*
448
* Finds the applet resource with the specified name. First checks
449
* loaded JAR files then the applet code base for the resource.
450
*/
451
public URL findResource(String name) {
452
// check loaded JAR files
453
URL url = super.findResource(name);
454
455
// 6215746: Disable META-INF/* lookup from codebase in
456
// applet/plugin classloader. [stanley.ho]
457
if (name.startsWith("META-INF/"))
458
return url;
459
460
// 4668479: Option to turn off codebase lookup in AppletClassLoader
461
// during resource requests. [stanley.ho]
462
if (codebaseLookup == false)
463
return url;
464
465
if (url == null)
466
{
467
//#4805170, if it is a call from Applet.getImage()
468
//we should check for the image only in the archives
469
boolean insideGetResourceAsStreamFromJar = false;
470
synchronized(syncResourceAsStreamFromJar) {
471
insideGetResourceAsStreamFromJar = resourceAsStreamFromJarInCall;
472
}
473
474
if (insideGetResourceAsStreamFromJar) {
475
return null;
476
}
477
478
// Fixed #4507227: Slow performance to load
479
// class and resources. [stanleyh]
480
//
481
// Check if getResourceAsStream is called.
482
//
483
boolean insideGetResourceAsStream = false;
484
485
synchronized(syncResourceAsStream)
486
{
487
insideGetResourceAsStream = resourceAsStreamInCall;
488
}
489
490
// If getResourceAsStream is called, don't
491
// trigger the following code. Otherwise,
492
// unnecessary connection will be made.
493
//
494
if (insideGetResourceAsStream == false)
495
{
496
// otherwise, try the code base
497
try {
498
url = new URL(base, ParseUtil.encodePath(name, false));
499
// check if resource exists
500
if(!resourceExists(url))
501
url = null;
502
} catch (Exception e) {
503
// all exceptions, including security exceptions, are caught
504
url = null;
505
}
506
}
507
}
508
return url;
509
}
510
511
512
private boolean resourceExists(URL url) {
513
// Check if the resource exists.
514
// It almost works to just try to do an openConnection() but
515
// HttpURLConnection will return true on HTTP_BAD_REQUEST
516
// when the requested name ends in ".html", ".htm", and ".txt"
517
// and we want to be able to handle these
518
//
519
// Also, cannot just open a connection for things like FileURLConnection,
520
// because they succeed when connecting to a nonexistent file.
521
// So, in those cases we open and close an input stream.
522
boolean ok = true;
523
try {
524
URLConnection conn = url.openConnection();
525
if (conn instanceof java.net.HttpURLConnection) {
526
java.net.HttpURLConnection hconn =
527
(java.net.HttpURLConnection) conn;
528
529
// To reduce overhead, using http HEAD method instead of GET method
530
hconn.setRequestMethod("HEAD");
531
532
int code = hconn.getResponseCode();
533
if (code == java.net.HttpURLConnection.HTTP_OK) {
534
return true;
535
}
536
if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) {
537
return false;
538
}
539
} else {
540
/**
541
* Fix for #4182052 - stanleyh
542
*
543
* The same connection should be reused to avoid multiple
544
* HTTP connections
545
*/
546
547
// our best guess for the other cases
548
InputStream is = conn.getInputStream();
549
is.close();
550
}
551
} catch (Exception ex) {
552
ok = false;
553
}
554
return ok;
555
}
556
557
/*
558
* Returns an enumeration of all the applet resources with the specified
559
* name. First checks loaded JAR files then the applet code base for all
560
* available resources.
561
*/
562
public Enumeration findResources(String name) throws IOException {
563
564
final Enumeration e = super.findResources(name);
565
566
// 6215746: Disable META-INF/* lookup from codebase in
567
// applet/plugin classloader. [stanley.ho]
568
if (name.startsWith("META-INF/"))
569
return e;
570
571
// 4668479: Option to turn off codebase lookup in AppletClassLoader
572
// during resource requests. [stanley.ho]
573
if (codebaseLookup == false)
574
return e;
575
576
URL u = new URL(base, ParseUtil.encodePath(name, false));
577
if (!resourceExists(u)) {
578
u = null;
579
}
580
581
final URL url = u;
582
return new Enumeration() {
583
private boolean done;
584
public Object nextElement() {
585
if (!done) {
586
if (e.hasMoreElements()) {
587
return e.nextElement();
588
}
589
done = true;
590
if (url != null) {
591
return url;
592
}
593
}
594
throw new NoSuchElementException();
595
}
596
public boolean hasMoreElements() {
597
return !done && (e.hasMoreElements() || url != null);
598
}
599
};
600
}
601
602
/*
603
* Load and resolve the file specified by the applet tag CODE
604
* attribute. The argument can either be the relative path
605
* of the class file itself or just the name of the class.
606
*/
607
Class loadCode(String name) throws ClassNotFoundException {
608
// first convert any '/' or native file separator to .
609
name = name.replace('/', '.');
610
name = name.replace(File.separatorChar, '.');
611
612
// deal with URL rewriting
613
String cookie = null;
614
int index = name.indexOf(";");
615
if(index != -1) {
616
cookie = name.substring(index, name.length());
617
name = name.substring(0, index);
618
}
619
620
// save that name for later
621
String fullName = name;
622
// then strip off any suffixes
623
if (name.endsWith(".class") || name.endsWith(".java")) {
624
name = name.substring(0, name.lastIndexOf('.'));
625
}
626
try {
627
if(cookie != null)
628
name = (new StringBuffer(name)).append(cookie).toString();
629
return loadClass(name);
630
} catch (ClassNotFoundException e) {
631
}
632
// then if it didn't end with .java or .class, or in the
633
// really pathological case of a class named class or java
634
if(cookie != null)
635
fullName = (new StringBuffer(fullName)).append(cookie).toString();
636
637
return loadClass(fullName);
638
}
639
640
/*
641
* The threadgroup that the applets loaded by this classloader live
642
* in. In the sun.* implementation of applets, the security manager's
643
* (AppletSecurity) getThreadGroup returns the thread group of the
644
* first applet on the stack, which is the applet's thread group.
645
*/
646
private AppletThreadGroup threadGroup;
647
private AppContext appContext;
648
649
public ThreadGroup getThreadGroup() {
650
synchronized (threadGroupSynchronizer) {
651
if (threadGroup == null || threadGroup.isDestroyed()) {
652
AccessController.doPrivileged(new PrivilegedAction() {
653
public Object run() {
654
threadGroup = new AppletThreadGroup(base + "-threadGroup");
655
// threadGroup.setDaemon(true);
656
// threadGroup is now destroyed by AppContext.dispose()
657
658
// Create the new AppContext from within a Thread belonging
659
// to the newly created ThreadGroup, and wait for the
660
// creation to complete before returning from this method.
661
AppContextCreator creatorThread = new AppContextCreator(threadGroup);
662
663
// Since this thread will later be used to launch the
664
// applet's AWT-event dispatch thread and we want the applet
665
// code executing the AWT callbacks to use their own class
666
// loader rather than the system class loader, explicitly
667
// set the context class loader to the AppletClassLoader.
668
creatorThread.setContextClassLoader(AppletClassLoader.this);
669
670
creatorThread.start();
671
try {
672
synchronized(creatorThread.syncObject) {
673
while (!creatorThread.created) {
674
creatorThread.syncObject.wait();
675
}
676
}
677
} catch (InterruptedException e) { }
678
appContext = creatorThread.appContext;
679
return null;
680
}
681
});
682
}
683
return threadGroup;
684
}
685
}
686
687
/*
688
* Get the AppContext, if any, corresponding to this AppletClassLoader.
689
*/
690
public AppContext getAppContext() {
691
return appContext;
692
}
693
694
int usageCount = 0;
695
696
/**
697
* Grab this AppletClassLoader and its ThreadGroup/AppContext, so they
698
* won't be destroyed.
699
*/
700
public void grab() {
701
synchronized(grabReleaseSynchronizer) {
702
usageCount++;
703
}
704
getThreadGroup(); // Make sure ThreadGroup/AppContext exist
705
}
706
707
protected void setExceptionStatus()
708
{
709
exceptionStatus = true;
710
}
711
712
public boolean getExceptionStatus()
713
{
714
return exceptionStatus;
715
}
716
717
/**
718
* Release this AppletClassLoader and its ThreadGroup/AppContext.
719
* If nothing else has grabbed this AppletClassLoader, its ThreadGroup
720
* and AppContext will be destroyed.
721
*
722
* Because this method may destroy the AppletClassLoader's ThreadGroup,
723
* this method should NOT be called from within the AppletClassLoader's
724
* ThreadGroup.
725
*
726
* Changed modifier to protected in order to be able to overwrite this
727
* function in PluginClassLoader.java
728
*/
729
protected void release() {
730
731
AppContext tempAppContext = null;
732
733
synchronized(grabReleaseSynchronizer) {
734
if (usageCount > 1) {
735
--usageCount;
736
} else {
737
synchronized(threadGroupSynchronizer) {
738
tempAppContext = resetAppContext();
739
}
740
}
741
}
742
743
// Dispose appContext outside any sync block to
744
// prevent potential deadlock.
745
if (tempAppContext != null) {
746
try {
747
tempAppContext.dispose(); // nuke the world!
748
} catch (IllegalThreadStateException e) { }
749
}
750
}
751
752
/*
753
* reset classloader's AppContext and ThreadGroup
754
* This method is for subclass PluginClassLoader to
755
* reset superclass's AppContext and ThreadGroup but do
756
* not dispose the AppContext. PluginClassLoader does not
757
* use UsageCount to decide whether to dispose AppContext
758
*
759
* @return previous AppContext
760
*/
761
protected AppContext resetAppContext() {
762
AppContext tempAppContext = null;
763
764
synchronized(threadGroupSynchronizer) {
765
// Store app context in temp variable
766
tempAppContext = appContext;
767
usageCount = 0;
768
appContext = null;
769
threadGroup = null;
770
}
771
return tempAppContext;
772
}
773
774
775
// Hash map to store applet compatibility info
776
private HashMap jdk11AppletInfo = new HashMap();
777
private HashMap jdk12AppletInfo = new HashMap();
778
779
/**
780
* Set applet target level as JDK 1.1.
781
*
782
* @param clazz Applet class.
783
* @param bool true if JDK is targeted for JDK 1.1;
784
* false otherwise.
785
*/
786
void setJDK11Target(Class clazz, boolean bool)
787
{
788
jdk11AppletInfo.put(clazz.toString(), Boolean.valueOf(bool));
789
}
790
791
/**
792
* Set applet target level as JDK 1.2.
793
*
794
* @param clazz Applet class.
795
* @param bool true if JDK is targeted for JDK 1.2;
796
* false otherwise.
797
*/
798
void setJDK12Target(Class clazz, boolean bool)
799
{
800
jdk12AppletInfo.put(clazz.toString(), Boolean.valueOf(bool));
801
}
802
803
/**
804
* Determine if applet is targeted for JDK 1.1.
805
*
806
* @param applet Applet class.
807
* @return TRUE if applet is targeted for JDK 1.1;
808
* FALSE if applet is not;
809
* null if applet is unknown.
810
*/
811
Boolean isJDK11Target(Class clazz)
812
{
813
return (Boolean) jdk11AppletInfo.get(clazz.toString());
814
}
815
816
/**
817
* Determine if applet is targeted for JDK 1.2.
818
*
819
* @param applet Applet class.
820
* @return TRUE if applet is targeted for JDK 1.2;
821
* FALSE if applet is not;
822
* null if applet is unknown.
823
*/
824
Boolean isJDK12Target(Class clazz)
825
{
826
return (Boolean) jdk12AppletInfo.get(clazz.toString());
827
}
828
829
private static AppletMessageHandler mh =
830
new AppletMessageHandler("appletclassloader");
831
832
/*
833
* Prints a class loading error message.
834
*/
835
private static void printError(String name, Throwable e) {
836
String s = null;
837
if (e == null) {
838
s = mh.getMessage("filenotfound", name);
839
} else if (e instanceof IOException) {
840
s = mh.getMessage("fileioexception", name);
841
} else if (e instanceof ClassFormatError) {
842
s = mh.getMessage("fileformat", name);
843
} else if (e instanceof ThreadDeath) {
844
s = mh.getMessage("filedeath", name);
845
} else if (e instanceof Error) {
846
s = mh.getMessage("fileerror", e.toString(), name);
847
}
848
if (s != null) {
849
System.err.println(s);
850
}
851
}
852
}
853
854
/*
855
* The AppContextCreator class is used to create an AppContext from within
856
* a Thread belonging to the new AppContext's ThreadGroup. To wait for
857
* this operation to complete before continuing, wait for the notifyAll()
858
* operation on the syncObject to occur.
859
*/
860
class AppContextCreator extends Thread {
861
Object syncObject = new Object();
862
AppContext appContext = null;
863
volatile boolean created = false;
864
865
AppContextCreator(ThreadGroup group) {
866
super(group, "AppContextCreator");
867
}
868
869
public void run() {
870
appContext = SunToolkit.createNewAppContext();
871
created = true;
872
synchronized(syncObject) {
873
syncObject.notifyAll();
874
}
875
} // run()
876
877
} // class AppContextCreator
878
879