/* * Creates a thread to run the applet. This method is called * each time an applet is loaded and reloaded. */ synchronized void createAppletThread() { // Create a thread group for the applet, and start a new // thread to load the applet. String nm = "applet-" + getCode(); loader = getClassLoader(getCodeBase(), getClassLoaderCacheKey()); loader.grab(); // Keep this puppy around! // 4668479: Option to turn off codebase lookup in AppletClassLoader // during resource requests. [stanley.ho] String param = getParameter("codebase_lookup"); if (param != null && param.equals("false")) loader.setCodebaseLookup(false); else loader.setCodebaseLookup(true); ThreadGroup appletGroup = loader.getThreadGroup(); handler = new Thread(appletGroup, this, "thread " + nm, 0, false); // set the context class loader for this thread AccessController.doPrivileged( new PrivilegedAction<Object>() { @Override public Object run() { handler.setContextClassLoader(loader); return null; } }); handler.start(); }
/** * Gets most recent focus owner component associated with the given window. It does that without * calling Window.getMostRecentFocusOwner since it provides its own logic contradicting with * setDefautlFocus. Instead, it calls KeyboardFocusManager directly. */ private Component getMostRecentFocusOwnerForWindow(Window w) { Method meth = AccessController.doPrivileged( new PrivilegedAction<Method>() { @Override public Method run() { Method meth = null; try { meth = KeyboardFocusManager.class.getDeclaredMethod( "getMostRecentFocusOwner", new Class<?>[] {Window.class}); meth.setAccessible(true); } catch (Exception e) { // Must never happen e.printStackTrace(); } return meth; } }); if (meth != null) { // Meth refers static method try { return (Component) meth.invoke(null, new Object[] {w}); } catch (Exception e) { // Must never happen e.printStackTrace(); } } // Will get here if exception was thrown or meth is null return w.getMostRecentFocusOwner(); }
/** Get a class loader. Create in a restricted context */ synchronized AppletClassLoader getClassLoader(final URL codebase, final String key) { AppletClassLoader c = classloaders.get(key); if (c == null) { AccessControlContext acc = getAccessControlContext(codebase); c = AccessController.doPrivileged( new PrivilegedAction<AppletClassLoader>() { @Override public AppletClassLoader run() { AppletClassLoader ac = createClassLoader(codebase); /* Should the creation of the classloader be * within the class synchronized block? Since * this class is used by the plugin, take care * to avoid deadlocks, or specialize * AppletPanel within the plugin. It may take * an arbitrary amount of time to create a * class loader (involving getting Jar files * etc.) and may block unrelated applets from * finishing createAppletThread (due to the * class synchronization). If * createAppletThread does not finish quickly, * the applet cannot process other messages, * particularly messages such as destroy * (which timeout when called from the browser). */ synchronized (getClass()) { AppletClassLoader res = classloaders.get(key); if (res == null) { classloaders.put(key, ac); return ac; } else { return res; } } } }, acc); } return c; }
/** * get the context for the AppletClassLoader we are creating. the context is granted permission to * create the class loader, connnect to the codebase, and whatever else the policy grants to all * codebases. */ private AccessControlContext getAccessControlContext(final URL codebase) { PermissionCollection perms = AccessController.doPrivileged( new PrivilegedAction<PermissionCollection>() { @Override public PermissionCollection run() { Policy p = java.security.Policy.getPolicy(); if (p != null) { return p.getPermissions( new CodeSource(null, (java.security.cert.Certificate[]) null)); } else { return null; } } }); if (perms == null) perms = new Permissions(); // XXX: this is needed to be able to create the classloader itself! perms.add(SecurityConstants.CREATE_CLASSLOADER_PERMISSION); Permission p; java.net.URLConnection urlConnection = null; try { urlConnection = codebase.openConnection(); p = urlConnection.getPermission(); } catch (java.io.IOException ioe) { p = null; } if (p != null) perms.add(p); if (p instanceof FilePermission) { String path = p.getName(); int endIndex = path.lastIndexOf(File.separatorChar); if (endIndex != -1) { path = path.substring(0, endIndex + 1); if (path.endsWith(File.separator)) { path += "-"; } perms.add(new FilePermission(path, SecurityConstants.FILE_READ_ACTION)); } } else { URL locUrl = codebase; if (urlConnection instanceof JarURLConnection) { locUrl = ((JarURLConnection) urlConnection).getJarFileURL(); } String host = locUrl.getHost(); if (host != null && (host.length() > 0)) perms.add(new SocketPermission(host, SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION)); } ProtectionDomain domain = new ProtectionDomain( new CodeSource(codebase, (java.security.cert.Certificate[]) null), perms); AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] {domain}); return acc; }
/** Determine JDK level of an applet. */ private void findAppletJDKLevel(Applet applet) { // To determine the JDK level of an applet, the // most reliable way is to check the major version // of the applet class file. // synchronized on applet class object, so calling from // different instances of the same applet will be // serialized. Class<?> appletClass = applet.getClass(); synchronized (appletClass) { // Determine if the JDK level of an applet has been // checked before. Boolean jdk11Target = loader.isJDK11Target(appletClass); Boolean jdk12Target = loader.isJDK12Target(appletClass); // if applet JDK level has been checked before, retrieve // value and return. if (jdk11Target != null || jdk12Target != null) { jdk11Applet = (jdk11Target == null) ? false : jdk11Target.booleanValue(); jdk12Applet = (jdk12Target == null) ? false : jdk12Target.booleanValue(); return; } String name = appletClass.getName(); // first convert any '.' to '/' name = name.replace('.', '/'); // append .class final String resourceName = name + ".class"; byte[] classHeader = new byte[8]; try (InputStream is = AccessController.doPrivileged( (PrivilegedAction<InputStream>) () -> loader.getResourceAsStream(resourceName))) { // Read the first 8 bytes of the class file int byteRead = is.read(classHeader, 0, 8); // return if the header is not read in entirely // for some reasons. if (byteRead != 8) return; } catch (IOException e) { return; } // Check major version in class file header int major_version = readShort(classHeader, 6); // Major version in class file is as follows: // 45 - JDK 1.1 // 46 - JDK 1.2 // 47 - JDK 1.3 // 48 - JDK 1.4 // 49 - JDK 1.5 if (major_version < 46) jdk11Applet = true; else if (major_version == 46) jdk12Applet = true; // Store applet JDK level in AppContext for later lookup, // e.g. page switch. loader.setJDK11Target(appletClass, jdk11Applet); loader.setJDK12Target(appletClass, jdk12Applet); } }