// 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.util.io;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ExceptionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.nio.ch.FileChannelImpl;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.channels.FileChannel;

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

  private static final MethodHandle setUnInterruptible = setupUnInterruptibleHandle();

  @Nullable
  private static MethodHandle setupUnInterruptibleHandle() {
    MethodHandle setUnInterruptible = null;
    try {
      //noinspection SpellCheckingInspection,JavaLangInvokeHandleSignature
      setUnInterruptible = MethodHandles
        .lookup()
        .findVirtual(FileChannelImpl.class, "setUninterruptible", MethodType.methodType(void.class));
      LOG.info("un-interruptible FileChannel-s will be used for indexes");
    }
    catch (NoSuchMethodException e) {
      LOG.info("interruptible FileChannel-s will be used for indexes");
    }
    catch (IllegalAccessException e) {
      LOG.error(e);
    }
    return setUnInterruptible;
  }

  @NotNull
  static FileChannel unInterruptible(@NotNull FileChannel channel) {
    try {
      if (setUnInterruptible != null && channel instanceof FileChannelImpl) {
        setUnInterruptible.invoke(channel);
      }
    }
    catch (Throwable e) {
      ExceptionUtil.rethrow(e);
    }
    return channel;
  }
}

@@ -340,43 +340,8 @@
 ble;
-%0Aimport sun.nio.ch.FileChannelImpl;
 %0A%0Aim
@@ -594,16 +594,98 @@
 lass);%0A%0A
+  private static final Class%3C?%3E sunNioChFileChannelImpl = setupFileChannelImpl();%0A
   privat
@@ -764,16 +764,209 @@
 dle();%0A%0A
+  private static Class%3C?%3E setupFileChannelImpl() %7B%0A    try %7B%0A      return Class.forName(%22sun.nio.ch.FileChannelImpl%22);%0A    %7D%0A    catch (ClassNotFoundException ignored) %7B%7D%0A    return null;%0A  %7D%0A%0A
   @Nulla
@@ -1088,16 +1088,63 @@
 y %7B%0A
+      if (sunNioChFileChannelImpl != null) %7B%0A  
       //
 noin
@@ -1139,16 +1139,17 @@
       //
+ 
 noinspec
@@ -1180,39 +1180,11 @@
 tion
-,JavaLangInvokeHandleSignature%0A
+%0A  
     
@@ -1228,16 +1228,18 @@
         
+  
 .lookup(
@@ -1240,16 +1240,18 @@
 ookup()%0A
+  
         
@@ -1263,16 +1263,24 @@
 Virtual(
+sunNioCh
 FileChan
@@ -1286,22 +1286,16 @@
 nnelImpl
-.class
 , %22setUn
@@ -1346,16 +1346,68 @@
 lass));%0A
+      %7D%0A    %7D%0A    catch (NoSuchMethodException e) %7B%0A
       LO
@@ -1418,11 +1418,8 @@
 fo(%22
-un-
 inte
@@ -1483,36 +1483,37 @@
 %0A    catch (
-NoSuchMethod
+IllegalAccess
 Exception e)
@@ -1507,32 +1507,96 @@
 sException e) %7B%0A
+      LOG.error(e);%0A    %7D%0A    if (setUnInterruptible != null) %7B%0A
       LOG.info(%22
@@ -1587,32 +1587,35 @@
       LOG.info(%22
+un-
 interruptible Fi
@@ -1663,65 +1663,85 @@
    %7D
-%0A    catch (IllegalAccessException e) %7B%0A      LOG.error(e
+ else %7B%0A      LOG.info(%22interruptible FileChannel-s will be used for indexes%22
 );%0A 
@@ -1915,42 +1915,86 @@
  && 
-channel instanceof FileChannelImpl
+sunNioChFileChannelImpl != null && sunNioChFileChannelImpl.isInstance(channel)
 ) %7B%0A

use reflection to get FileChannelUtil class