src/share/classes/sun/applet/AppletPanel.java

Print this page
rev 10175 : 8042872: Fix raw and unchecked warnings in sun.applet
Reviewed-by:


 162         // Create a thread group for the applet, and start a new
 163         // thread to load the applet.
 164         String nm = "applet-" + getCode();
 165         loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey());
 166         loader.grab(); // Keep this puppy around!
 167 
 168         // 4668479: Option to turn off codebase lookup in AppletClassLoader
 169         // during resource requests. [stanley.ho]
 170         String param = getParameter("codebase_lookup");
 171 
 172         if (param != null && param.equals("false"))
 173             loader.setCodebaseLookup(false);
 174         else
 175             loader.setCodebaseLookup(true);
 176 
 177 
 178         ThreadGroup appletGroup = loader.getThreadGroup();
 179 
 180         handler = new Thread(appletGroup, this, "thread " + nm);
 181         // set the context class loader for this thread
 182         AccessController.doPrivileged(new PrivilegedAction() {
 183                 @Override
 184                 public Object run() {
 185                     handler.setContextClassLoader(loader);
 186                     return null;
 187                 }
 188             });
 189         handler.start();
 190     }
 191 
 192     void joinAppletThread() throws InterruptedException {
 193         if (handler != null) {
 194             handler.join();
 195             handler = null;
 196         }
 197     }
 198 
 199     void release() {
 200         if (loader != null) {
 201             loader.release();
 202             loader = null;


 236     @Override
 237     public Dimension minimumSize() {
 238         return new Dimension(defaultAppletSize.width,
 239                              defaultAppletSize.height);
 240     }
 241 
 242     /**
 243      * Preferred size
 244      */
 245     @Override
 246     public Dimension preferredSize() {
 247         return new Dimension(currentAppletSize.width,
 248                              currentAppletSize.height);
 249     }
 250 
 251     private AppletListener listeners;
 252 
 253     /**
 254      * AppletEvent Queue
 255      */
 256     private Queue queue = null;
 257 
 258 
 259     synchronized public void addAppletListener(AppletListener l) {
 260         listeners = AppletEventMulticaster.add(listeners, l);
 261     }
 262 
 263     synchronized public void removeAppletListener(AppletListener l) {
 264         listeners = AppletEventMulticaster.remove(listeners, l);
 265     }
 266 
 267     /**
 268      * Dispatch event to the listeners..
 269      */
 270     public void dispatchAppletEvent(int id, Object argument) {
 271         //System.out.println("SEND= " + id);
 272         if (listeners != null) {
 273             AppletEvent evt = new AppletEvent(this, id, argument);
 274             listeners.appletStateChanged(evt);
 275         }
 276     }
 277 
 278     /**
 279      * Send an event. Queue it for execution by the handler thread.
 280      */
 281     public void sendEvent(int id) {
 282         synchronized(this) {
 283             if (queue == null) {
 284                 //System.out.println("SEND0= " + id);
 285                 queue = new Queue();
 286             }
 287             Integer eventId = Integer.valueOf(id);
 288             queue.enqueue(eventId);
 289             notifyAll();
 290         }
 291         if (id == APPLET_QUIT) {
 292             try {
 293                 joinAppletThread(); // Let the applet event handler exit
 294             } catch (InterruptedException e) {
 295             }
 296 
 297             // AppletClassLoader.release() must be called by a Thread
 298             // not within the applet's ThreadGroup
 299             if (loader == null)
 300                 loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey());
 301             release();
 302         }
 303     }
 304 
 305     /**
 306      * Get an event from the queue.
 307      */
 308     synchronized AppletEvent getNextEvent() throws InterruptedException {
 309         while (queue == null || queue.isEmpty()) {
 310             wait();
 311         }
 312         Integer eventId = (Integer)queue.dequeue();
 313         return new AppletEvent(this, eventId.intValue(), null);
 314     }
 315 
 316     boolean emptyEventQueue() {
 317         if ((queue == null) || (queue.isEmpty()))
 318             return true;
 319         else
 320             return false;
 321     }
 322 
 323     /**
 324      * This kludge is specific to get over AccessControlException thrown during
 325      * Applet.stop() or destroy() when static thread is suspended.  Set a flag
 326      * in AppletClassLoader to indicate that an
 327      * AccessControlException for RuntimePermission "modifyThread" or
 328      * "modifyThreadGroup" had occurred.
 329      */
 330      private void setExceptionStatus(AccessControlException e) {
 331      Permission p = e.getPermission();
 332      if (p instanceof RuntimePermission) {


 614                 status = APPLET_ERROR;
 615                 if (e.getMessage() != null) {
 616                     showAppletStatus("error2", e.getClass().getName(),
 617                                      e.getMessage());
 618                 } else {
 619                     showAppletStatus("error", e.getClass().getName());
 620                 }
 621                 showAppletException(e);
 622             }
 623             clearLoadAbortRequest();
 624         }
 625     }
 626 
 627     /**
 628      * Gets most recent focus owner component associated with the given window.
 629      * It does that without calling Window.getMostRecentFocusOwner since it
 630      * provides its own logic contradicting with setDefautlFocus. Instead, it
 631      * calls KeyboardFocusManager directly.
 632      */
 633     private Component getMostRecentFocusOwnerForWindow(Window w) {
 634         Method meth = (Method)AccessController.doPrivileged(new PrivilegedAction() {

 635                 @Override
 636                 public Object run() {
 637                     Method meth = null;
 638                     try {
 639                         meth = KeyboardFocusManager.class.getDeclaredMethod(
 640                                 "getMostRecentFocusOwner",
 641                                 new Class[]{Window.class});
 642                         meth.setAccessible(true);
 643                     } catch (Exception e) {
 644                         // Must never happen
 645                         e.printStackTrace();
 646                     }
 647                     return meth;
 648                 }
 649             });
 650         if (meth != null) {
 651             // Meth refers static method
 652             try {
 653                 return (Component)meth.invoke(null, new Object[] {w});
 654             } catch (Exception e) {
 655                 // Must never happen
 656                 e.printStackTrace();
 657             }
 658         }
 659         // Will get here if exception was thrown or meth is null
 660         return w.getMostRecentFocusOwner();
 661     }


 971         t.printStackTrace();
 972         repaint();
 973     }
 974 
 975     /**
 976      * Get caching key for classloader cache
 977      */
 978     public String getClassLoaderCacheKey()
 979     {
 980         /**
 981          * Fixed #4501142: Classloader sharing policy doesn't
 982          * take "archive" into account. This will be overridden
 983          * by Java Plug-in.                     [stanleyh]
 984          */
 985         return getCodeBase().toString();
 986     }
 987 
 988     /**
 989      * The class loaders
 990      */
 991     private static HashMap classloaders = new HashMap();
 992 
 993     /**
 994      * Flush a class loader.
 995      */
 996     public static synchronized void flushClassLoader(String key) {
 997         classloaders.remove(key);
 998     }
 999 
