docs: private ClassLoader createRarClassLoader() throws UnableToAdaptException, MalformedURLException {
          final boolean trace = TraceComponent.isAnyTracingEnabled();
  
          // Get the files needed to convert the rar file artifact containers into adaptable containers
          // Using the ID and the rar file modification date as a unique name for the cache files
  
          File bundleWorkareaRoot = bundle.getDataFile("");
          if (trace && tc.isDebugEnabled()) {
              Tr.debug(this, tc, "bundleWorkareaRoot " + bundleWorkareaRoot);
          }
  
          // Get list of files in the bundle's data cache
          final Bundle theBundle = bundle;
          File[] cacheFiles = AccessController.doPrivileged(new PrivilegedAction<File[]>() {
              @Override
              public File[] run() {
                  return theBundle.getDataFile("").listFiles();
              }
          });
  
          // Create unique cache suffix for this rar file
          String cacheSuffix = "-.-." + id + "--.-";
          String cacheSuffixMod = cacheSuffix + Long.valueOf(FileUtils.fileLastModified(new File(rarFilePath))).toString();
          if (trace && tc.isDebugEnabled()) {
              Tr.debug(this, tc, "cacheSuffixMod " + cacheSuffixMod);
          }
  
          // Clean out cache directories that are for a different version of the rar file than the current one.
          // ONLY clean out cache directories for this ID, there may be other rar files specified for this server
          for (File f : cacheFiles) {
              if (trace && tc.isDebugEnabled()) {
                  Tr.debug(this, tc, "bundle file path: " + f.getPath());
              }
              if (f.getPath().contains(cacheSuffixMod)) {
                  // keep it
                  if (trace && tc.isDebugEnabled()) {
                      Tr.debug(this, tc, "This is a good cache dir for the rar file, keep it");
                  }
              } else {
                  // if the directory does not have the correct suffix but does have the id then it
                  // must be a version different from the current rar file, delete it
                  if (f.getPath().contains(cacheSuffix)) {
                      if (trace && tc.isDebugEnabled()) {
                          Tr.debug(this, tc, "This is a cache dir for " + cacheSuffix + " but the modification date is not a match, delete it");
                      }
                      if (!deleteBundleCacheDir(f)) {
                          if (trace && tc.isDebugEnabled()) {
                              Tr.debug(this, tc, "Delete failed for ", f, " check previous debug messages");
                          }
                      }
                  } else {
                      if (trace && tc.isDebugEnabled()) {
                          Tr.debug(this, tc, "This is NOT a cache dir for " + cacheSuffix + " leave it alone");
                      }
                  }
              }
          }
  
          // getDataFile will return reference to existing file or create it if it does not exist
          File rarCacheDir = bundle.getDataFile("rarCache" + cacheSuffixMod);
          if (trace && tc.isDebugEnabled()) {
              Tr.debug(this, tc, "getDataFile rarCacheDir " + rarCacheDir);
          }
          if (!FileUtils.ensureDirExists(rarCacheDir)) {
              // TODO This should really be Tr.error(tc, "jca.msg.id", bundle, ctx);
              if (trace && tc.isDebugEnabled()) {
                  Tr.debug(this, tc, "Cache failed!!!");
              }
          }
          File rarOverlayDirectory = bundle.getDataFile("rarOverlayDirectory" + cacheSuffixMod);
          if (trace && tc.isDebugEnabled()) {
              Tr.debug(this, tc, "getDataFile rarOverlayDirectory " + rarOverlayDirectory);
          }
          if (!FileUtils.ensureDirExists(rarOverlayDirectory)) {
              // TODO This should really be Tr.error(tc, "jca.msg.id", bundle, ctx);
              if (trace && tc.isDebugEnabled()) {
                  Tr.debug(this, tc, "Overlay failed!!!");
              }
          }
          File rarCacheDirForOverlayContent = bundle.getDataFile("rarCacheDirForOverlayContent" + cacheSuffixMod);
          if (trace && tc.isDebugEnabled()) {
              Tr.debug(this, tc, "getDataFile rarCacheDirForOverlayContent " + rarCacheDirForOverlayContent);
          }
          if (!FileUtils.ensureDirExists(rarCacheDirForOverlayContent)) {
              // TODO This should really be Tr.error(tc, "jca.msg.id", bundle, ctx);
              if (trace && tc.isDebugEnabled()) {
                  Tr.debug(this, tc, "Cache for overlay failed!!!");
              }
          }
  
          // Get artifact containers for the rar file classes and for the jars in the rar file
          ArtifactContainer c = null;
  
          List<ArtifactContainer> rarContainers = new ArrayList<ArtifactContainer>();
  
          c = _acf.getContainer(rarCacheDir, new File(rarFilePath));
          rarContainers.add(c);
          Iterator<ArtifactEntry> i = c.iterator();
          // TODO this is only working for jars that are in the root, i.e. there is no path in front of the jar
          while (i.hasNext()) {
              ArtifactEntry ae = i.next();
              if (ae.getPath().toLowerCase().endsWith(".jar")) {
                  if (trace && tc.isDebugEnabled()) {
                      Tr.debug(this, tc, "Artifact entry [ " + ae.getPath() + " ]");
                  }
                  ArtifactContainer jarEntry = ae.convertToContainer();
                  rarContainers.add(jarEntry);
                  if (trace && tc.isDebugEnabled()) {
                      Tr.debug(this, tc, "Jar entry [ " + jarEntry.getPath() + " ]");
                  }
              }
          }
  
          // Convert artifact containers to adaptable containers
          List<Container> classLoaderContainers = new ArrayList<Container>();
  
          for (ArtifactContainer ac : rarContainers) {
              classLoaderContainers.add(_amf.getContainer(rarOverlayDirectory, rarCacheDirForOverlayContent, ac));
          }
  
          // Create the class loader
          GatewayConfiguration gwCfg = classloadingSvc.createGatewayConfiguration().setApiTypeVisibility(ApiType.SPEC, ApiType.API, ApiType.IBMAPI,
                                                                                                         ApiType.THIRDPARTY,
                                                                                                         ApiType.STABLE).setDynamicImportPackage("*").setDelegateToSystem(true);
  
          rarClassLoaderId = classloadingSvc.createIdentity(DeferredService.RESOURCE_ADAPTER_DOMAIN, id);
          if (trace && tc.isDebugEnabled()) {
              Tr.debug(this, tc, "Resource adapter [ " + rarFilePath + " ]: Class loader ID [ " + rarClassLoaderId + " ]");
          }
  
          Container rarContainer = _amf.getContainer(rarOverlayDirectory, rarCacheDirForOverlayContent, c);
          ProtectionDomain protectionDomain = getProtectionDomain(rarContainer);
  
          ClassLoaderConfiguration clCfg = classloadingSvc.createClassLoaderConfiguration().setId(rarClassLoaderId).setProtectionDomain(protectionDomain);
  
          ClassLoader rarClassLoader = classloadingSvc.createTopLevelClassLoader(classLoaderContainers, gwCfg, clCfg);
  
          if (trace && tc.isDebugEnabled()) {
              Tr.debug(this, tc, "Resource adapter [ " + rarFilePath + " ]: Class loader [ " + rarClassLoader + " ]");
          }
  
          return rarClassLoader;
      }