public void apply() throws ConfigurationException {
    // validate content and source roots
    final Map<VirtualFile, String> contentRootToModuleNameMap = new HashMap<>();
    final Map<VirtualFile, VirtualFile> srcRootsToContentRootMap = new HashMap<>();
    for (final ModuleEditor moduleEditor : myModuleEditors.values()) {
      final ModuleRootModel rootModel = moduleEditor.getRootModel();
      final ContentEntry[] contents = rootModel.getContentEntries();
      final String moduleName = moduleEditor.getName();
      Set<VirtualFile> sourceRoots = new HashSet<>();
      for (ContentEntry content : contents) {
        for (VirtualFile root : content.getSourceFolderFiles()) {
          if (!sourceRoots.add(root)) {
            throw new ConfigurationException(JavaUiBundle.message("module.paths.validation.duplicate.source.root.in.same.module.error", root.getPresentableUrl(), moduleName));
          }
        }
      }

      for (ContentEntry contentEntry : contents) {
        final VirtualFile contentRoot = contentEntry.getFile();
        if (contentRoot == null) {
          continue;
        }
        final String previousName = contentRootToModuleNameMap.put(contentRoot, moduleName);
        if (previousName != null && !previousName.equals(moduleName)) {
          throw new ConfigurationException(
            JavaUiBundle.message("module.paths.validation.duplicate.content.error", contentRoot.getPresentableUrl(), previousName, moduleName)
          );
        }
        for (VirtualFile srcRoot : contentEntry.getSourceFolderFiles()) {
          final VirtualFile anotherContentRoot = srcRootsToContentRootMap.put(srcRoot, contentRoot);
          if (anotherContentRoot != null) {
            final String problematicModule;
            final String correctModule;
            if (VfsUtilCore.isAncestor(anotherContentRoot, contentRoot, true)) {
              problematicModule = contentRootToModuleNameMap.get(anotherContentRoot);
              correctModule = contentRootToModuleNameMap.get(contentRoot);
            }
            else {
              problematicModule = contentRootToModuleNameMap.get(contentRoot);
              correctModule = contentRootToModuleNameMap.get(anotherContentRoot);
            }
            throw new ConfigurationException(
              JavaUiBundle.message("module.paths.validation.duplicate.source.root.error", problematicModule, srcRoot.getPresentableUrl(), correctModule)
            );
          }
        }
      }
    }
    // additional validation: directories marked as src roots must belong to the same module as their corresponding content root
    for (Map.Entry<VirtualFile, VirtualFile> entry : srcRootsToContentRootMap.entrySet()) {
      final VirtualFile srcRoot = entry.getKey();
      final VirtualFile correspondingContent = entry.getValue();
      final String expectedModuleName = contentRootToModuleNameMap.get(correspondingContent);

      for (VirtualFile candidateContent = srcRoot; candidateContent != null && !candidateContent.equals(correspondingContent); candidateContent = candidateContent.getParent()) {
        final String moduleName = contentRootToModuleNameMap.get(candidateContent);
        if (moduleName != null && !moduleName.equals(expectedModuleName)) {
          throw new ConfigurationException(
            JavaUiBundle.message("module.paths.validation.source.root.belongs.to.another.module.error", srcRoot.getPresentableUrl(), expectedModuleName, moduleName)
          );
        }
      }
    }

    for (ModuleEditor moduleEditor : myModuleEditors.values()) {
      moduleEditor.canApply();
    }

    final Map<Sdk, Sdk> modifiedToOriginalMap = new HashMap<>();
    final ProjectSdksModel projectJdksModel = myProjectStructureConfigurable.getProjectJdksModel();
    for (Map.Entry<Sdk, Sdk> entry : projectJdksModel.getProjectSdks().entrySet()) {
      modifiedToOriginalMap.put(entry.getValue(), entry.getKey());
    }

    final Ref<ConfigurationException> exceptionRef = Ref.create();
    ApplicationManager.getApplication().runWriteAction(() -> {
      final List<ModifiableRootModel> models = new ArrayList<>(myModuleEditors.size());
      try {
        for (final ModuleEditor moduleEditor : myModuleEditors.values()) {
          final ModifiableRootModel model = moduleEditor.apply();
          if (model != null) {
            if (!model.isSdkInherited()) {
              // make sure the sdk is set to original SDK stored in the JDK Table
              final Sdk modelSdk = model.getSdk();
              if (modelSdk != null) {
                final Sdk original = modifiedToOriginalMap.get(modelSdk);
                if (original != null) {
                  model.setSdk(original);
                }
              }
            }
            models.add(model);
          }
        }
        myFacetsConfigurator.applyEditors();
      }
      catch (ConfigurationException e) {
        exceptionRef.set(e);
        return;
      }

      try {
        for (ModuleEditor editor : myModuleEditors.values()) {
          editor.resetModifiableModel();
        }
        ModifiableModelCommitter.multiCommit(models, myModuleModel);
        myModuleModelCommitted = true;
        myFacetsConfigurator.commitFacets();

      }
      finally {
        myProjectStructureConfigurable.getModulesConfig().getFacetEditorFacade().clearMaps(false);

        myFacetsConfigurator = createFacetsConfigurator();
        initModuleModel();
        myModuleModelCommitted = false;
      }
    });

    if (!exceptionRef.isNull()) {
      throw exceptionRef.get();
    }

    myModified = false;
  }
public void apply()