// Copyright 2015 ThoughtWorks, Inc. // This file is part of getgauge/Intellij-plugin. // getgauge/Intellij-plugin is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // getgauge/Intellij-plugin is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with getgauge/Intellij-plugin. If not, see <http://www.gnu.org/licenses/>. package com.thoughtworks.gauge.module.lib; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.CompilerModuleExtension; import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.thoughtworks.gauge.connection.GaugeConnection; import com.thoughtworks.gauge.GaugeModuleComponent; import com.thoughtworks.gauge.PluginNotInstalledException; import com.thoughtworks.gauge.core.Gauge; import com.thoughtworks.gauge.core.GaugeService; import java.io.File; import java.io.IOException; import static com.intellij.openapi.roots.OrderRootType.CLASSES; import static com.thoughtworks.gauge.util.GaugeUtil.moduleDir; import static com.thoughtworks.gauge.util.GaugeUtil.moduleDirPath; public class GaugeLibHelper extends AbstractLibHelper { public static final String PROJECT_LIB = "project-lib"; public static final String GAUGE_LIB = "gauge-lib"; public static final String JAVA = "java"; private static final String SRC_DIR = new File(new File("src", "test"), JAVA).getPath(); public static final String LIBS = "libs"; public GaugeLibHelper(Module module) { super(module); } public void checkDeps() { final ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(getModule()).getModifiableModel(); if (!gaugeJavaLibIsAdded(modifiableModel)) { addGaugeJavaLib(modifiableModel); } else { updateGaugeJavaLibIfNeeded(modifiableModel); } addProjectLibIfNeeded(modifiableModel); checkProjectSourceAndOutputDirectory(modifiableModel); ApplicationManager.getApplication().runWriteAction(modifiableModel::commit); } private void checkProjectSourceAndOutputDirectory(ModifiableRootModel modifiableModel) { VirtualFile[] sourceRoots = modifiableModel.getSourceRoots(); if (sourceRoots.length < 1) { ContentEntry contentEntry = modifiableModel.addContentEntry(modifiableModel.getProject().getBaseDir()); VirtualFile srcPath = srcPath(modifiableModel); if (srcPath != null) { contentEntry.addSourceFolder(srcPath, false); } CompilerModuleExtension compilerModuleExtension = modifiableModel.getModuleExtension(CompilerModuleExtension.class); compilerModuleExtension.setCompilerOutputPath(outputPath(modifiableModel.getModule())); compilerModuleExtension.setCompilerOutputPathForTests(testOutputPath(modifiableModel.getModule())); compilerModuleExtension.inheritCompilerOutputPath(false); compilerModuleExtension.commit(); } } private VirtualFile testOutputPath(Module module) { File outputDir = new File(String.format("%s%sout%stest%s%s", moduleDirPath(module), File.separator, File.separator, File.separator, module.getName())); outputDir.mkdirs(); return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(outputDir); } private VirtualFile outputPath(Module module) { File outputDir = new File(String.format("%s%sout%sproduction%s%s", moduleDirPath(module), File.separator, File.separator, File.separator, module.getName())); outputDir.mkdirs(); return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(outputDir); } private VirtualFile srcPath(ModifiableRootModel modifiableModel) { return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(moduleDir(modifiableModel.getModule()), SRC_DIR)); } private void addProjectLibIfNeeded(ModifiableRootModel model) { Library library = model.getModuleLibraryTable().getLibraryByName(PROJECT_LIB); if (library == null) { addProjectLib(model); } } private void updateGaugeJavaLibIfNeeded(ModifiableRootModel model) { LibraryTable libraryTable = model.getModuleLibraryTable(); Library library = libraryTable.getLibraryByName(GAUGE_LIB); ProjectLib latestGaugeLib = gaugeLib(model.getModule()); updateLibrary(library, latestGaugeLib); } private void updateLibrary(Library library, ProjectLib newLib) { VirtualFile lib = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(newLib.getDir()); Library.ModifiableModel model = library.getModifiableModel(); if (lib != null) { model.removeRoot(getClassesRootFrom(model), CLASSES); model.addJarDirectory(lib, true, CLASSES); } model.commit(); } private String getClassesRootFrom(Library.ModifiableModel model) { return model.getUrls(CLASSES)[0]; } private boolean gaugeJavaLibIsAdded(ModifiableRootModel model) { Library library = model.getModuleLibraryTable().getLibraryByName(GAUGE_LIB); return !(library == null); } private void addGaugeJavaLib(ModifiableRootModel modifiableRootModel) { Module module = modifiableRootModel.getModule(); ProjectLib gaugeLib = gaugeLib(module); if (gaugeLib != null) { addLib(gaugeLib, modifiableRootModel); } } private void addProjectLib(ModifiableRootModel modifiableRootModel) { addLib(projectLib(modifiableRootModel.getModule()), modifiableRootModel); } private void addLib(ProjectLib lib, ModifiableRootModel modifiableRootModel) { final Library library = modifiableRootModel.getModuleLibraryTable().createLibrary(lib.getLibName()); final VirtualFile libDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(lib.getDir()); if (libDir != null) { final Library.ModifiableModel libModel = library.getModifiableModel(); libModel.addJarDirectory(libDir, true); libModel.commit(); } } private ProjectLib projectLib(Module module) { return new ProjectLib(PROJECT_LIB, new File(moduleDir(module), LIBS)); } private ProjectLib gaugeLib(Module module) { String libRoot; try { GaugeService gaugeService = Gauge.getGaugeService(module, true); if (gaugeService == null) { gaugeService = GaugeModuleComponent.createGaugeService(module); } GaugeConnection gaugeConnection = gaugeService.getGaugeConnection(); if (gaugeConnection == null) { throw new IOException("Gauge api connection not established"); } libRoot = gaugeConnection.getLibPath("java"); } catch (IOException e) { System.err.println("Could not add gauge lib, add it manually: " + e.getMessage()); return null; } catch (PluginNotInstalledException e) { throw new RuntimeException("Gauge " + JAVA + " plugin is not installed."); } return new ProjectLib(GAUGE_LIB, new File(libRoot)); } private class ProjectLib { private String libName; public File dir; public ProjectLib(String libName, File dir) { this.libName = libName; this.dir = dir; } public String getLibName() { return libName; } public File getDir() { return dir; } } }