8205537: Drop of sun.applet package
Reviewed-by: prr
This commit is contained in:
parent
222c1eb393
commit
cd38b8562f
@ -1,854 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.applet;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.URLConnection;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permission;
|
||||
import java.security.PermissionCollection;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.net.www.ParseUtil;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
/**
|
||||
* This class defines the class loader for loading applet classes and
|
||||
* resources. It extends URLClassLoader to search the applet code base
|
||||
* for the class or resource after checking any loaded JAR files.
|
||||
*/
|
||||
public class AppletClassLoader extends URLClassLoader {
|
||||
private URL base; /* applet code base URL */
|
||||
private CodeSource codesource; /* codesource for the base URL */
|
||||
private AccessControlContext acc;
|
||||
private boolean exceptionStatus = false;
|
||||
|
||||
private final Object threadGroupSynchronizer = new Object();
|
||||
private final Object grabReleaseSynchronizer = new Object();
|
||||
|
||||
private boolean codebaseLookup = true;
|
||||
private volatile boolean allowRecursiveDirectoryRead = true;
|
||||
|
||||
/*
|
||||
* Creates a new AppletClassLoader for the specified base URL.
|
||||
*/
|
||||
protected AppletClassLoader(URL base) {
|
||||
super(new URL[0]);
|
||||
this.base = base;
|
||||
this.codesource =
|
||||
new CodeSource(base, (java.security.cert.Certificate[]) null);
|
||||
acc = AccessController.getContext();
|
||||
}
|
||||
|
||||
public void disableRecursiveDirectoryRead() {
|
||||
allowRecursiveDirectoryRead = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the codebase lookup flag.
|
||||
*/
|
||||
void setCodebaseLookup(boolean codebaseLookup) {
|
||||
this.codebaseLookup = codebaseLookup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the applet code base URL.
|
||||
*/
|
||||
URL getBaseURL() {
|
||||
return base;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the URLs used for loading classes and resources.
|
||||
*/
|
||||
public URL[] getURLs() {
|
||||
URL[] jars = super.getURLs();
|
||||
URL[] urls = new URL[jars.length + 1];
|
||||
System.arraycopy(jars, 0, urls, 0, jars.length);
|
||||
urls[urls.length - 1] = base;
|
||||
return urls;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the specified JAR file to the search path of loaded JAR files.
|
||||
* Changed modifier to protected in order to be able to overwrite addJar()
|
||||
* in PluginClassLoader.java
|
||||
*/
|
||||
protected void addJar(String name) throws IOException {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(base, name);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new IllegalArgumentException("name");
|
||||
}
|
||||
addURL(url);
|
||||
// DEBUG
|
||||
//URL[] urls = getURLs();
|
||||
//for (int i = 0; i < urls.length; i++) {
|
||||
// System.out.println("url[" + i + "] = " + urls[i]);
|
||||
//}
|
||||
}
|
||||
|
||||
/*
|
||||
* Override loadClass so that class loading errors can be caught in
|
||||
* order to print better error messages.
|
||||
*/
|
||||
public synchronized Class<?> loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
// First check if we have permission to access the package. This
|
||||
// should go away once we've added support for exported packages.
|
||||
int i = name.lastIndexOf('.');
|
||||
if (i != -1) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
sm.checkPackageAccess(name.substring(0, i));
|
||||
}
|
||||
try {
|
||||
return super.loadClass(name, resolve);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the applet class with the specified name. First searches
|
||||
* loaded JAR files then the applet code base for the class.
|
||||
*/
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
|
||||
int index = name.indexOf(';');
|
||||
String cookie = "";
|
||||
if(index != -1) {
|
||||
cookie = name.substring(index, name.length());
|
||||
name = name.substring(0, index);
|
||||
}
|
||||
|
||||
// check loaded JAR files
|
||||
try {
|
||||
return super.findClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
|
||||
// Otherwise, try loading the class from the code base URL
|
||||
|
||||
// 4668479: Option to turn off codebase lookup in AppletClassLoader
|
||||
// during resource requests. [stanley.ho]
|
||||
if (codebaseLookup == false)
|
||||
throw new ClassNotFoundException(name);
|
||||
|
||||
// final String path = name.replace('.', '/').concat(".class").concat(cookie);
|
||||
String encodedName = ParseUtil.encodePath(name.replace('.', '/'), false);
|
||||
final String path = (new StringBuffer(encodedName)).append(".class").append(cookie).toString();
|
||||
try {
|
||||
byte[] b = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<byte[]>() {
|
||||
public byte[] run() throws IOException {
|
||||
try {
|
||||
URL finalURL = new URL(base, path);
|
||||
|
||||
// Make sure the codebase won't be modified
|
||||
if (base.getProtocol().equals(finalURL.getProtocol()) &&
|
||||
base.getHost().equals(finalURL.getHost()) &&
|
||||
base.getPort() == finalURL.getPort()) {
|
||||
return getBytes(finalURL);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}, acc);
|
||||
|
||||
if (b != null) {
|
||||
return defineClass(name, b, 0, b.length, codesource);
|
||||
} else {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw new ClassNotFoundException(name, e.getException());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the permissions for the given codesource object.
|
||||
* The implementation of this method first calls super.getPermissions,
|
||||
* to get the permissions
|
||||
* granted by the super class, and then adds additional permissions
|
||||
* based on the URL of the codesource.
|
||||
* <p>
|
||||
* If the protocol is "file"
|
||||
* and the path specifies a file, permission is granted to read all files
|
||||
* and (recursively) all files and subdirectories contained in
|
||||
* that directory. This is so applets with a codebase of
|
||||
* file:/blah/some.jar can read in file:/blah/, which is needed to
|
||||
* be backward compatible. We also add permission to connect back to
|
||||
* the "localhost".
|
||||
*
|
||||
* @param codesource the codesource
|
||||
* @throws NullPointerException if {@code codesource} is {@code null}.
|
||||
* @return the permissions granted to the codesource
|
||||
*/
|
||||
protected PermissionCollection getPermissions(CodeSource codesource)
|
||||
{
|
||||
final PermissionCollection perms = super.getPermissions(codesource);
|
||||
|
||||
URL url = codesource.getLocation();
|
||||
|
||||
String path = null;
|
||||
Permission p;
|
||||
|
||||
try {
|
||||
p = url.openConnection().getPermission();
|
||||
} catch (java.io.IOException ioe) {
|
||||
p = null;
|
||||
}
|
||||
|
||||
if (p instanceof FilePermission) {
|
||||
path = p.getName();
|
||||
} else if ((p == null) && (url.getProtocol().equals("file"))) {
|
||||
path = url.getFile().replace('/', File.separatorChar);
|
||||
path = ParseUtil.decode(path);
|
||||
}
|
||||
|
||||
if (path != null) {
|
||||
final String rawPath = path;
|
||||
if (!path.endsWith(File.separator)) {
|
||||
int endIndex = path.lastIndexOf(File.separatorChar);
|
||||
if (endIndex != -1) {
|
||||
path = path.substring(0, endIndex + 1) + "-";
|
||||
perms.add(new FilePermission(path,
|
||||
SecurityConstants.FILE_READ_ACTION));
|
||||
}
|
||||
}
|
||||
final File f = new File(rawPath);
|
||||
final boolean isDirectory = f.isDirectory();
|
||||
// grant codebase recursive read permission
|
||||
// this should only be granted to non-UNC file URL codebase and
|
||||
// the codesource path must either be a directory, or a file
|
||||
// that ends with .jar or .zip
|
||||
if (allowRecursiveDirectoryRead && (isDirectory ||
|
||||
rawPath.toLowerCase().endsWith(".jar") ||
|
||||
rawPath.toLowerCase().endsWith(".zip"))) {
|
||||
|
||||
Permission bperm;
|
||||
try {
|
||||
bperm = base.openConnection().getPermission();
|
||||
} catch (java.io.IOException ioe) {
|
||||
bperm = null;
|
||||
}
|
||||
if (bperm instanceof FilePermission) {
|
||||
String bpath = bperm.getName();
|
||||
if (bpath.endsWith(File.separator)) {
|
||||
bpath += "-";
|
||||
}
|
||||
perms.add(new FilePermission(bpath,
|
||||
SecurityConstants.FILE_READ_ACTION));
|
||||
} else if ((bperm == null) && (base.getProtocol().equals("file"))) {
|
||||
String bpath = base.getFile().replace('/', File.separatorChar);
|
||||
bpath = ParseUtil.decode(bpath);
|
||||
if (bpath.endsWith(File.separator)) {
|
||||
bpath += "-";
|
||||
}
|
||||
perms.add(new FilePermission(bpath, SecurityConstants.FILE_READ_ACTION));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return perms;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the contents of the specified URL as an array of bytes.
|
||||
*/
|
||||
private static byte[] getBytes(URL url) throws IOException {
|
||||
URLConnection uc = url.openConnection();
|
||||
if (uc instanceof java.net.HttpURLConnection) {
|
||||
java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc;
|
||||
int code = huc.getResponseCode();
|
||||
if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) {
|
||||
throw new IOException("open HTTP connection failed.");
|
||||
}
|
||||
}
|
||||
int len = uc.getContentLength();
|
||||
|
||||
// Fixed #4507227: Slow performance to load
|
||||
// class and resources. [stanleyh]
|
||||
//
|
||||
// Use buffered input stream [stanleyh]
|
||||
InputStream in = new BufferedInputStream(uc.getInputStream());
|
||||
|
||||
byte[] b;
|
||||
try {
|
||||
b = in.readAllBytes();
|
||||
if (len != -1 && b.length != len)
|
||||
throw new EOFException("Expected:" + len + ", read:" + b.length);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
// Object for synchronization around getResourceAsStream()
|
||||
private Object syncResourceAsStream = new Object();
|
||||
private Object syncResourceAsStreamFromJar = new Object();
|
||||
|
||||
// Flag to indicate getResourceAsStream() is in call
|
||||
private boolean resourceAsStreamInCall = false;
|
||||
private boolean resourceAsStreamFromJarInCall = false;
|
||||
|
||||
/**
|
||||
* Returns an input stream for reading the specified resource.
|
||||
*
|
||||
* The search order is described in the documentation for {@link
|
||||
* #getResource(String)}.<p>
|
||||
*
|
||||
* @param name the resource name
|
||||
* @return an input stream for reading the resource, or {@code null}
|
||||
* if the resource could not be found
|
||||
* @since 1.1
|
||||
*/
|
||||
public InputStream getResourceAsStream(String name)
|
||||
{
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
InputStream is = null;
|
||||
|
||||
// Fixed #4507227: Slow performance to load
|
||||
// class and resources. [stanleyh]
|
||||
//
|
||||
// The following is used to avoid calling
|
||||
// AppletClassLoader.findResource() in
|
||||
// super.getResourceAsStream(). Otherwise,
|
||||
// unnecessary connection will be made.
|
||||
//
|
||||
synchronized(syncResourceAsStream)
|
||||
{
|
||||
resourceAsStreamInCall = true;
|
||||
|
||||
// Call super class
|
||||
is = super.getResourceAsStream(name);
|
||||
|
||||
resourceAsStreamInCall = false;
|
||||
}
|
||||
|
||||
// 4668479: Option to turn off codebase lookup in AppletClassLoader
|
||||
// during resource requests. [stanley.ho]
|
||||
if (codebaseLookup == true && is == null)
|
||||
{
|
||||
// If resource cannot be obtained,
|
||||
// try to download it from codebase
|
||||
URL url = new URL(base, ParseUtil.encodePath(name, false));
|
||||
is = url.openStream();
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an input stream for reading the specified resource from the
|
||||
* the loaded jar files.
|
||||
*
|
||||
* The search order is described in the documentation for {@link
|
||||
* #getResource(String)}.<p>
|
||||
*
|
||||
* @param name the resource name
|
||||
* @return an input stream for reading the resource, or {@code null}
|
||||
* if the resource could not be found
|
||||
* @since 1.1
|
||||
*/
|
||||
public InputStream getResourceAsStreamFromJar(String name) {
|
||||
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream is = null;
|
||||
synchronized(syncResourceAsStreamFromJar) {
|
||||
resourceAsStreamFromJarInCall = true;
|
||||
// Call super class
|
||||
is = super.getResourceAsStream(name);
|
||||
resourceAsStreamFromJarInCall = false;
|
||||
}
|
||||
|
||||
return is;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finds the applet resource with the specified name. First checks
|
||||
* loaded JAR files then the applet code base for the resource.
|
||||
*/
|
||||
public URL findResource(String name) {
|
||||
// check loaded JAR files
|
||||
URL url = super.findResource(name);
|
||||
|
||||
// 6215746: Disable META-INF/* lookup from codebase in
|
||||
// applet/plugin classloader. [stanley.ho]
|
||||
if (name.startsWith("META-INF/"))
|
||||
return url;
|
||||
|
||||
// 4668479: Option to turn off codebase lookup in AppletClassLoader
|
||||
// during resource requests. [stanley.ho]
|
||||
if (codebaseLookup == false)
|
||||
return url;
|
||||
|
||||
if (url == null)
|
||||
{
|
||||
//#4805170, if it is a call from Applet.getImage()
|
||||
//we should check for the image only in the archives
|
||||
boolean insideGetResourceAsStreamFromJar = false;
|
||||
synchronized(syncResourceAsStreamFromJar) {
|
||||
insideGetResourceAsStreamFromJar = resourceAsStreamFromJarInCall;
|
||||
}
|
||||
|
||||
if (insideGetResourceAsStreamFromJar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fixed #4507227: Slow performance to load
|
||||
// class and resources. [stanleyh]
|
||||
//
|
||||
// Check if getResourceAsStream is called.
|
||||
//
|
||||
boolean insideGetResourceAsStream = false;
|
||||
|
||||
synchronized(syncResourceAsStream)
|
||||
{
|
||||
insideGetResourceAsStream = resourceAsStreamInCall;
|
||||
}
|
||||
|
||||
// If getResourceAsStream is called, don't
|
||||
// trigger the following code. Otherwise,
|
||||
// unnecessary connection will be made.
|
||||
//
|
||||
if (insideGetResourceAsStream == false)
|
||||
{
|
||||
// otherwise, try the code base
|
||||
try {
|
||||
url = new URL(base, ParseUtil.encodePath(name, false));
|
||||
// check if resource exists
|
||||
if(!resourceExists(url))
|
||||
url = null;
|
||||
} catch (Exception e) {
|
||||
// all exceptions, including security exceptions, are caught
|
||||
url = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
private boolean resourceExists(URL url) {
|
||||
// Check if the resource exists.
|
||||
// It almost works to just try to do an openConnection() but
|
||||
// HttpURLConnection will return true on HTTP_BAD_REQUEST
|
||||
// when the requested name ends in ".html", ".htm", and ".txt"
|
||||
// and we want to be able to handle these
|
||||
//
|
||||
// Also, cannot just open a connection for things like FileURLConnection,
|
||||
// because they succeed when connecting to a nonexistent file.
|
||||
// So, in those cases we open and close an input stream.
|
||||
boolean ok = true;
|
||||
try {
|
||||
URLConnection conn = url.openConnection();
|
||||
if (conn instanceof java.net.HttpURLConnection) {
|
||||
java.net.HttpURLConnection hconn =
|
||||
(java.net.HttpURLConnection) conn;
|
||||
|
||||
// To reduce overhead, using http HEAD method instead of GET method
|
||||
hconn.setRequestMethod("HEAD");
|
||||
|
||||
int code = hconn.getResponseCode();
|
||||
if (code == java.net.HttpURLConnection.HTTP_OK) {
|
||||
return true;
|
||||
}
|
||||
if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Fix for #4182052 - stanleyh
|
||||
*
|
||||
* The same connection should be reused to avoid multiple
|
||||
* HTTP connections
|
||||
*/
|
||||
|
||||
// our best guess for the other cases
|
||||
InputStream is = conn.getInputStream();
|
||||
is.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an enumeration of all the applet resources with the specified
|
||||
* name. First checks loaded JAR files then the applet code base for all
|
||||
* available resources.
|
||||
*/
|
||||
@Override
|
||||
public Enumeration<URL> findResources(String name) throws IOException {
|
||||
|
||||
final Enumeration<URL> e = super.findResources(name);
|
||||
|
||||
// 6215746: Disable META-INF/* lookup from codebase in
|
||||
// applet/plugin classloader. [stanley.ho]
|
||||
if (name.startsWith("META-INF/"))
|
||||
return e;
|
||||
|
||||
// 4668479: Option to turn off codebase lookup in AppletClassLoader
|
||||
// during resource requests. [stanley.ho]
|
||||
if (codebaseLookup == false)
|
||||
return e;
|
||||
|
||||
URL u = new URL(base, ParseUtil.encodePath(name, false));
|
||||
if (!resourceExists(u)) {
|
||||
u = null;
|
||||
}
|
||||
|
||||
final URL url = u;
|
||||
return new Enumeration<URL>() {
|
||||
private boolean done;
|
||||
public URL nextElement() {
|
||||
if (!done) {
|
||||
if (e.hasMoreElements()) {
|
||||
return e.nextElement();
|
||||
}
|
||||
done = true;
|
||||
if (url != null) {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
public boolean hasMoreElements() {
|
||||
return !done && (e.hasMoreElements() || url != null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Load and resolve the file specified by the applet tag CODE
|
||||
* attribute. The argument can either be the relative path
|
||||
* of the class file itself or just the name of the class.
|
||||
*/
|
||||
Class<?> loadCode(String name) throws ClassNotFoundException {
|
||||
// first convert any '/' or native file separator to .
|
||||
name = name.replace('/', '.');
|
||||
name = name.replace(File.separatorChar, '.');
|
||||
|
||||
// deal with URL rewriting
|
||||
String cookie = null;
|
||||
int index = name.indexOf(';');
|
||||
if(index != -1) {
|
||||
cookie = name.substring(index, name.length());
|
||||
name = name.substring(0, index);
|
||||
}
|
||||
|
||||
// save that name for later
|
||||
String fullName = name;
|
||||
// then strip off any suffixes
|
||||
if (name.endsWith(".class") || name.endsWith(".java")) {
|
||||
name = name.substring(0, name.lastIndexOf('.'));
|
||||
}
|
||||
try {
|
||||
if(cookie != null)
|
||||
name = (new StringBuffer(name)).append(cookie).toString();
|
||||
return loadClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
// then if it didn't end with .java or .class, or in the
|
||||
// really pathological case of a class named class or java
|
||||
if(cookie != null)
|
||||
fullName = (new StringBuffer(fullName)).append(cookie).toString();
|
||||
|
||||
return loadClass(fullName);
|
||||
}
|
||||
|
||||
/*
|
||||
* The threadgroup that the applets loaded by this classloader live
|
||||
* in. In the sun.* implementation of applets, the security manager's
|
||||
* (AppletSecurity) getThreadGroup returns the thread group of the
|
||||
* first applet on the stack, which is the applet's thread group.
|
||||
*/
|
||||
private AppletThreadGroup threadGroup;
|
||||
private AppContext appContext;
|
||||
|
||||
public ThreadGroup getThreadGroup() {
|
||||
synchronized (threadGroupSynchronizer) {
|
||||
if (threadGroup == null || threadGroup.isDestroyed()) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
threadGroup = new AppletThreadGroup(base + "-threadGroup");
|
||||
// threadGroup.setDaemon(true);
|
||||
// threadGroup is now destroyed by AppContext.dispose()
|
||||
|
||||
// Create the new AppContext from within a Thread belonging
|
||||
// to the newly created ThreadGroup, and wait for the
|
||||
// creation to complete before returning from this method.
|
||||
AppContextCreator creatorThread = new AppContextCreator(threadGroup);
|
||||
|
||||
// Since this thread will later be used to launch the
|
||||
// applet's AWT-event dispatch thread and we want the applet
|
||||
// code executing the AWT callbacks to use their own class
|
||||
// loader rather than the system class loader, explicitly
|
||||
// set the context class loader to the AppletClassLoader.
|
||||
creatorThread.setContextClassLoader(AppletClassLoader.this);
|
||||
|
||||
creatorThread.start();
|
||||
try {
|
||||
synchronized(creatorThread.syncObject) {
|
||||
while (!creatorThread.created) {
|
||||
creatorThread.syncObject.wait();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) { }
|
||||
appContext = creatorThread.appContext;
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
return threadGroup;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the AppContext, if any, corresponding to this AppletClassLoader.
|
||||
*/
|
||||
public AppContext getAppContext() {
|
||||
return appContext;
|
||||
}
|
||||
|
||||
int usageCount = 0;
|
||||
|
||||
/**
|
||||
* Grab this AppletClassLoader and its ThreadGroup/AppContext, so they
|
||||
* won't be destroyed.
|
||||
*/
|
||||
public void grab() {
|
||||
synchronized(grabReleaseSynchronizer) {
|
||||
usageCount++;
|
||||
}
|
||||
getThreadGroup(); // Make sure ThreadGroup/AppContext exist
|
||||
}
|
||||
|
||||
protected void setExceptionStatus()
|
||||
{
|
||||
exceptionStatus = true;
|
||||
}
|
||||
|
||||
public boolean getExceptionStatus()
|
||||
{
|
||||
return exceptionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release this AppletClassLoader and its ThreadGroup/AppContext.
|
||||
* If nothing else has grabbed this AppletClassLoader, its ThreadGroup
|
||||
* and AppContext will be destroyed.
|
||||
*
|
||||
* Because this method may destroy the AppletClassLoader's ThreadGroup,
|
||||
* this method should NOT be called from within the AppletClassLoader's
|
||||
* ThreadGroup.
|
||||
*
|
||||
* Changed modifier to protected in order to be able to overwrite this
|
||||
* function in PluginClassLoader.java
|
||||
*/
|
||||
protected void release() {
|
||||
|
||||
AppContext tempAppContext = null;
|
||||
|
||||
synchronized(grabReleaseSynchronizer) {
|
||||
if (usageCount > 1) {
|
||||
--usageCount;
|
||||
} else {
|
||||
synchronized(threadGroupSynchronizer) {
|
||||
tempAppContext = resetAppContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dispose appContext outside any sync block to
|
||||
// prevent potential deadlock.
|
||||
if (tempAppContext != null) {
|
||||
try {
|
||||
tempAppContext.dispose(); // nuke the world!
|
||||
} catch (IllegalThreadStateException e) { }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* reset classloader's AppContext and ThreadGroup
|
||||
* This method is for subclass PluginClassLoader to
|
||||
* reset superclass's AppContext and ThreadGroup but do
|
||||
* not dispose the AppContext. PluginClassLoader does not
|
||||
* use UsageCount to decide whether to dispose AppContext
|
||||
*
|
||||
* @return previous AppContext
|
||||
*/
|
||||
protected AppContext resetAppContext() {
|
||||
AppContext tempAppContext = null;
|
||||
|
||||
synchronized(threadGroupSynchronizer) {
|
||||
// Store app context in temp variable
|
||||
tempAppContext = appContext;
|
||||
usageCount = 0;
|
||||
appContext = null;
|
||||
threadGroup = null;
|
||||
}
|
||||
return tempAppContext;
|
||||
}
|
||||
|
||||
|
||||
// Hash map to store applet compatibility info
|
||||
private HashMap<String, Boolean> jdk11AppletInfo = new HashMap<>();
|
||||
private HashMap<String, Boolean> jdk12AppletInfo = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Set applet target level as JDK 1.1.
|
||||
*
|
||||
* @param clazz Applet class.
|
||||
* @param bool true if JDK is targeted for JDK 1.1;
|
||||
* false otherwise.
|
||||
*/
|
||||
void setJDK11Target(Class<?> clazz, boolean bool)
|
||||
{
|
||||
jdk11AppletInfo.put(clazz.toString(), Boolean.valueOf(bool));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set applet target level as JDK 1.2.
|
||||
*
|
||||
* @param clazz Applet class.
|
||||
* @param bool true if JDK is targeted for JDK 1.2;
|
||||
* false otherwise.
|
||||
*/
|
||||
void setJDK12Target(Class<?> clazz, boolean bool)
|
||||
{
|
||||
jdk12AppletInfo.put(clazz.toString(), Boolean.valueOf(bool));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if applet is targeted for JDK 1.1.
|
||||
*
|
||||
* @param clazz Applet class.
|
||||
* @return TRUE if applet is targeted for JDK 1.1;
|
||||
* FALSE if applet is not;
|
||||
* null if applet is unknown.
|
||||
*/
|
||||
Boolean isJDK11Target(Class<?> clazz)
|
||||
{
|
||||
return jdk11AppletInfo.get(clazz.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if applet is targeted for JDK 1.2.
|
||||
*
|
||||
* @param clazz Applet class.
|
||||
* @return TRUE if applet is targeted for JDK 1.2;
|
||||
* FALSE if applet is not;
|
||||
* null if applet is unknown.
|
||||
*/
|
||||
Boolean isJDK12Target(Class<?> clazz)
|
||||
{
|
||||
return jdk12AppletInfo.get(clazz.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The AppContextCreator class is used to create an AppContext from within
|
||||
* a Thread belonging to the new AppContext's ThreadGroup. To wait for
|
||||
* this operation to complete before continuing, wait for the notifyAll()
|
||||
* operation on the syncObject to occur.
|
||||
*/
|
||||
class AppContextCreator extends Thread {
|
||||
Object syncObject = new Object();
|
||||
AppContext appContext = null;
|
||||
volatile boolean created = false;
|
||||
|
||||
/**
|
||||
* Must call the 5-args super-class constructor to erase locals.
|
||||
*/
|
||||
private AppContextCreator() {
|
||||
throw new UnsupportedOperationException("Must erase locals");
|
||||
}
|
||||
|
||||
AppContextCreator(ThreadGroup group) {
|
||||
super(group, null, "AppContextCreator", 0, false);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
appContext = SunToolkit.createNewAppContext();
|
||||
created = true;
|
||||
synchronized(syncObject) {
|
||||
syncObject.notifyAll();
|
||||
}
|
||||
} // run()
|
||||
|
||||
} // class AppContextCreator
|
@ -1,421 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.applet;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.FileDescriptor;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.net.SocketPermission;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
import java.util.StringTokenizer;
|
||||
import java.security.*;
|
||||
import java.lang.reflect.*;
|
||||
import jdk.internal.misc.JavaNetURLClassLoaderAccess;
|
||||
import jdk.internal.misc.JavaSecurityAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import sun.awt.AWTSecurityManager;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.AWTPermissions;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
import static java.lang.StackWalker.*;
|
||||
import static java.lang.StackWalker.Option.*;
|
||||
|
||||
|
||||
/**
|
||||
* This class defines an applet security policy
|
||||
*
|
||||
*/
|
||||
public
|
||||
class AppletSecurity extends AWTSecurityManager {
|
||||
private static final JavaNetURLClassLoaderAccess JNUCLA
|
||||
= SharedSecrets.getJavaNetURLClassLoaderAccess();
|
||||
private static final JavaSecurityAccess JSA = SharedSecrets.getJavaSecurityAccess();
|
||||
|
||||
/**
|
||||
* Construct and initialize.
|
||||
*/
|
||||
public AppletSecurity() {
|
||||
reset();
|
||||
}
|
||||
|
||||
// Cache to store known restricted packages
|
||||
private HashSet<String> restrictedPackages = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Reset from Properties
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
// Clear cache
|
||||
restrictedPackages.clear();
|
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
public Object run()
|
||||
{
|
||||
// Enumerate system properties
|
||||
Enumeration<?> e = System.getProperties().propertyNames();
|
||||
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
String name = (String) e.nextElement();
|
||||
|
||||
if (name != null && name.startsWith("package.restrict.access."))
|
||||
{
|
||||
String value = System.getProperty(name);
|
||||
|
||||
if (value != null && value.equalsIgnoreCase("true"))
|
||||
{
|
||||
String pkg = name.substring(24);
|
||||
|
||||
// Cache restricted packages
|
||||
restrictedPackages.add(pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static final StackWalker walker =
|
||||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<StackWalker>) () ->
|
||||
StackWalker.getInstance(RETAIN_CLASS_REFERENCE));
|
||||
/**
|
||||
* Returns the class loader of the most recently executing method from
|
||||
* a class defined using a non-system class loader. A non-system
|
||||
* class loader is defined as being a class loader that is not equal to
|
||||
* the system class loader (as returned
|
||||
* by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors.
|
||||
* <p>
|
||||
* This method will return
|
||||
* <code>null</code> in the following three cases:
|
||||
* <ol>
|
||||
* <li>All methods on the execution stack are from classes
|
||||
* defined using the system class loader or one of its ancestors.
|
||||
*
|
||||
* <li>All methods on the execution stack up to the first
|
||||
* "privileged" caller
|
||||
* (see {@link java.security.AccessController#doPrivileged})
|
||||
* are from classes
|
||||
* defined using the system class loader or one of its ancestors.
|
||||
*
|
||||
* <li> A call to <code>checkPermission</code> with
|
||||
* <code>java.security.AllPermission</code> does not
|
||||
* result in a SecurityException.
|
||||
* </ol>
|
||||
*
|
||||
* NOTE: This is an implementation of the SecurityManager.currentClassLoader
|
||||
* method that uses StackWalker. SecurityManager.currentClassLoader
|
||||
* has been removed from SE. This is a temporary workaround which is
|
||||
* only needed while applets are still supported.
|
||||
*
|
||||
* @return the class loader of the most recent occurrence on the stack
|
||||
* of a method from a class defined using a non-system class
|
||||
* loader.
|
||||
*/
|
||||
private static ClassLoader currentClassLoader() {
|
||||
StackFrame f =
|
||||
walker.walk(s -> s.takeWhile(AppletSecurity::isNonPrivileged)
|
||||
.filter(AppletSecurity::isNonSystemFrame)
|
||||
.findFirst())
|
||||
.orElse(null);
|
||||
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (f != null && sm != null) {
|
||||
try {
|
||||
sm.checkPermission(new AllPermission());
|
||||
} catch (SecurityException se) {
|
||||
return f.getDeclaringClass().getClassLoader();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the StackFrame is not AccessController.doPrivileged.
|
||||
*/
|
||||
private static boolean isNonPrivileged(StackFrame f) {
|
||||
// possibly other doPrivileged variants
|
||||
Class<?> c = f.getDeclaringClass();
|
||||
return c == AccessController.class &&
|
||||
f.getMethodName().equals("doPrivileged");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the StackFrame is not from a class defined by the
|
||||
* system class loader or one of its ancestors.
|
||||
*/
|
||||
private static boolean isNonSystemFrame(StackFrame f) {
|
||||
ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
ClassLoader ld = f.getDeclaringClass().getClassLoader();
|
||||
if (ld == null || ld == loader) return false;
|
||||
|
||||
while ((loader = loader.getParent()) != null) {
|
||||
if (ld == loader)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current (first) instance of an AppletClassLoader on the stack.
|
||||
*/
|
||||
private AppletClassLoader currentAppletClassLoader()
|
||||
{
|
||||
// try currentClassLoader first
|
||||
ClassLoader loader = currentClassLoader();
|
||||
|
||||
if ((loader == null) || (loader instanceof AppletClassLoader))
|
||||
return (AppletClassLoader)loader;
|
||||
|
||||
// if that fails, get all the classes on the stack and check them.
|
||||
Class<?>[] context = getClassContext();
|
||||
for (int i = 0; i < context.length; i++) {
|
||||
loader = context[i].getClassLoader();
|
||||
if (loader instanceof AppletClassLoader)
|
||||
return (AppletClassLoader)loader;
|
||||
}
|
||||
|
||||
/*
|
||||
* fix bug # 6433620 the logic here is : try to find URLClassLoader from
|
||||
* class context, check its AccessControlContext to see if
|
||||
* AppletClassLoader is in stack when it's created. for this kind of
|
||||
* URLClassLoader, return the AppContext associated with the
|
||||
* AppletClassLoader.
|
||||
*/
|
||||
for (int i = 0; i < context.length; i++) {
|
||||
final ClassLoader currentLoader = context[i].getClassLoader();
|
||||
|
||||
if (currentLoader instanceof URLClassLoader) {
|
||||
URLClassLoader ld = (URLClassLoader)currentLoader;
|
||||
loader = AccessController.doPrivileged(
|
||||
new PrivilegedAction<ClassLoader>() {
|
||||
public ClassLoader run() {
|
||||
|
||||
AccessControlContext acc = null;
|
||||
ProtectionDomain[] pds = null;
|
||||
|
||||
try {
|
||||
acc = JNUCLA.getAccessControlContext(ld);
|
||||
if (acc == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
pds = JSA.getProtectDomains(acc);
|
||||
if (pds == null) {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
|
||||
for (int i=0; i<pds.length; i++) {
|
||||
ClassLoader cl = pds[i].getClassLoader();
|
||||
|
||||
if (cl instanceof AppletClassLoader) {
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if (loader != null) {
|
||||
return (AppletClassLoader) loader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if that fails, try the context class loader
|
||||
loader = Thread.currentThread().getContextClassLoader();
|
||||
if (loader instanceof AppletClassLoader)
|
||||
return (AppletClassLoader)loader;
|
||||
|
||||
// no AppletClassLoaders on the stack
|
||||
return (AppletClassLoader)null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this threadgroup is in the applet's own thread
|
||||
* group. This will return false if there is no current class
|
||||
* loader.
|
||||
*/
|
||||
protected boolean inThreadGroup(ThreadGroup g) {
|
||||
if (currentAppletClassLoader() == null)
|
||||
return false;
|
||||
else
|
||||
return getThreadGroup().parentOf(g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true of the threadgroup of thread is in the applet's
|
||||
* own threadgroup.
|
||||
*/
|
||||
protected boolean inThreadGroup(Thread thread) {
|
||||
return inThreadGroup(thread.getThreadGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applets are not allowed to manipulate threads outside
|
||||
* applet thread groups. However a terminated thread no longer belongs
|
||||
* to any group.
|
||||
*/
|
||||
public void checkAccess(Thread t) {
|
||||
/* When multiple applets is reloaded simultaneously, there will be
|
||||
* multiple invocations to this method from plugin's SecurityManager.
|
||||
* This method should not be synchronized to avoid deadlock when
|
||||
* a page with multiple applets is reloaded
|
||||
*/
|
||||
if ((t.getState() != Thread.State.TERMINATED) && !inThreadGroup(t)) {
|
||||
checkPermission(SecurityConstants.MODIFY_THREAD_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean inThreadGroupCheck = false;
|
||||
|
||||
/**
|
||||
* Applets are not allowed to manipulate thread groups outside
|
||||
* applet thread groups.
|
||||
*/
|
||||
public synchronized void checkAccess(ThreadGroup g) {
|
||||
if (inThreadGroupCheck) {
|
||||
// if we are in a recursive check, it is because
|
||||
// inThreadGroup is calling appletLoader.getThreadGroup
|
||||
// in that case, only do the super check, as appletLoader
|
||||
// has a begin/endPrivileged
|
||||
checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
|
||||
} else {
|
||||
try {
|
||||
inThreadGroupCheck = true;
|
||||
if (!inThreadGroup(g)) {
|
||||
checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
|
||||
}
|
||||
} finally {
|
||||
inThreadGroupCheck = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws a {@code SecurityException} if the
|
||||
* calling thread is not allowed to access the package specified by
|
||||
* the argument.
|
||||
* <p>
|
||||
* This method is used by the {@code loadClass} method of class
|
||||
* loaders.
|
||||
* <p>
|
||||
* The {@code checkPackageAccess} method for class
|
||||
* {@code SecurityManager} calls
|
||||
* {@code checkPermission} with the
|
||||
* {@code RuntimePermission("accessClassInPackage."+ pkgname)}
|
||||
* permission.
|
||||
*
|
||||
* @param pkgname the package name.
|
||||
* @exception SecurityException if the caller does not have
|
||||
* permission to access the specified package.
|
||||
* @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
|
||||
*/
|
||||
public void checkPackageAccess(final String pkgname) {
|
||||
|
||||
// first see if the VM-wide policy allows access to this package
|
||||
super.checkPackageAccess(pkgname);
|
||||
|
||||
// now check the list of restricted packages
|
||||
for (Iterator<String> iter = restrictedPackages.iterator(); iter.hasNext();)
|
||||
{
|
||||
String pkg = iter.next();
|
||||
|
||||
// Prevent matching "sun" and "sunir" even if they
|
||||
// starts with similar beginning characters
|
||||
//
|
||||
if (pkgname.equals(pkg) || pkgname.startsWith(pkg + "."))
|
||||
{
|
||||
checkPermission(new java.lang.RuntimePermission
|
||||
("accessClassInPackage." + pkgname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thread group of the applet. We consult the classloader
|
||||
* if there is one.
|
||||
*/
|
||||
public ThreadGroup getThreadGroup() {
|
||||
/* If any applet code is on the execution stack, we return
|
||||
that applet's ThreadGroup. Otherwise, we use the default
|
||||
behavior. */
|
||||
AppletClassLoader appletLoader = currentAppletClassLoader();
|
||||
ThreadGroup loaderGroup = (appletLoader == null) ? null
|
||||
: appletLoader.getThreadGroup();
|
||||
if (loaderGroup != null) {
|
||||
return loaderGroup;
|
||||
} else {
|
||||
return super.getThreadGroup();
|
||||
}
|
||||
} // getThreadGroup()
|
||||
|
||||
/**
|
||||
* Get the AppContext corresponding to the current context.
|
||||
* The default implementation returns null, but this method
|
||||
* may be overridden by various SecurityManagers
|
||||
* (e.g. AppletSecurity) to index AppContext objects by the
|
||||
* calling context.
|
||||
*
|
||||
* @return the AppContext corresponding to the current context.
|
||||
* @see sun.awt.AppContext
|
||||
* @see java.lang.SecurityManager
|
||||
* @since 1.2.1
|
||||
*/
|
||||
public AppContext getAppContext() {
|
||||
AppletClassLoader appletLoader = currentAppletClassLoader();
|
||||
|
||||
if (appletLoader == null) {
|
||||
return null;
|
||||
} else {
|
||||
AppContext context = appletLoader.getAppContext();
|
||||
|
||||
// context == null when some thread in applet thread group
|
||||
// has not been destroyed in AppContext.dispose()
|
||||
if (context == null) {
|
||||
throw new SecurityException("Applet classloader has invalid AppContext");
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
} // class AppletSecurity
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1997, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.applet;
|
||||
|
||||
/**
|
||||
* This class defines an applet thread group.
|
||||
*
|
||||
* @author Arthur van Hoff
|
||||
*/
|
||||
public class AppletThreadGroup extends ThreadGroup {
|
||||
|
||||
/**
|
||||
* Constructs a new thread group for an applet.
|
||||
* The parent of this new group is the thread
|
||||
* group of the currently running thread.
|
||||
*
|
||||
* @param name the name of the new thread group.
|
||||
*/
|
||||
public AppletThreadGroup(String name) {
|
||||
this(Thread.currentThread().getThreadGroup(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new thread group for an applet.
|
||||
* The parent of this new group is the specified
|
||||
* thread group.
|
||||
*
|
||||
* @param parent the parent thread group.
|
||||
* @param name the name of the new thread group.
|
||||
* @exception NullPointerException if the thread group argument is
|
||||
* {@code null}.
|
||||
* @exception SecurityException if the current thread cannot create a
|
||||
* thread in the specified thread group.
|
||||
* @see java.lang.SecurityException
|
||||
* @since 1.1.1
|
||||
*/
|
||||
public AppletThreadGroup(ThreadGroup parent, String name) {
|
||||
super(parent, name);
|
||||
setMaxPriority(Thread.NORM_PRIORITY - 1);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -2740,7 +2740,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
|
||||
new java.security.PrivilegedAction<Object>() {
|
||||
public Object run() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
return sm instanceof sun.applet.AppletSecurity;
|
||||
return sm instanceof sun.awt.AWTSecurityManager;
|
||||
}
|
||||
});
|
||||
return appletSM.booleanValue();
|
||||
|
@ -143,7 +143,7 @@ public class CheckPackageAccess {
|
||||
"jdk.internal.loader", null, null),
|
||||
// java.desktop module loaded by boot loader and has an openQual pkg
|
||||
// that is exported
|
||||
new Test("java.desktop", "java.applet", null, "sun.applet",
|
||||
new Test("java.desktop", "java.applet", null, "sun.font",
|
||||
"sun.awt", null, "javax.swing.plaf.basic"),
|
||||
// java.security.jgss module loaded by platform loader
|
||||
new Test("java.security.jgss", "org.ietf.jgss", null,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,14 +24,11 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 6795356
|
||||
* @summary Checks that SwingLazyValue class correclty works
|
||||
* @summary Checks that SwingLazyValue class works correctly
|
||||
* @author Alexander Potochkin
|
||||
* @modules java.desktop/sun.applet
|
||||
* @run main/othervm TableTest
|
||||
*/
|
||||
|
||||
import sun.applet.AppletSecurity;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import java.awt.*;
|
||||
@ -41,7 +38,7 @@ public class TableTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
System.setSecurityManager(new AppletSecurity());
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
|
||||
JTable table = new JTable();
|
||||
TableCellEditor de = table.getDefaultEditor(Double.class);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,7 @@
|
||||
* @bug 4957669 5017871
|
||||
* @summary cannot load class names containing some JSR 202 characters;
|
||||
* plugin does not escape unicode character in http request
|
||||
* @modules java.desktop/sun.applet
|
||||
* @modules java.base/sun.net.www
|
||||
* jdk.httpserver
|
||||
* @compile -XDignore.symbol.file=true ClassnameCharTest.java
|
||||
* @run main ClassnameCharTest
|
||||
@ -33,9 +33,14 @@
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.jar.*;
|
||||
import com.sun.net.httpserver.*;
|
||||
import sun.applet.AppletClassLoader;
|
||||
import sun.net.www.ParseUtil;
|
||||
|
||||
public class ClassnameCharTest {
|
||||
static String FNPrefix = System.getProperty("test.src", ".") + File.separator;
|
||||
@ -79,7 +84,7 @@ public class ClassnameCharTest {
|
||||
try {
|
||||
URL base = new URL("http://localhost:" + server.getAddress().getPort());
|
||||
System.out.println ("Server: listening on " + base);
|
||||
MyAppletClassLoader acl = new MyAppletClassLoader(base);
|
||||
MyURLClassLoader acl = new MyURLClassLoader(base);
|
||||
Class<?> class1 = acl.findClass("fo o");
|
||||
System.out.println("class1 = " + class1);
|
||||
pass();
|
||||
@ -90,15 +95,95 @@ public class ClassnameCharTest {
|
||||
server.stop(0);
|
||||
}
|
||||
}
|
||||
|
||||
static class MyAppletClassLoader extends AppletClassLoader {
|
||||
MyAppletClassLoader(URL base) {
|
||||
super(base);
|
||||
// the class loader code was copied from the now deleted AppletClassLoader
|
||||
static class MyURLClassLoader extends URLClassLoader {
|
||||
private URL base; /* applet code base URL */
|
||||
private CodeSource codesource; /* codesource for the base URL */
|
||||
private AccessControlContext acc;
|
||||
MyURLClassLoader(URL base) {
|
||||
super(new URL[0]);
|
||||
this.base = base;
|
||||
this.codesource =
|
||||
new CodeSource(base, (java.security.cert.Certificate[]) null);
|
||||
acc = AccessController.getContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
return super.findClass(name);
|
||||
int index = name.indexOf(';');
|
||||
String cookie = "";
|
||||
if(index != -1) {
|
||||
cookie = name.substring(index, name.length());
|
||||
name = name.substring(0, index);
|
||||
}
|
||||
|
||||
// check loaded JAR files
|
||||
try {
|
||||
return super.findClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
|
||||
// Otherwise, try loading the class from the code base URL
|
||||
// final String path = name.replace('.', '/').concat(".class").concat(cookie);
|
||||
String encodedName = ParseUtil.encodePath(name.replace('.', '/'), false);
|
||||
final String path = (new StringBuffer(encodedName)).append(".class").append(cookie).toString();
|
||||
try {
|
||||
byte[] b = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<byte[]>() {
|
||||
public byte[] run() throws IOException {
|
||||
try {
|
||||
URL finalURL = new URL(base, path);
|
||||
|
||||
// Make sure the codebase won't be modified
|
||||
if (base.getProtocol().equals(finalURL.getProtocol()) &&
|
||||
base.getHost().equals(finalURL.getHost()) &&
|
||||
base.getPort() == finalURL.getPort()) {
|
||||
return getBytes(finalURL);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}, acc);
|
||||
|
||||
if (b != null) {
|
||||
return defineClass(name, b, 0, b.length, codesource);
|
||||
} else {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw new ClassNotFoundException(name, e.getException());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the contents of the specified URL as an array of bytes.
|
||||
*/
|
||||
private static byte[] getBytes(URL url) throws IOException {
|
||||
URLConnection uc = url.openConnection();
|
||||
if (uc instanceof java.net.HttpURLConnection) {
|
||||
java.net.HttpURLConnection huc = (java.net.HttpURLConnection) uc;
|
||||
int code = huc.getResponseCode();
|
||||
if (code >= java.net.HttpURLConnection.HTTP_BAD_REQUEST) {
|
||||
throw new IOException("open HTTP connection failed.");
|
||||
}
|
||||
}
|
||||
int len = uc.getContentLength();
|
||||
|
||||
InputStream in = new BufferedInputStream(uc.getInputStream());
|
||||
|
||||
byte[] b;
|
||||
try {
|
||||
b = in.readAllBytes();
|
||||
if (len != -1 && b.length != len)
|
||||
throw new EOFException("Expected:" + len + ", read:" + b.length);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user