/**
   * INTERNAL: This method will return the key to be used to store/retrieve the delegates for a
   * given application.
   *
   * <p>OC4J classLoader levels: 0 - APP.web (servlet/jsp) or APP.wrapper (ejb) 1 - APP.root (parent
   * for helperContext) 2 - default.root 3 - system.root 4 - oc4j.10.1.3 (remote EJB) or
   * org.eclipse.persistence:11.1.1.0.0 5 - api:1.4.0 6 - jre.extension:0.0.0 7 -
   * jre.bootstrap:1.5.0_07 (with various J2SE versions)
   *
   * @return Application classloader for OC4J, application name for WebLogic, otherwise
   *     Thread.currentThread().getContextClassLoader()
   */
  private static Object getDelegateMapKey(ClassLoader classLoader) {
    String classLoaderName = classLoader.getClass().getName();

    // Default to Thread.currentThread().getContextClassLoader()
    Object delegateKey = classLoader;

    // Delegates in OC4J server will be keyed on classloader
    if (classLoaderName.startsWith(OC4J_CLASSLOADER_NAME)) {
      // Check to see if we are running in a Servlet container or a local EJB container
      if ((classLoader.getParent() != null) //
          && ((classLoader.toString().indexOf(SDOConstants.CLASSLOADER_WEB_FRAGMENT) != -1) //
              || (classLoader.toString().indexOf(SDOConstants.CLASSLOADER_EJB_FRAGMENT) != -1))) {
        classLoader = classLoader.getParent();
      }
      delegateKey = classLoader;
      // Delegates in WebLogic server will be keyed on application name
    } else if (classLoaderName.contains(WLS_CLASSLOADER_NAME)) {
      Object executeThread = getExecuteThread();
      if (executeThread != null) {
        try {
          Method getMethod =
              PrivilegedAccessHelper.getPublicMethod(
                  executeThread.getClass(),
                  WLS_APPLICATION_NAME_GET_METHOD_NAME,
                  PARAMETER_TYPES,
                  false);
          delegateKey = PrivilegedAccessHelper.invokeMethod(getMethod, executeThread);
          // ExecuteThread returns null
          if (delegateKey == null) {
            delegateKey = classLoader;
          }
        } catch (Exception e) {
          throw SDOException.errorInvokingWLSMethodReflectively(
              WLS_APPLICATION_NAME_GET_METHOD_NAME, WLS_EXECUTE_THREAD, e);
        }
      }
    }
    return delegateKey;
  }
 /**
  * INTERNAL: This convenience method will look up a WebLogic execute thread from the runtime MBean
  * tree. The execute thread contains application information. This code will use the name of the
  * current thread to lookup the corresponding ExecuteThread. The ExecuteThread will allow us to
  * obtain the application name (and version, etc).
  *
  * @return application name or null if the name cannot be obtained
  */
 private static Object getExecuteThread() {
   if (getWLSMBeanServer() != null) {
     // Lazy load the ThreadPoolRuntime instance
     if (wlsThreadPoolRuntime == null) {
       ObjectName service = null;
       ObjectName serverRuntime = null;
       try {
         service = new ObjectName(WLS_SERVICE_KEY);
       } catch (Exception x) {
         throw SDOException.errorGettingWLSObjectName(
             WLS_RUNTIME_SERVICE + " [" + WLS_SERVICE_KEY + "]", x);
       }
       try {
         serverRuntime = (ObjectName) wlsMBeanServer.getAttribute(service, WLS_SERVER_RUNTIME);
       } catch (Exception x) {
         throw SDOException.errorGettingWLSObjectName(WLS_SERVER_RUNTIME, x);
       }
       try {
         wlsThreadPoolRuntime =
             (ObjectName) wlsMBeanServer.getAttribute(serverRuntime, WLS_THREADPOOL_RUNTIME);
       } catch (Exception x) {
         throw SDOException.errorGettingWLSObjectName(WLS_THREADPOOL_RUNTIME, x);
       }
     }
     try {
       return wlsMBeanServer.invoke(
           wlsThreadPoolRuntime,
           WLS_EXECUTE_THREAD_GET_METHOD_NAME,
           new Object[] {Thread.currentThread().getName()},
           new String[] {String.class.getName()});
     } catch (Exception x) {
       throw SDOException.errorInvokingWLSMethodReflectively(
           WLS_EXECUTE_THREAD_GET_METHOD_NAME, WLS_THREADPOOL_RUNTIME, x);
     }
   }
   return null;
 }