package com.google.jstestdriver.idea.assertFramework.support; import com.google.common.collect.Sets; import com.intellij.ide.scriptingContext.ScriptingLibraryMappings; import com.intellij.lang.javascript.library.JSLibraryManager; import com.intellij.lang.javascript.library.JSLibraryMappings; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.libraries.scripting.ScriptingLibraryModel; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Set; /* * All operations should be executed on EDT. */ class NewLibraryCreationManager implements ExtractDirectoryTypeManager.ChangeListener { private final Project myProject; private final JPanel myLibraryNameDefinitionPanel; private final JTextField myNewLibraryNameTextField; private final String myAssertionFrameworkName; private final JSLibraryManager myScriptingLibraryManager; private File myExtractDirectory; private NewLibraryCreationManager(Project project, JPanel libraryNameDefinitionPanel, JTextField newLibraryNameTextField, String assertionFrameworkName) { myProject = project; myLibraryNameDefinitionPanel = libraryNameDefinitionPanel; myNewLibraryNameTextField = newLibraryNameTextField; myAssertionFrameworkName = assertionFrameworkName; myScriptingLibraryManager = ServiceManager.getService(myProject, JSLibraryManager.class); initNewLibraryName(); } private void initNewLibraryName() { String libraryName = findAvailableLibraryName(); myNewLibraryNameTextField.setText(libraryName); } private String findAvailableLibraryName() { myScriptingLibraryManager.reset(); final String initialLibraryName = myAssertionFrameworkName + " adapter for JsTestDriver"; String libraryName = initialLibraryName; boolean available = checkGlobalLibraryAvailabilityByName(libraryName); int id = 1; while (!available) { libraryName = initialLibraryName + " #" + id; available = checkGlobalLibraryAvailabilityByName(libraryName); id++; } return libraryName; } public DialogWrapper.ValidationInfo validate() { String libraryName = myNewLibraryNameTextField.getText(); boolean libraryNameAvailable = checkGlobalLibraryAvailabilityByName(libraryName); if (!libraryNameAvailable) { return new DialogWrapper.ValidationInfo("Library '" + libraryName + "' is already created.", myNewLibraryNameTextField); } return null; } private boolean checkGlobalLibraryAvailabilityByName(String libraryName) { return myScriptingLibraryManager.getLibraryByName(libraryName) == null; } public static NewLibraryCreationManager install(Project project, JPanel libraryNameDefinitionPanel, JTextField newJavaScriptLibraryTextField, String assertionFrameworkName) { return new NewLibraryCreationManager(project, libraryNameDefinitionPanel, newJavaScriptLibraryTextField, assertionFrameworkName); } @Override public void onExtractDirectoryChanged(File extractDirectory) { boolean insideContentRoots = isInsideContentRoots(extractDirectory); myNewLibraryNameTextField.setEnabled(!insideContentRoots); myExtractDirectory = extractDirectory; } private boolean isInsideContentRoots(@NotNull File file) { final File canonicalFile; try { canonicalFile = file.getCanonicalFile(); } catch (IOException e) { return false; } Set<File> ancestors = findAllAncestorsIncludingThisFileAsSet(canonicalFile); VirtualFile[] contentRoots = ProjectRootManager.getInstance(myProject).getContentRoots(); for (VirtualFile contentRoot : contentRoots) { try { File canonicalContentRoot = new File(contentRoot.getPath()).getCanonicalFile(); if (ancestors.contains(canonicalContentRoot)) { return true; } } catch (IOException ignored) { } } return false; } private static Set<File> findAllAncestorsIncludingThisFileAsSet(File file) { Set<File> path = Sets.newHashSet(); while (file != null) { path.add(file); file = file.getParentFile(); } return path; } public boolean installCodeAssistance(final List<VirtualFile> extractedAdapterSourceFiles) { return ApplicationManager.getApplication().runWriteAction(new Computable<Boolean>() { @Override public Boolean compute() { boolean insideContentRoots = isInsideContentRoots(myExtractDirectory); if (insideContentRoots) { return true; } return createLibrary(extractedAdapterSourceFiles); } }); } private boolean createLibrary(List<VirtualFile> extractedAdapterSourceFiles) { ScriptingLibraryModel libraryModel = myScriptingLibraryManager.createLibrary( myNewLibraryNameTextField.getText(), VfsUtil.toVirtualFileArray(extractedAdapterSourceFiles), VirtualFile.EMPTY_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY ); boolean success = false; try { if (libraryModel != null) { myScriptingLibraryManager.commitChanges(); success = true; ScriptingLibraryMappings libraryMappings = ServiceManager.getService(myProject, JSLibraryMappings.class); libraryMappings.setMapping(myProject.getBaseDir(), libraryModel); } } catch (Exception ignore) { } if (!success) { Messages.showErrorDialog("Unable to create '" + myNewLibraryNameTextField.getText() + "' JavaScript library", "Adding " + myAssertionFrameworkName + " adapter support for JsTestDriver"); } return success; } }