@NotNull
  public static ProjectJdkImpl createSdk(
      @NotNull Sdk[] allSdks,
      @NotNull VirtualFile homeDir,
      SdkType sdkType,
      @Nullable SdkAdditionalData additionalData,
      @Nullable String customSdkSuggestedName) {
    final List<Sdk> sdksList = Arrays.asList(allSdks);

    String sdkPath = sdkType.sdkPath(homeDir);

    final String sdkName =
        customSdkSuggestedName == null
            ? createUniqueSdkName(sdkType, sdkPath, sdksList)
            : createUniqueSdkName(customSdkSuggestedName, sdksList);

    ProjectJdkImpl sdk = new ProjectJdkImpl(sdkName, sdkType);

    if (additionalData != null) {
      // additional initialization.
      // E.g. some ruby sdks must be initialized before
      // setupSdkPaths() method invocation
      sdk.setSdkAdditionalData(additionalData);
    }

    sdk.setHomePath(sdkPath);
    return sdk;
  }
  @NotNull
  @Override
  public Sdk createJdk(@NotNull String jdkName, @NotNull String home, boolean isJre) {
    ProjectJdkImpl jdk = new ProjectJdkImpl(jdkName, this);
    SdkModificator sdkModificator = jdk.getSdkModificator();

    String path = home.replace(File.separatorChar, '/');
    sdkModificator.setHomePath(path);
    sdkModificator.setVersionString(
        jdkName); // must be set after home path, otherwise setting home path clears the version
                  // string

    File jdkHomeFile = new File(home);
    addClasses(jdkHomeFile, sdkModificator, isJre);
    addSources(jdkHomeFile, sdkModificator);
    addDocs(jdkHomeFile, sdkModificator);
    sdkModificator.commitChanges();

    return jdk;
  }
  @NotNull
  @TestOnly
  public Sdk createMockJdk(@NotNull String jdkName, @NotNull String home, boolean isJre) {
    String homePath = home.replace(File.separatorChar, '/');
    File jdkHomeFile = new File(homePath);
    List<VirtualFile> classes = findClasses(jdkHomeFile, isJre);
    VirtualFile sources = findSources(jdkHomeFile);
    VirtualFile docs = findDocs(jdkHomeFile, "docs/api");
    ProjectRootContainerImpl rootContainer = new ProjectRootContainerImpl(true);
    rootContainer.startChange();
    for (VirtualFile aClass : classes) {
      rootContainer.addRoot(aClass, OrderRootType.CLASSES);
    }
    if (sources != null) {
      rootContainer.addRoot(sources, OrderRootType.SOURCES);
    }
    if (docs != null) {
      rootContainer.addRoot(docs, OrderRootType.DOCUMENTATION);
    }
    rootContainer.finishChange();

    ProjectJdkImpl jdk =
        new ProjectJdkImpl(jdkName, this, homePath, jdkName) {
          @Override
          public void setName(@NotNull String name) {
            throwReadOnly();
          }

          @Override
          public void readExternal(@NotNull Element element) {
            throwReadOnly();
          }

          @Override
          public void readExternal(
              @NotNull Element element, @Nullable ProjectJdkTable projectJdkTable) {
            throwReadOnly();
          }

          @NotNull
          @Override
          public SdkModificator getSdkModificator() {
            throwReadOnly();
            return null;
          }

          @Override
          public void setSdkAdditionalData(SdkAdditionalData data) {
            throwReadOnly();
          }

          @Override
          public void addRoot(VirtualFile root, OrderRootType rootType) {
            throwReadOnly();
          }

          @Override
          public void removeRoot(VirtualFile root, OrderRootType rootType) {
            throwReadOnly();
          }

          @Override
          public void removeRoots(OrderRootType rootType) {
            throwReadOnly();
          }

          @Override
          public void removeAllRoots() {
            throwReadOnly();
          }

          @Override
          public boolean isWritable() {
            return false;
          }

          @Override
          public void update() {
            throwReadOnly();
          }

          @Override
          public VirtualFile[] getRoots(OrderRootType rootType) {
            return rootContainer.getRootFiles(rootType);
          }

          @NotNull
          @Override
          public RootProvider getRootProvider() {
            return new RootProvider() {
              @NotNull
              @Override
              public String[] getUrls(@NotNull OrderRootType rootType) {
                return ContainerUtil.map2Array(
                    getFiles(rootType), String.class, VirtualFile::getUrl);
              }

              @NotNull
              @Override
              public VirtualFile[] getFiles(@NotNull OrderRootType rootType) {
                return getRoots(rootType);
              }

              @Override
              public void addRootSetChangedListener(@NotNull RootSetChangedListener listener) {}

              @Override
              public void addRootSetChangedListener(
                  @NotNull RootSetChangedListener listener, @NotNull Disposable parentDisposable) {}

              @Override
              public void removeRootSetChangedListener(@NotNull RootSetChangedListener listener) {}
            };
          }
        };

    ProjectJdkImpl.copyRoots(rootContainer, jdk);
    return jdk;
  }