// 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;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleComponent;
import com.thoughtworks.gauge.connection.GaugeConnection;
import com.thoughtworks.gauge.core.Gauge;
import com.thoughtworks.gauge.core.GaugeExceptionHandler;
import com.thoughtworks.gauge.core.GaugeService;
import com.thoughtworks.gauge.core.GaugeVersion;
import com.thoughtworks.gauge.exception.GaugeNotFoundException;
import com.thoughtworks.gauge.module.GaugeModuleType;
import com.thoughtworks.gauge.module.lib.LibHelperFactory;
import com.thoughtworks.gauge.settings.GaugeSettingsModel;
import com.thoughtworks.gauge.util.GaugeUtil;
import com.thoughtworks.gauge.util.SocketUtils;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import static com.thoughtworks.gauge.GaugeConstant.DAEMONIZE_FLAG;
import static com.thoughtworks.gauge.execution.GaugeRunConfiguration.GAUGE_CUSTOM_CLASSPATH;
import static com.thoughtworks.gauge.util.GaugeUtil.*;
public class GaugeModuleComponent implements ModuleComponent {
public static final String GAUGE_SUPPORTED_VERSION = "0.8.0";
public static final String API_PORT_FLAG = "--api-port";
private final Module module;
private static final Logger LOG = Logger.getInstance("#com.thoughtworks.gauge.GaugeModuleComponent");
public GaugeModuleComponent(Module module) {
this.module = module;
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
Gauge.disposeComponent(module);
}
@NotNull
@Override
public String getComponentName() {
return "GaugeModuleComponent";
}
@Override
public void projectOpened() {
if (GaugeUtil.isGaugeModule(module) && GaugeVersion.isLessThan(GAUGE_SUPPORTED_VERSION)) {
String message = "This plugin version supports Gauge " + GAUGE_SUPPORTED_VERSION + " or above. Please refer <a href=\"https://docs.getgauge.io/installing.html\">this doc</a> to update Gauge.";
Notification notification = new Notification("Gauge", "Version Incompatible", message, NotificationType.ERROR, NotificationListener.URL_OPENING_LISTENER);
Notifications.Bus.notify(notification, module.getProject());
return;
}
new LibHelperFactory().helperFor(module).checkDeps();
}
@Override
public void projectClosed() {
GaugeService gaugeService = Gauge.getGaugeService(module, true);
if (gaugeService != null && gaugeService.getGaugeProcess() != null) {
gaugeService.getGaugeProcess().destroy();
}
}
@Override
public void moduleAdded() {
if (GaugeUtil.isGaugeModule(module)) {
GaugeVersion.updateVersionInfo();
if (GaugeVersion.isLessThan(GAUGE_SUPPORTED_VERSION)) return;
}
projectOpened();
}
/**
* Creates a gauge service for the particular module. GaugeService is used to make api calls to the gauge daemon process.
*
* @param module
* @return
*/
public static GaugeService createGaugeService(Module module) {
int freePortForApi = SocketUtils.findFreePortForApi();
Process gaugeProcess = initializeGaugeProcess(freePortForApi, module);
GaugeConnection gaugeConnection = initializeGaugeConnection(freePortForApi);
GaugeService gaugeService = new GaugeService(gaugeProcess, gaugeConnection);
Gauge.addModule(module, gaugeService);
return gaugeService;
}
private static GaugeConnection initializeGaugeConnection(int apiPort) {
if (apiPort != -1) {
return new GaugeConnection(apiPort);
} else {
return null;
}
}
private static Process initializeGaugeProcess(int apiPort, Module module) {
try {
GaugeSettingsModel settings = getGaugeSettings();
String port = String.valueOf(apiPort);
ProcessBuilder gauge = new ProcessBuilder(settings.getGaugePath(), DAEMONIZE_FLAG, API_PORT_FLAG, port);
GaugeUtil.setGaugeEnvironmentsTo(gauge, settings);
String cp = classpathForModule(module);
LOG.info(String.format("Setting `%s` to `%s`", GAUGE_CUSTOM_CLASSPATH, cp));
gauge.environment().put(GAUGE_CUSTOM_CLASSPATH, cp);
File dir = moduleDir(module);
LOG.info(String.format("Using `%s` as api port to connect to gauge API for project %s", port, dir));
gauge.directory(dir);
Process process = gauge.start();
new GaugeExceptionHandler(process, module.getProject()).start();
return process;
} catch (IOException | GaugeNotFoundException e) {
LOG.error("An error occurred while starting gauge api. \n" + e);
}
return null;
}
public static void makeGaugeModuleType(Module module) {
module.setOption("type", GaugeModuleType.MODULE_TYPE_ID);
}
public static boolean isGaugeModule(Module module) {
return GaugeModuleType.MODULE_TYPE_ID.equals(module.getOptionValue(Module.ELEMENT_TYPE)) || isGaugeProjectDir(moduleDir(module));
}
public static boolean isGaugeProject(Module module) {
return isGaugeProjectDir(moduleDir(module));
}
}