// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.remoteServer.agent.impl;

import com.intellij.ReviseWhenPortedToJDK;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.lang.JavaVersion;

import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class RemoteAgentClassLoaderCache {
  private static final Logger LOG = Logger.getInstance(RemoteAgentClassLoaderCache.class);

  private final Map<Set<URL>, URLClassLoader> myUrls2ClassLoader = new HashMap<>();

  public URLClassLoader getOrCreateClassLoader(Set<URL> libraryUrls) {
    URLClassLoader result = myUrls2ClassLoader.get(libraryUrls);
    if (result == null) {
      result = createClassLoaderWithoutApplicationParent(libraryUrls);
      myUrls2ClassLoader.put(libraryUrls, result);
    }
    return result;
  }

  public static URLClassLoader createClassLoaderWithoutApplicationParent(Set<URL> libraryUrls) {
    ClassLoader platformOrBootstrap = PlatformClassLoaderHolder.ourInstance;
    LOG.info("platform class loader: " + platformOrBootstrap);
    return new URLClassLoader(libraryUrls.toArray(new URL[0]), platformOrBootstrap);
  }

  private static final class PlatformClassLoaderHolder {
    public static final ClassLoader ourInstance = initPlatformClassLoader();

    @ReviseWhenPortedToJDK("9")
    private static ClassLoader initPlatformClassLoader() {
      if (JavaVersion.current().isAtLeast(9)) {
        try {
          @SuppressWarnings("JavaReflectionMemberAccess")
          Object result = ClassLoader.class.getMethod("getPlatformClassLoader").invoke(null);
          return (ClassLoader)result;
        }
        catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
          LOG.error("Can't access platform classloader for " + JavaVersion.current(), e);
        }
      }
      return null; // `null` represents bootstrap classloader
    }
  }
}

@@ -205,173 +205,35 @@
 lij.
-ReviseWhenPortedToJDK;%0Aimport com.intellij.openapi.diagnostic.Logger;%0Aimport com.intellij.util.lang.JavaVersion;%0A%0Aimport java.lang.reflect.InvocationTargetException;
+openapi.diagnostic.Logger;%0A
 %0Aimp
@@ -1022,16 +1022,31 @@
 strap = 
+ClassLoader.get
 Platform
@@ -1060,26 +1060,10 @@
 ader
-Holder.ourInstance
+()
 ;%0A  
@@ -1215,771 +1215,7 @@
 %0A  %7D
-%0A%0A  private static final class PlatformClassLoaderHolder %7B%0A    public static final ClassLoader ourInstance = initPlatformClassLoader();%0A%0A    @ReviseWhenPortedToJDK(%229%22)%0A    private static ClassLoader initPlatformClassLoader() %7B%0A      if (JavaVersion.current().isAtLeast(9)) %7B%0A        try %7B%0A          @SuppressWarnings(%22JavaReflectionMemberAccess%22)%0A          Object result = ClassLoader.class.getMethod(%22getPlatformClassLoader%22).invoke(null);%0A          return (ClassLoader)result;%0A        %7D%0A        catch (NoSuchMethodException %7C IllegalAccessException %7C InvocationTargetException e) %7B%0A          LOG.error(%22Can't access platform classloader for %22 + JavaVersion.current(), e);%0A        %7D%0A      %7D%0A      return null; // %60null%60 represents bootstrap classloader%0A    %7D%0A  %7D
 %0A%7D%0A

use API from JDK 11 directly and get rid of reflection