Class JNLPClassLoader

java.lang.Object
java.lang.ClassLoader
java.security.SecureClassLoader
java.net.URLClassLoader
net.sourceforge.jnlp.runtime.classloader.JNLPClassLoader
All Implemented Interfaces:
Closeable, AutoCloseable

public class JNLPClassLoader extends URLClassLoader
Classloader that takes it's resources from a JNLP file. If the JNLP file defines extensions, separate classloaders for these will be created automatically. Classes are loaded with the security context when the classloader was created.
Version:
$Revision: 1.20 $
  • Field Details

    • FILE_READ_ACTION

      private static final String FILE_READ_ACTION
      See Also:
    • LOG

      private static final Logger LOG
    • TEMPLATE

      private static final String TEMPLATE
      Signed JNLP File and Template
      See Also:
    • APPLICATION

      private static final String APPLICATION
      See Also:
    • isSignedJNLP

      private boolean isSignedJNLP
      True if the application has a signed JNLP File
    • uniqueKeyToLoader

      private static final Map<String, JNLPClassLoader> uniqueKeyToLoader
      map from JNLPFile unique key to shared classloader
    • uniqueKeyToLock

      private static final Map<String, ReentrantLock> uniqueKeyToLock
      map from JNLPFile unique key to lock, the lock is needed to enforce correct initialization of applets that share a unique key
    • nativeLibraryStorage

      private final NativeLibraryStorage nativeLibraryStorage
      Provides a search path invalid input: '&' temporary storage for native code
    • acc

      private final AccessControlContext acc
      security context
    • resourcePermissions

      private final List<Permission> resourcePermissions
      the permissions for the cached jar files
    • app

      private ApplicationInstance app
      the app
    • loaders

      private JNLPClassLoader[] loaders
      list of this, local and global loaders this loader uses
    • strict

      private final boolean strict
      whether to strictly adhere to the spec or not
    • tracker

      private final ResourceTracker tracker
      loads the resources
    • updatePolicy

      private final UpdatePolicy updatePolicy
      the update policy for resources
    • file

      private final JNLPFile file
      the JNLP file
    • resources

      private final ResourcesDesc resources
      the resources section
    • security

      private SecurityDesc security
      the security section
    • runtimePermissions

      private final ArrayList<Permission> runtimePermissions
      Permissions granted by the user during runtime.
    • available

      private final List<JARDesc> available
      all jars not yet part of classloader or active Synchronized since this field may become shared data between multiple classloading threads. See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String).
    • jcv

      final JarCertVerifier jcv
      the jar cert verifier tool to verify our jars
    • signing

    • jarIndexes

      private final List<JarIndexAccess> jarIndexes
      ArrayList containing jar indexes for various jars available to this classloader Synchronized since this field may become shared data between multiple classloading threads/ See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String).
    • classpaths

      private final Set<String> classpaths
      Set of classpath strings declared in the manifest.mf files Synchronized since this field may become shared data between multiple classloading threads. See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String).
    • jarEntries

      private final Set<String> jarEntries
      File entries in the jar files available to this classloader Synchronized sinc this field may become shared data between multiple classloading threads. See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String).
    • jarLocationSecurityMap

      final Map<UrlKey, SecurityDesc> jarLocationSecurityMap
      Map of specific original (remote) CodeSource Urls to securitydesc Synchronized since this field may become shared data between multiple classloading threads. See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String).
    • alreadyTried

      private final Set<UrlKey> alreadyTried
    • codeBaseLoader

      private CodeBaseClassLoader codeBaseLoader
      Loader for codebase (which is a path, rather than a file)
    • foundMainJar

      private boolean foundMainJar
      True if the jar with the main class has been found
    • mainClass

      private String mainClass
      Name of the application's main class
    • useCount

      private int useCount
      Variable to track how many times this loader is in use
    • enableCodeBase

      private boolean enableCodeBase
    • securityDelegate

      private final SecurityDelegate securityDelegate
    • mac

  • Constructor Details

    • JNLPClassLoader

      public JNLPClassLoader(JNLPFile file, UpdatePolicy policy) throws LaunchException
      Create a new JNLPClassLoader from the specified file.
      Parameters:
      file - the JNLP file
      policy - update policy of loader
      Throws:
      LaunchException - if app can not be loaded
    • JNLPClassLoader

      private JNLPClassLoader(JNLPFile file, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws LaunchException
      Create a new JNLPClassLoader from the specified file.
      Parameters:
      file - the JNLP file
      policy - the UpdatePolicy for this class loader
      mainName - name of the application's main class
      enableCodeBase - switch whether this classloader can search in codebase or not
      Throws:
      LaunchException - when need to kill an app comes.
  • Method Details

    • isCertUnderestimated

      private static boolean isCertUnderestimated()
    • consultCertificateSecurityException

      static void consultCertificateSecurityException(LaunchException ex) throws LaunchException
      Throws:
      LaunchException
    • installShutdownHooks

      private void installShutdownHooks()
      Install JVM shutdown hooks to clean up resources allocated by this ClassLoader.
    • setSecurity

      private void setSecurity() throws LaunchException
      Throws:
      LaunchException
    • checkEnforceable

      private SecurityDesc checkEnforceable(SecurityDesc desc) throws LaunchException
      Without a SecurityManager every permission set is effectively AllPermission, so anything less than all-permissions cannot be honoured.
      Throws:
      LaunchException
    • getUniqueKeyLock

      private static ReentrantLock getUniqueKeyLock(String uniqueKey)
      Gets the lock for a given unique key, creating one if it does not yet exist. This operation is atomic invalid input: '&' thread-safe.
      Parameters:
      uniqueKey - the file whose unique key should be used
      Returns:
      the lock
    • createInstance

      private static JNLPClassLoader createInstance(JNLPFile file, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws LaunchException
      Creates a fully initialized JNLP classloader for the specified JNLPFile, to be used as an applet/application's classloader. In contrast, JNLP classloaders can also be constructed simply to merge its resources into another classloader.
      Parameters:
      file - the file to load classes for
      policy - the update policy to use when downloading resources
      mainName - Overrides the main class name of the application
      Throws:
      LaunchException
    • getInstance

      public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy, boolean enableCodeBase) throws LaunchException
      Returns a JNLP classloader for the specified JNLP file.
      Parameters:
      file - the file to load classes for
      policy - the update policy to use when downloading resources
      enableCodeBase - true if codebase can be searched (ok for applets,false for apps)
      Returns:
      existing classloader. creates new if none reliable exists
      Throws:
      LaunchException - when launch is doomed
    • getInstance

      private static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws LaunchException
      Returns a JNLP classloader for the specified JNLP file.
      Parameters:
      file - the file to load classes for
      policy - the update policy to use when downloading resources
      mainName - Overrides the main class name of the application
      enableCodeBase - ue if codebase can be searched (ok for applets,false for apps)
      Returns:
      existing classloader. creates new if none reliable exists
      Throws:
      LaunchException - when launch is doomed
    • getInstance

      private static JNLPClassLoader getInstance(URL location, String uniqueKey, VersionString version, ParserSettings settings, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws IOException, ParseException, LaunchException
      Returns a JNLP classloader for the JNLP file at the specified location.
      Parameters:
      location - the file's location
      uniqueKey - key to manage applets/applications in shared vm
      version - the file's version
      settings - settings of parser
      policy - the update policy to use when downloading resources
      mainName - Overrides the main class name of the application
      enableCodeBase - whether to enable codebase search or not
      Returns:
      classloader of this app
      Throws:
      IOException - when IO fails
      ParseException - when parsing fails
      LaunchException - when launch is doomed
    • initializeExtensions

      private void initializeExtensions()
      Load the extensions specified in the JNLP file.
    • initializeReadJarPermissions

      private void initializeReadJarPermissions()
      Make permission objects for the classpath.
    • getReadPermission

      private Permission getReadPermission(JARDesc jar)
    • isInvalidJar

      boolean isInvalidJar(JARDesc jar)
      Check if a described jar file is invalid
      Parameters:
      jar - the jar to check
      Returns:
      true if file exists AND is an invalid jar, false otherwise
    • initializeResources

      private void initializeResources() throws LaunchException
      Load all of the JARs used in this JNLP file into the ResourceTracker for downloading.
      Throws:
      LaunchException
    • initializeManifestAttributesChecker

      private void initializeManifestAttributesChecker()
    • getJnlpFileCodebase

      private URL getJnlpFileCodebase()
    • checkForMain

      void checkForMain(List<JARDesc> jars) throws LaunchException
      * Checks for the jar that contains the main class. If the main class was found, it checks to see if the jar is signed and whether it contains a signed JNLP file
      Parameters:
      jars - Jars that are checked to see if they contain the main class
      Throws:
      LaunchException - Thrown if the signed JNLP file, within the main jar, fails to be verified or does not match
    • hasMainJar

      boolean hasMainJar()
      Returns:
      true if this loader has the main jar
    • hasMainInExtensions

      private boolean hasMainInExtensions()
      Returns true if extension loaders have the main jar
    • verifySignedJNLP

      private void verifySignedJNLP(JarFile jarFile) throws LaunchException
      Is called by checkForMain() to check if the jar file is signed and if it contains a signed JNLP file.
      Parameters:
      jarFile - the jar file
      Throws:
      LaunchException - thrown if the signed JNLP file, within the main jar, fails to be verified or does not match
    • checkTrustWithUser

      private void checkTrustWithUser() throws LaunchException
      Prompt the user for trust on all the signers that require approval.
      Throws:
      LaunchException - if the user does not approve every dialog prompt.
    • enableCodeBase

      public void enableCodeBase()
      Add applet's codebase URL. This allows compatibility with applets that load resources from their codebase instead of through JARs, but can slow down resource loading. Resources loaded from the codebase are not cached.
    • setApplication

      public void setApplication(ApplicationInstance app)
      Sets the JNLP app this group is for; can only be called once.
      Parameters:
      app - application to be ser to this group
    • getApplication

      public ApplicationInstance getApplication()
      Returns:
      the JNLP app for this classloader
    • getJNLPFile

      public JNLPFile getJNLPFile()
      Returns:
      the JNLP file the classloader was created from.
    • getPermissions

      public PermissionCollection getPermissions(CodeSource cs)
      Returns the permissions for the CodeSource.
      Overrides:
      getPermissions in class URLClassLoader
    • addPermission

      public void addPermission(Permission p)
    • fillInPartJars

      private void fillInPartJars(List<JARDesc> jars)
      Adds to the specified list of JARS any other JARs that need to be loaded at the same time as the JARs specified (ie, are in the same part).
      Parameters:
      jars - jar archives to be added
    • getAllAvailableJarsInPart

      private LinkedHashSet<JARDesc> getAllAvailableJarsInPart(String part)
    • activateJars

      void activateJars(List<JARDesc> jars)
      Ensures that the list of jars have all been transferred, and makes them available to the classloader. If a jar contains native code, the libraries will be extracted and placed in the path.
      Parameters:
      jars - the list of jars to load
    • doActivateJars

      private Void doActivateJars(List<JARDesc> jars)
    • findLibrary

      protected String findLibrary(String lib)
      Return the absolute path to the native library.
      Overrides:
      findLibrary in class ClassLoader
    • findNativeLibrary

      private String findNativeLibrary(String lib, String syslib)
    • findLibraryExt

      private String findLibraryExt(String lib)
      Try to find the library path from another peer classloader.
      Parameters:
      lib - library to be found
      Returns:
      location of library
    • waitForJars

      private void waitForJars(List<JARDesc> jars)
      Wait for a group of JARs, and send download events if there is a download listener or display a progress window otherwise.
      Parameters:
      jars - the jars
    • findLoadedClassAll

      private Class<?> findLoadedClassAll(String name)
      Find the loaded class in this loader or any of its extension loaders.
      Parameters:
      name - name of class
      Returns:
      the class found by name
    • loadClass

      public Class<?> loadClass(String name) throws ClassNotFoundException
      Find a JAR in the shared 'extension' classloaders, this classloader, or one of the classloaders for the JNLP file's extensions. This method used to be qualified "synchronized." This was done solely for the purpose of ensuring only one thread entered the method at a time. This was not strictly necessary - ensuring that all affected fields are thread-safe is sufficient. Locking on the JNLPClassLoader instance when this method is called can result in deadlock if another thread is dealing with the CodebaseClassLoader at the same time. This solution is very heavy-handed as the instance lock is not truly required, and taking the lock on the classloader instance when not needed is not in general a good idea because it can and will lead to deadlock when multithreaded classloading is in effect. The solution is to keep the fields thread safe on their own. This is accomplished by wrapping them in Collections.synchronized* to provide atomic add/remove operations, and synchronizing on them when iterating or performing multiple mutations. See bug report RH976833. On some systems this bug will manifest itself as deadlock on every webpage with more than one Java applet, potentially also causing the browser process to hang. More information in the mailing list archives: http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2013-September/024536.html

      Affected fields: available, classpaths, jarIndexes, jarEntries, jarLocationSecurityMap

      Overrides:
      loadClass in class ClassLoader
      Throws:
      ClassNotFoundException
    • loadClassFromParentClassloader

      private Class<?> loadClassFromParentClassloader(String name) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • loadClassFromInternalManifestClasspath

      private Class<?> loadClassFromInternalManifestClasspath(String name) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • loadFromJarIndexes

      private Class<?> loadFromJarIndexes(String name) throws ClassNotFoundException
      Throws:
      ClassNotFoundException
    • addNewJar

      private void addNewJar(JARDesc desc)
      Adds a new JARDesc into this classloader.

      This will add the JARDesc into the resourceTracker and block until it is downloaded.

      Parameters:
      desc - the JARDesc for the new jar
    • addNewJar

      private void addNewJar(JARDesc desc, UpdatePolicy updatePolicy)
      Adds a new JARDesc into this classloader.
      Parameters:
      desc - the JARDesc for the new jar
      updatePolicy - the UpdatePolicy for the resource
    • findClass

      protected Class<?> findClass(String name) throws ClassNotFoundException
      Find the class in this loader or any of its extension loaders.
      Overrides:
      findClass in class URLClassLoader
      Throws:
      ClassNotFoundException
    • loadClassExt

      private Class<?> loadClassExt(String name) throws ClassNotFoundException
      Search for the class by incrementally adding resources to the classloader and its extension classloaders until the resource is found.
      Throws:
      ClassNotFoundException
    • findResource

      public URL findResource(String name)
      Finds the resource in this, the parent, or the extension class loaders.
      Overrides:
      findResource in class URLClassLoader
      Returns:
      a URL for the resource, or null if the resource could not be found.
    • findResources

      public Enumeration<URL> findResources(String name) throws IOException
      Find the resources in this, the parent, or the extension class loaders. Load lazy resources if not found in current resources.
      Overrides:
      findResources in class URLClassLoader
      Throws:
      IOException
    • findResourcesBySearching

      private Enumeration<URL> findResourcesBySearching(String name) throws IOException
      Find the resources in this, the parent, or the extension class loaders.
      Throws:
      IOException
    • removeDuplicates

      private Collection<URL> removeDuplicates(List<URL> lresources)
    • addAvailable

      private void addAvailable()
      Adds whatever resources have already been downloaded in the background.
    • addNextResource

      private JNLPClassLoader addNextResource() throws LaunchException
      Adds the next unused resource to the classloader. That resource and all those in the same part will be downloaded and added to the classloader before returning. If there are no more resources to add, the method returns immediately.
      Returns:
      the classloader that resources were added to, or null
      Throws:
      LaunchException - Thrown if the signed JNLP file, within the main jar, fails to be verified or does not match
    • getNextJarsToLoad

      private List<JARDesc> getNextJarsToLoad()
    • getSigning

      public boolean getSigning()
    • checkPartialSigningWithUser

      void checkPartialSigningWithUser()
      Call this when it's suspected that an applet's permission level may have just changed from Full Signing to Partial Signing. This will display a one-time prompt asking the user to confirm running the partially signed applet. Partially Signed applets always start off as appearing to be Fully Signed, and then during the initialization or loading process, we find that we actually need to demote the applet to Partial, either due to finding that not all of its JARs are actually signed, or because it needs to load something unsigned out of the codebase.
    • getSigningState

      private JNLPClassLoader.SigningState getSigningState()
    • getSecurity

      public SecurityDesc getSecurity()
    • getCodeSourceSecurity

      private SecurityDesc getCodeSourceSecurity(URL source)
      Returns the security descriptor for given code source URL
      Parameters:
      source - the origin (remote) url of the code
      Returns:
      The SecurityDescriptor for that source
    • merge

      private void merge(JNLPClassLoader extLoader)
      Merges the code source/security descriptor mapping from another loader
      Parameters:
      extLoader - The loader form which to merge
      Throws:
      SecurityException - if the code is called from an untrusted source
    • addToCodeBaseLoader

      private void addToCodeBaseLoader(URL u)
      Adds the given path to the path loader
      Parameters:
      u - the path to add
      Throws:
      IllegalArgumentException - If the given url is not a path
    • incrementLoaderUseCount

      private void incrementLoaderUseCount()
      Increments loader use count by 1
      Throws:
      SecurityException - if caller is not trusted
    • getLoaders

      JNLPClassLoader[] getLoaders()
      Returns all loaders that this loader uses, including itself
    • removeJars

      void removeJars(JARDesc[] jars)
      Remove jars from the file system.
      Parameters:
      jars - Jars marked for removal.
    • initializeNewJarDownload

      void initializeNewJarDownload(URL ref, String part, VersionString version)
      Downloads and initializes jars into this loader.
      Parameters:
      ref - Path of the launch or extension JNLP File containing the resource. If null, main JNLP's file location will be used instead.
      part - The name of the path.
      version - of jar to be downloaded
    • manageExternalJars

      boolean manageExternalJars(URL ref, String version, JNLPClassLoader.DownloadAction action)
      Manages DownloadService jars which are not mentioned in the JNLP file
      Parameters:
      ref - Path to the resource.
      version - The version of resource. If null, no version is specified.
      action - The action to perform with the resource. Either DOWNLOADTOCACHE, REMOVEFROMCACHE, or CHECKCACHE.
      Returns:
      true if CHECKCACHE and the resource is cached.
    • decrementLoaderUseCount

      private void decrementLoaderUseCount()
      Decrements loader use count by 1

      If count reaches 0, loader is removed from list of available loaders

      Throws:
      SecurityException - if caller is not trusted
    • getAccessControlContextForClassLoading

      AccessControlContext getAccessControlContextForClassLoading()
      Returns an appropriate AccessControlContext for loading classes in the running instance.

      The default context during class-loading only allows connection to codebase. However applets are allowed to load jars from arbitrary locations and the codebase only access falls short if a class from one location needs a class from another.

      Given protected access since CodeBaseClassloader uses this function too.

      Returns:
      The appropriate AccessControlContext for loading classes for this instance
    • getMainClass

      public String getMainClass()
    • getTracker

      public ResourceTracker getTracker()
    • getMainClassNameFromManifest

      public String getMainClassNameFromManifest(JARDesc mainJarDesc) throws IOException
      Throws:
      IOException