/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* 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.
*/
private boolean exceptionStatus = false;
private boolean codebaseLookup = true;
private volatile boolean allowRecursiveDirectoryRead = true;
/*
* Creates a new AppletClassLoader for the specified base URL.
*/
super(new URL[0]);
this.codesource =
}
public void disableRecursiveDirectoryRead() {
allowRecursiveDirectoryRead = false;
}
/**
* Set the codebase lookup flag.
*/
this.codebaseLookup = codebaseLookup;
}
/*
* Returns the applet code base URL.
*/
return base;
}
/*
* Returns the URLs used for loading classes and resources.
*/
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()
*/
try {
} catch (MalformedURLException e) {
throw new IllegalArgumentException("name");
}
// 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.
*/
throws ClassNotFoundException
{
// First check if we have permission to access the package. This
// should go away once we've added support for exported packages.
if (i != -1) {
}
try {
} catch (ClassNotFoundException e) {
//printError(name, e.getException());
throw e;
} catch (RuntimeException e) {
//printError(name, e);
throw e;
} catch (Error e) {
//printError(name, e);
throw e;
}
}
/*
* Finds the applet class with the specified name. First searches
* loaded JAR files then the applet code base for the class.
*/
if(index != -1) {
}
// check loaded JAR files
try {
} 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);
try {
byte[] b = (byte[]) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
try {
// Make sure the codebase won't be modified
}
else {
return null;
}
} catch (Exception e) {
return null;
}
}
}, acc);
if (b != null) {
} else {
throw new ClassNotFoundException(name);
}
} catch (PrivilegedActionException e) {
}
}
/**
* 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
* be backward compatible. We also add permission to connect back to
* the "localhost".
*
* @param codesource the codesource
* @return the permissions granted to the codesource
*/
{
Permission p;
try {
p = null;
}
if (p instanceof FilePermission) {
}
if (endIndex != -1) {
}
}
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 ||
try {
}
if (bperm instanceof FilePermission) {
bpath += "-";
}
bpath += "-";
}
}
}
}
return perms;
}
/*
* Returns the contents of the specified URL as an array of bytes.
*/
throw new IOException("open HTTP connection failed.");
}
}
// Fixed #4507227: Slow performance to load
// class and resources. [stanleyh]
//
// Use buffered input stream [stanleyh]
byte[] b;
try {
} finally {
}
return b;
}
// Object for synchronization around getResourceAsStream()
// 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</code>
* if the resource could not be found
* @since JDK1.1
*/
{
throw new NullPointerException("name");
}
try
{
// 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
resourceAsStreamInCall = false;
}
// 4668479: Option to turn off codebase lookup in AppletClassLoader
// during resource requests. [stanley.ho]
{
// If resource cannot be obtained,
// try to download it from codebase
}
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</code>
* if the resource could not be found
* @since JDK1.1
*/
throw new NullPointerException("name");
}
try {
synchronized(syncResourceAsStreamFromJar) {
resourceAsStreamFromJarInCall = true;
// Call super class
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.
*/
// check loaded JAR files
// 6215746: Disable META-INF/* lookup from codebase in
return url;
// 4668479: Option to turn off codebase lookup in AppletClassLoader
// during resource requests. [stanley.ho]
if (codebaseLookup == false)
return url;
{
//#4805170, if it is a call from Applet.getImage()
//we should check for the image only in the archives
boolean insideGetResourceAsStreamFromJar = false;
synchronized(syncResourceAsStreamFromJar) {
}
return null;
}
// Fixed #4507227: Slow performance to load
// class and resources. [stanleyh]
//
// Check if getResourceAsStream is called.
//
boolean insideGetResourceAsStream = false;
synchronized(syncResourceAsStream)
{
}
// 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 {
// check if resource exists
if(!resourceExists(url))
} catch (Exception e) {
// all exceptions, including security exceptions, are caught
}
}
}
return 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 {
// To reduce overhead, using http HEAD method instead of GET method
return true;
}
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
}
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.
*/
// 6215746: Disable META-INF/* lookup from codebase in
return e;
// 4668479: Option to turn off codebase lookup in AppletClassLoader
// during resource requests. [stanley.ho]
if (codebaseLookup == false)
return e;
if (!resourceExists(u)) {
u = null;
}
return new Enumeration() {
private boolean done;
public Object nextElement() {
if (!done) {
if (e.hasMoreElements()) {
return e.nextElement();
}
done = true;
return url;
}
}
throw new NoSuchElementException();
}
public boolean hasMoreElements() {
}
};
}
/*
* 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.
*/
// first convert any '/' or native file separator to .
// deal with URL rewriting
if(index != -1) {
}
// save that name for later
// then strip off any suffixes
}
try {
} 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
}
/*
* 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.
*/
synchronized (threadGroupSynchronizer) {
// 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.
// 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.
try {
synchronized(creatorThread.syncObject) {
while (!creatorThread.created) {
}
}
} catch (InterruptedException e) { }
return null;
}
});
}
return threadGroup;
}
}
/*
* Get the AppContext, if any, corresponding to this AppletClassLoader.
*/
return appContext;
}
/**
* 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() {
synchronized(grabReleaseSynchronizer) {
if (usageCount > 1) {
--usageCount;
} else {
synchronized(threadGroupSynchronizer) {
}
}
}
// Dispose appContext outside any sync block to
// prevent potential deadlock.
if (tempAppContext != null) {
try {
} 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
*/
synchronized(threadGroupSynchronizer) {
// Store app context in temp variable
usageCount = 0;
appContext = null;
threadGroup = null;
}
return tempAppContext;
}
// Hash map to store applet compatibility info
/**
* 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.
*/
{
}
/**
* 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.
*/
{
}
/**
* Determine if applet is targeted for JDK 1.1.
*
* @param applet Applet class.
* @return TRUE if applet is targeted for JDK 1.1;
* FALSE if applet is not;
* null if applet is unknown.
*/
{
}
/**
* Determine if applet is targeted for JDK 1.2.
*
* @param applet Applet class.
* @return TRUE if applet is targeted for JDK 1.2;
* FALSE if applet is not;
* null if applet is unknown.
*/
{
}
new AppletMessageHandler("appletclassloader");
/*
* Prints a class loading error message.
*/
if (e == null) {
} else if (e instanceof IOException) {
} else if (e instanceof ClassFormatError) {
} else if (e instanceof ThreadDeath) {
} else if (e instanceof Error) {
}
if (s != null) {
}
}
}
/*
* 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.
*/
volatile boolean created = false;
super(group, "AppContextCreator");
}
public void run() {
created = true;
synchronized(syncObject) {
}
} // run()
} // class AppContextCreator