1000     /**
1001      * Flush all class loaders.
1002      */
1003     public static synchronized void flushClassLoaders() {
1004         classloaders = new HashMap();
1005     }
1006 
1007     /**
1008      * This method actually creates an AppletClassLoader.
1009      *
1010      * It can be override by subclasses (such as the Plug-in)
1011      * to provide different classloaders.
1012      */
1013     protected AppletClassLoader createClassLoader(final URL codebase) {
1014         return new AppletClassLoader(codebase);
1015     }
1016 
1017     /**
1018      * Get a class loader. Create in a restricted context
1019      */
1020     synchronized AppletClassLoader getClassLoader(final URL codebase, final String key) {
1021         AppletClassLoader c = (AppletClassLoader)classloaders.get(key);
1022         if (c == null) {
1023             AccessControlContext acc =
1024                 getAccessControlContext(codebase);
1025             c = (AppletClassLoader)
1026                 AccessController.doPrivileged(new PrivilegedAction() {
1027                         @Override
1028                         public Object run() {
1029                             AppletClassLoader ac = createClassLoader(codebase);
1030                             /* Should the creation of the classloader be
1031                              * within the class synchronized block?  Since
1032                              * this class is used by the plugin, take care
1033                              * to avoid deadlocks, or specialize
1034                              * AppletPanel within the plugin.  It may take
1035                              * an arbitrary amount of time to create a
1036                              * class loader (involving getting Jar files
1037                              * etc.) and may block unrelated applets from
1038                              * finishing createAppletThread (due to the
1039                              * class synchronization). If
1040                              * createAppletThread does not finish quickly,
1041                              * the applet cannot process other messages,
1042                              * particularly messages such as destroy
1043                              * (which timeout when called from the browser).
1044                              */
1045                             synchronized (getClass()) {
1046                                 AppletClassLoader res =
1047                                     (AppletClassLoader)classloaders.get(key);
1048                                 if (res == null) {
1049                                     classloaders.put(key, ac);
1050                                     return ac;
1051                                 } else {
1052                                     return res;
1053                                 }
1054                             }
1055                         }
1056                     },acc);
1057         }
1058         return c;
1059     }
1060 
1061     /**
1062      * get the context for the AppletClassLoader we are creating.
1063      * the context is granted permission to create the class loader,
1064      * connnect to the codebase, and whatever else the policy grants
1065      * to all codebases.
1066      */
1067     private AccessControlContext getAccessControlContext(final URL codebase) {
1068 
1069         PermissionCollection perms = (PermissionCollection)
1070             AccessController.doPrivileged(new PrivilegedAction() {
1071                     @Override
1072                     public Object run() {
1073                         Policy p = java.security.Policy.getPolicy();
1074                         if (p != null) {
1075                             return p.getPermissions(new CodeSource(null,
1076                                                                    (java.security.cert.Certificate[]) null));
1077                         } else {
1078                             return null;
1079                         }
1080                     }
1081                 });
1082 
1083         if (perms == null)
1084             perms = new Permissions();
1085 
1086         //XXX: this is needed to be able to create the classloader itself!
1087 
1088         perms.add(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
1089 
1090         Permission p;
1091         java.net.URLConnection urlConnection = null;
1092         try {


1155         // is created in main thread group. Thus, when certain
1156         // AWT/Swing events are generated, the events will be
1157         // dispatched through the wrong event dispatch thread.
1158         //
1159         // To fix this, we rearrange the AppContext with the frame,
1160         // so the proper event queue will be looked up.
1161         //
1162         // Swing also maintains a Frame list for the AppContext,
1163         // so we will have to rearrange it as well.
1164 
1165         // Check if frame's AppContext has already been set properly
1166         AppContext oldAppContext = SunToolkit.targetToAppContext(frame);
1167 
1168         if (oldAppContext == newAppContext)
1169             return;
1170 
1171         // Synchronization on Window.class is needed for locking the
1172         // critical section of the window list in AppContext.
1173         synchronized (Window.class)
1174         {
1175             WeakReference weakRef = null;
1176             // Remove frame from the Window list in wrong AppContext
1177             {
1178                 // Lookup current frame's AppContext
1179                 Vector<WeakReference<Window>> windowList = (Vector<WeakReference<Window>>)oldAppContext.get(Window.class);


1180                 if (windowList != null) {
1181                     for (WeakReference ref : windowList) {
1182                         if (ref.get() == frame) {
1183                             weakRef = ref;
1184                             break;
1185                         }
1186                     }
1187                     // Remove frame from wrong AppContext
1188                     if (weakRef != null)
1189                         windowList.remove(weakRef);
1190                 }
1191             }
1192 
1193             // Put the frame into the applet's AppContext map
1194             SunToolkit.insertTargetMapping(frame, newAppContext);
1195 
1196             // Insert frame into the Window list in the applet's AppContext map
1197             {
1198                 Vector<WeakReference<Window>> windowList = (Vector)newAppContext.get(Window.class);


1199                 if (windowList == null) {
1200                     windowList = new Vector<WeakReference<Window>>();
1201                     newAppContext.put(Window.class, windowList);
1202                 }
1203                 // use the same weakRef here as it is used elsewhere
1204                 windowList.add(weakRef);
1205             }
1206         }
1207     }
1208 
1209     // Flag to indicate if applet is targeted for JDK 1.1.
1210     private boolean jdk11Applet = false;
1211 
1212     // Flag to indicate if applet is targeted for JDK 1.2.
1213     private boolean jdk12Applet = false;
1214 
1215     /**
1216      * Determine JDK level of an applet.
1217      */
1218     private void findAppletJDKLevel(Applet applet)
1219     {
1220         // To determine the JDK level of an applet, the
1221         // most reliable way is to check the major version
1222         // of the applet class file.
1223 
1224         // synchronized on applet class object, so calling from
1225         // different instances of the same applet will be
1226         // serialized.
1227         Class appletClass = applet.getClass();
1228 
1229         synchronized(appletClass)  {
1230             // Determine if the JDK level of an applet has been
1231             // checked before.
1232             Boolean jdk11Target = loader.isJDK11Target(appletClass);
1233             Boolean jdk12Target = loader.isJDK12Target(appletClass);
1234 
1235             // if applet JDK level has been checked before, retrieve
1236             // value and return.
1237             if (jdk11Target != null || jdk12Target != null) {
1238                 jdk11Applet = (jdk11Target == null) ? false : jdk11Target.booleanValue();
1239                 jdk12Applet = (jdk12Target == null) ? false : jdk12Target.booleanValue();
1240                 return;
1241             }
1242 
1243             String name = appletClass.getName();
1244 
1245             // first convert any '.' to '/'
1246             name = name.replace('.', '/');
1247 




 162         // Create a thread group for the applet, and start a new
 163         // thread to load the applet.
 164         String nm = "applet-" + getCode();
 165         loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey());
 166         loader.grab(); // Keep this puppy around!
 167 
 168         // 4668479: Option to turn off codebase lookup in AppletClassLoader
 169         // during resource requests. [stanley.ho]
 170         String param = getParameter("codebase_lookup");
 171 
 172         if (param != null && param.equals("false"))
 173             loader.setCodebaseLookup(false);
 174         else
 175             loader.setCodebaseLookup(true);
 176 
 177 
 178         ThreadGroup appletGroup = loader.getThreadGroup();
 179 
 180         handler = new Thread(appletGroup, this, "thread " + nm);
 181         // set the context class loader for this thread
 182         AccessController.doPrivileged(new PrivilegedAction<Object>() {
 183                 @Override
 184                 public Object run() {
 185                     handler.setContextClassLoader(loader);
 186                     return null;
 187                 }
 188             });
 189         handler.start();
 190     }
 191 
 192     void joinAppletThread() throws InterruptedException {
 193         if (handler != null) {
 194             handler.join();
 195             handler = null;
 196         }
 197     }
 198 
 199     void release() {
 200         if (loader != null) {
 201             loader.release();
 202             loader = null;


 236     @Override
 237     public Dimension minimumSize() {
 238         return new Dimension(defaultAppletSize.width,
 239                              defaultAppletSize.height);
 240     }
 241 
 242     /**
 243      * Preferred size
 244      */
 245     @Override
 246     public Dimension preferredSize() {
 247         return new Dimension(currentAppletSize.width,
 248                              currentAppletSize.height);
 249     }
 250 
 251     private AppletListener listeners;
 252 
 253     /**
 254      * AppletEvent Queue
 255      */
 256     private Queue<Integer> queue = null;
 257 
 258 
 259     synchronized public void addAppletListener(AppletListener l) {
 260         listeners = AppletEventMulticaster.add(listeners, l);
 261     }
 262 
 263     synchronized public void removeAppletListener(AppletListener l) {
 264         listeners = AppletEventMulticaster.remove(listeners, l);
 265     }
 266 
 267     /**
 268      * Dispatch event to the listeners..
 269      */
 270     public void dispatchAppletEvent(int id, Object argument) {
 271         //System.out.println("SEND= " + id);
 272         if (listeners != null) {
 273             AppletEvent evt = new AppletEvent(this, id, argument);
 274             listeners.appletStateChanged(evt);
 275         }
 276     }
 277 
 278     /**
 279      * Send an event. Queue it for execution by the handler thread.
 280      */
 281     public void sendEvent(int id) {
 282         synchronized(this) {
 283             if (queue == null) {
 284                 //System.out.println("SEND0= " + id);
 285                 queue = new Queue<>();
 286             }
 287             Integer eventId = Integer.valueOf(id);
 288             queue.enqueue(eventId);
 289             notifyAll();
 290         }
 291         if (id == APPLET_QUIT) {
 292             try {
 293                 joinAppletThread(); // Let the applet event handler exit
 294             } catch (InterruptedException e) {
 295             }
 296 
 297             // AppletClassLoader.release() must be called by a Thread
 298             // not within the applet's ThreadGroup
 299             if (loader == null)
 300                 loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey());
 301             release();
 302         }
 303     }
 304 
 305     /**
 306      * Get an event from the queue.
 307      */
 308     synchronized AppletEvent getNextEvent() throws InterruptedException {
 309         while (queue == null || queue.isEmpty()) {
 310             wait();
 311         }
 312         Integer eventId = queue.dequeue();
 313         return new AppletEvent(this, eventId.intValue(), null);
 314     }
 315 
 316     boolean emptyEventQueue() {
 317         if ((queue == null) || (queue.isEmpty()))
 318             return true;
 319         else
 320             return false;
 321     }
 322 
 323     /**
 324      * This kludge is specific to get over AccessControlException thrown during
 325      * Applet.stop() or destroy() when static thread is suspended.  Set a flag
 326      * in AppletClassLoader to indicate that an
 327      * AccessControlException for RuntimePermission "modifyThread" or
 328      * "modifyThreadGroup" had occurred.
 329      */
 330      private void setExceptionStatus(AccessControlException e) {
 331      Permission p = e.getPermission();
 332      if (p instanceof RuntimePermission) {


 614                 status = APPLET_ERROR;
 615                 if (e.getMessage() != null) {
 616                     showAppletStatus("error2", e.getClass().getName(),
 617                                      e.getMessage());
 618                 } else {
 619                     showAppletStatus("error", e.getClass().getName());
 620                 }
 621                 showAppletException(e);
 622             }
 623             clearLoadAbortRequest();
 624         }
 625     }
 626 
 627     /**
 628      * Gets most recent focus owner component associated with the given window.
 629      * It does that without calling Window.getMostRecentFocusOwner since it
 630      * provides its own logic contradicting with setDefautlFocus. Instead, it
 631      * calls KeyboardFocusManager directly.
 632      */
 633     private Component getMostRecentFocusOwnerForWindow(Window w) {
 634         Method meth = AccessController.doPrivileged(
 635             new PrivilegedAction<Method>() {
 636                 @Override
 637                 public Method run() {
 638                     Method meth = null;
 639                     try {
 640                         meth = KeyboardFocusManager.class.getDeclaredMethod(
 641                                 "getMostRecentFocusOwner",
 642                                 new Class<?>[]{Window.class});
 643                         meth.setAccessible(true);
 644                     } catch (Exception e) {
 645                         // Must never happen
 646                         e.printStackTrace();
 647                     }
 648                     return meth;
 649                 }
 650             });
 651         if (meth != null) {
 652             // Meth refers static method
 653             try {
 654                 return (Component)meth.invoke(null, new Object[] {w});
 655             } catch (Exception e) {
 656                 // Must never happen
 657                 e.printStackTrace();
 658             }
 659         }
 660         // Will get here if exception was thrown or meth is null
 661         return w.getMostRecentFocusOwner();
 662     }


 972         t.printStackTrace();
 973         repaint();
 974     }
 975 
 976     /**
 977      * Get caching key for classloader cache
 978      */
 979     public String getClassLoaderCacheKey()
 980     {
 981         /**
 982          * Fixed #4501142: Classloader sharing policy doesn't
 983          * take "archive" into account. This will be overridden
 984          * by Java Plug-in.                     [stanleyh]
 985          */
 986         return getCodeBase().toString();
 987     }
 988 
 989     /**
 990      * The class loaders
 991      */
 992     private static HashMap<String, AppletClassLoader> classloaders = new HashMap<>();
 993 
 994     /**
 995      * Flush a class loader.
 996      */
 997     public static synchronized void flushClassLoader(String key) {
 998         classloaders.remove(key);
 999     }
1000 
1001     /**
1002      * Flush all class loaders.
1003      */
1004     public static synchronized void flushClassLoaders() {
1005         classloaders = new HashMap<>();
1006     }
1007 
1008     /**
1009      * This method actually creates an AppletClassLoader.
1010      *
1011      * It can be override by subclasses (such as the Plug-in)
1012      * to provide different classloaders.
1013      */
1014     protected AppletClassLoader createClassLoader(final URL codebase) {
1015         return new AppletClassLoader(codebase);
1016     }
1017 
1018     /**
1019      * Get a class loader. Create in a restricted context
1020      */
1021     synchronized AppletClassLoader getClassLoader(final URL codebase, final String key) {
1022         AppletClassLoader c = classloaders.get(key);
1023         if (c == null) {
1024             AccessControlContext acc =
1025                 getAccessControlContext(codebase);
1026             c = AccessController.doPrivileged(
1027                     new PrivilegedAction<AppletClassLoader>() {
1028                         @Override
1029                         public AppletClassLoader run() {
1030                             AppletClassLoader ac = createClassLoader(codebase);
1031                             /* Should the creation of the classloader be
1032                              * within the class synchronized block?  Since
1033                              * this class is used by the plugin, take care
1034                              * to avoid deadlocks, or specialize
1035                              * AppletPanel within the plugin.  It may take
1036                              * an arbitrary amount of time to create a
1037                              * class loader (involving getting Jar files
1038                              * etc.) and may block unrelated applets from
1039                              * finishing createAppletThread (due to the
1040                              * class synchronization). If
1041                              * createAppletThread does not finish quickly,
1042                              * the applet cannot process other messages,
1043                              * particularly messages such as destroy
1044                              * (which timeout when called from the browser).
1045                              */
1046                             synchronized (getClass()) {
1047                                 AppletClassLoader res = classloaders.get(key);

1048                                 if (res == null) {
1049                                     classloaders.put(key, ac);
1050                                     return ac;
1051                                 } else {
1052                                     return res;
1053                                 }
1054                             }
1055                         }
1056                     },acc);
1057         }
1058         return c;
1059     }
1060 
1061     /**
1062      * get the context for the AppletClassLoader we are creating.
1063      * the context is granted permission to create the class loader,
1064      * connnect to the codebase, and whatever else the policy grants
1065      * to all codebases.
1066      */
1067     private AccessControlContext getAccessControlContext(final URL codebase) {
1068 
1069         PermissionCollection perms = AccessController.doPrivileged(
1070                 new PrivilegedAction<PermissionCollection>() {
1071                     @Override
1072                     public PermissionCollection run() {
1073                         Policy p = java.security.Policy.getPolicy();
1074                         if (p != null) {
1075                             return p.getPermissions(new CodeSource(null,
1076                                                                    (java.security.cert.Certificate[]) null));
1077                         } else {
1078                             return null;
1079                         }
1080                     }
1081                 });
1082 
1083         if (perms == null)
1084             perms = new Permissions();
1085 
1086         //XXX: this is needed to be able to create the classloader itself!
1087 
1088         perms.add(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
1089 
1090         Permission p;
1091         java.net.URLConnection urlConnection = null;
1092         try {


1155         // is created in main thread group. Thus, when certain
1156         // AWT/Swing events are generated, the events will be
1157         // dispatched through the wrong event dispatch thread.
1158         //
1159         // To fix this, we rearrange the AppContext with the frame,
1160         // so the proper event queue will be looked up.
1161         //
1162         // Swing also maintains a Frame list for the AppContext,
1163         // so we will have to rearrange it as well.
1164 
1165         // Check if frame's AppContext has already been set properly
1166         AppContext oldAppContext = SunToolkit.targetToAppContext(frame);
1167 
1168         if (oldAppContext == newAppContext)
1169             return;
1170 
1171         // Synchronization on Window.class is needed for locking the
1172         // critical section of the window list in AppContext.
1173         synchronized (Window.class)
1174         {
1175             WeakReference<Window> weakRef = null;
1176             // Remove frame from the Window list in wrong AppContext
1177             {
1178                 // Lookup current frame's AppContext
1179                 @SuppressWarnings("unchecked")
1180                 Vector<WeakReference<Window>> windowList =
1181                     (Vector<WeakReference<Window>>)oldAppContext.get(Window.class);
1182                 if (windowList != null) {
1183                     for (WeakReference<Window> ref : windowList) {
1184                         if (ref.get() == frame) {
1185                             weakRef = ref;
1186                             break;
1187                         }
1188                     }
1189                     // Remove frame from wrong AppContext
1190                     if (weakRef != null)
1191                         windowList.remove(weakRef);
1192                 }
1193             }
1194 
1195             // Put the frame into the applet's AppContext map
1196             SunToolkit.insertTargetMapping(frame, newAppContext);
1197 
1198             // Insert frame into the Window list in the applet's AppContext map
1199             {
1200                 @SuppressWarnings("unchecked")
1201                 Vector<WeakReference<Window>> windowList =
1202                     (Vector<WeakReference<Window>>)newAppContext.get(Window.class);
1203                 if (windowList == null) {
1204                     windowList = new Vector<WeakReference<Window>>();
1205                     newAppContext.put(Window.class, windowList);
1206                 }
1207                 // use the same weakRef here as it is used elsewhere
1208                 windowList.add(weakRef);
1209             }
1210         }
1211     }
1212 
1213     // Flag to indicate if applet is targeted for JDK 1.1.
1214     private boolean jdk11Applet = false;
1215 
1216     // Flag to indicate if applet is targeted for JDK 1.2.
1217     private boolean jdk12Applet = false;
1218 
1219     /**
1220      * Determine JDK level of an applet.
1221      */
1222     private void findAppletJDKLevel(Applet applet)
1223     {
1224         // To determine the JDK level of an applet, the
1225         // most reliable way is to check the major version
1226         // of the applet class file.
1227 
1228         // synchronized on applet class object, so calling from
1229         // different instances of the same applet will be
1230         // serialized.
1231         Class<?> appletClass = applet.getClass();
1232 
1233         synchronized(appletClass)  {
1234             // Determine if the JDK level of an applet has been
1235             // checked before.
1236             Boolean jdk11Target = loader.isJDK11Target(appletClass);
1237             Boolean jdk12Target = loader.isJDK12Target(appletClass);
1238 
1239             // if applet JDK level has been checked before, retrieve
1240             // value and return.
1241             if (jdk11Target != null || jdk12Target != null) {
1242                 jdk11Applet = (jdk11Target == null) ? false : jdk11Target.booleanValue();
1243                 jdk12Applet = (jdk12Target == null) ? false : jdk12Target.booleanValue();
1244                 return;
1245             }
1246 
1247             String name = appletClass.getName();
1248 
1249             // first convert any '.' to '/'
1250             name = name.replace('.', '/');
1251