diff --git a/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/DevModeOperations.java b/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/DevModeOperations.java index c83f10cd..b01269ef 100644 --- a/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/DevModeOperations.java +++ b/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/DevModeOperations.java @@ -14,11 +14,13 @@ import java.io.BufferedReader; import java.io.File; +import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -56,6 +58,7 @@ import io.openliberty.tools.eclipse.process.ProcessController; import io.openliberty.tools.eclipse.ui.dashboard.DashboardView; import io.openliberty.tools.eclipse.utils.ErrorHandler; +import io.openliberty.tools.eclipse.utils.Utils; /** * Provides the implementation of all supported dev mode operations. @@ -166,7 +169,7 @@ public static DevModeOperations getInstance() { * @param launch The launch associated with this run. * @param mode The configuration mode. */ - public void start(IProject iProject, String parms, String javaHomePath, ILaunch launch, String mode) { + public void start(IProject iProject, String parms, String javaHomePath, ILaunch launch, String mode, boolean runProjectClean) { if (Trace.isEnabled()) { Trace.getTracer().traceEntry(Trace.TRACE_TOOLS, new Object[] { iProject, parms, javaHomePath, mode }); @@ -230,11 +233,23 @@ public void start(IProject iProject, String parms, String javaHomePath, ILaunch String cmd = ""; if (buildType == Project.BuildType.MAVEN) { - cmd = CommandBuilder.getMavenCommandLine(projectPath, "io.openliberty.tools:liberty-maven-plugin:dev " + startParms, + cmd = CommandBuilder.getMavenCommandLine(projectPath, (runProjectClean == true ? " clean " : "" ) + "io.openliberty.tools:liberty-maven-plugin:dev " + startParms, pathEnv); - } else if (buildType == Project.BuildType.GRADLE) { - cmd = CommandBuilder.getGradleCommandLine(projectPath, "libertyDev " + startParms, pathEnv); - } else { + } else if (buildType == Project.BuildType.GRADLE) { + + if (runProjectClean == true) { + try { + String stopGradleDaemonCmd= CommandBuilder.getGradleCommandLine(projectPath," --stop", pathEnv); + executeCommand(stopGradleDaemonCmd, projectPath); + } catch (IOException | InterruptedException e) { + Logger.logError("An attempt to stop the Gradle daemon failed...."); + } + + } + cmd = CommandBuilder.getGradleCommandLine(projectPath, + (runProjectClean == true ? " clean " : "") + "libertyDev " + startParms, pathEnv); + + } else { throw new Exception("Unexpected project build type: " + buildType + ". Project " + projectName + "does not appear to be a Maven or Gradle built project."); } @@ -274,7 +289,7 @@ public void start(IProject iProject, String parms, String javaHomePath, ILaunch * @param launch The launch associated with this run. * @param mode The configuration mode. */ - public void startInContainer(IProject iProject, String parms, String javaHomePath, ILaunch launch, String mode) { + public void startInContainer(IProject iProject, String parms, String javaHomePath, ILaunch launch, String mode, boolean runProjectClean) { if (Trace.isEnabled()) { Trace.getTracer().traceEntry(Trace.TRACE_TOOLS, new Object[] { iProject, parms, javaHomePath, mode }); @@ -337,11 +352,22 @@ public void startInContainer(IProject iProject, String parms, String javaHomePat // Prepare the Liberty plugin container dev mode command. String cmd = ""; if (buildType == Project.BuildType.MAVEN) { - cmd = CommandBuilder.getMavenCommandLine(projectPath, "io.openliberty.tools:liberty-maven-plugin:devc " + startParms, + cmd = CommandBuilder.getMavenCommandLine(projectPath, (runProjectClean == true ? " clean " : "") + "io.openliberty.tools:liberty-maven-plugin:devc " + startParms, pathEnv); - } else if (buildType == Project.BuildType.GRADLE) { - cmd = CommandBuilder.getGradleCommandLine(projectPath, "libertyDevc " + startParms, pathEnv); - } else { + } else if (buildType == Project.BuildType.GRADLE) { + if (runProjectClean == true) { + try { + + String stopGradleDaemonCmd = CommandBuilder.getGradleCommandLine(projectPath, " --stop", + pathEnv); + executeCommand(stopGradleDaemonCmd, projectPath); + } catch (IOException | InterruptedException e) { + Logger.logError("An attempt to stop the Gradle daemon failed...."); + } + } + cmd = CommandBuilder.getGradleCommandLine(projectPath, + (runProjectClean == true ? " clean " : "") + "libertyDevc " + startParms, pathEnv); + } else { throw new Exception("Unexpected project build type: " + buildType + ". Project " + projectName + "does not appear to be a Maven or Gradle built project."); } @@ -1118,4 +1144,17 @@ public void cancelRunningJobs() { // Cancel will remove job from 'runningJobs' Map runningJobs.keySet().forEach(j -> j.cancel()); } + + + public void executeCommand(String fullCommand, String projectPath) throws IOException, InterruptedException { + // Split the full command into individual arguments + List command = Arrays.asList(fullCommand.trim().split("\\s+")); + + ProcessBuilder builder = new ProcessBuilder(command); + builder.directory(new File(projectPath)); // Set working directory + + Process process = builder.start(); + process.waitFor(); + } + } diff --git a/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/ui/launch/LaunchConfigurationDelegateLauncher.java b/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/ui/launch/LaunchConfigurationDelegateLauncher.java index 4fb2f7b6..21362152 100644 --- a/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/ui/launch/LaunchConfigurationDelegateLauncher.java +++ b/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/ui/launch/LaunchConfigurationDelegateLauncher.java @@ -153,14 +153,15 @@ private void launchDevMode(IProject iProject, ILaunchConfiguration iConfiguratio // Retrieve configuration data. boolean runInContainer = configuration.getAttribute(StartTab.PROJECT_RUN_IN_CONTAINER, false); + boolean runProjectClean = configuration.getAttribute(StartTab.PROJECT_CLEAN, false); String configParms = configuration.getAttribute(StartTab.PROJECT_START_PARM, (String) null); String javaHomePath = JRETab.resolveJavaHome(configuration); // Process the action. if (runInContainer) { - devModeOps.startInContainer(iProject, configParms, javaHomePath, launch, mode); + devModeOps.startInContainer(iProject, configParms, javaHomePath, launch, mode, runProjectClean); } else { - devModeOps.start(iProject, configParms, javaHomePath, launch, mode); + devModeOps.start(iProject, configParms, javaHomePath, launch, mode, runProjectClean); } if (Trace.isEnabled()) { diff --git a/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/ui/launch/StartTab.java b/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/ui/launch/StartTab.java index 0df51592..2439aa61 100644 --- a/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/ui/launch/StartTab.java +++ b/bundles/io.openliberty.tools.eclipse.ui/src/io/openliberty/tools/eclipse/ui/launch/StartTab.java @@ -61,6 +61,9 @@ public class StartTab extends AbstractLaunchConfigurationTab { /** Configuration map key with a value stating whether or not the associated project ran in a container. */ public static final String PROJECT_RUN_IN_CONTAINER = "io.openliberty.tools.eclipse.launch.project.container.run"; + + /** Configuration map key with a value stating whether or not the associated project ran with clean option. */ + public static final String PROJECT_CLEAN = "io.openliberty.tools.eclipse.launch.project.clean"; /** Main preference page ID. */ public static final String MAIN_PREFERENCE_PAGE_ID = "io.openliberty.tools.eclipse.ui.preferences.page"; @@ -84,6 +87,9 @@ public class StartTab extends AbstractLaunchConfigurationTab { /** Holds the run in container check box. */ private Button runInContainerCheckBox; + + /** Holds the project clean check box. */ + private Button projectCleanCheckBox; /** DevModeOperations instance. */ private DevModeOperations devModeOps = DevModeOperations.getInstance(); @@ -112,6 +118,7 @@ public void createControl(Composite parent) { Composite parmsGroupComposite = createGroupComposite(mainComposite, "", 2); createInputParmText(parmsGroupComposite); createRunInContainerButton(parmsGroupComposite); + createProjectCleanButton(parmsGroupComposite); createLabelWithPreferenceLink(mainComposite); } @@ -159,6 +166,9 @@ public void initializeFrom(ILaunchConfiguration configuration) { boolean runInContainer = configuration.getAttribute(PROJECT_RUN_IN_CONTAINER, false); runInContainerCheckBox.setSelection(runInContainer); + + boolean projectClean = configuration.getAttribute(PROJECT_CLEAN, false); + projectCleanCheckBox.setSelection(projectClean); String projectName = configuration.getAttribute(PROJECT_NAME, (String) null); if (projectName == null) { @@ -248,14 +258,18 @@ public void performApply(ILaunchConfigurationWorkingCopy configuration) { String startParamStr = startParmText.getText(); boolean runInContainerBool = runInContainerCheckBox.getSelection(); + + boolean projectCleanBool = projectCleanCheckBox.getSelection(); configuration.setAttribute(PROJECT_RUN_IN_CONTAINER, runInContainerBool); + + configuration.setAttribute(PROJECT_CLEAN, projectCleanBool); configuration.setAttribute(PROJECT_START_PARM, startParamStr); if (Trace.isEnabled()) { Trace.getTracer().trace(Trace.TRACE_UI, "In performApply with project name = " + projectNameLabel.getText() + ", text = " - + startParamStr + ", runInContainer = " + runInContainerBool); + + startParamStr + ", runInContainer = " + runInContainerBool + ", clean project = " + projectCleanBool); } } @@ -408,6 +422,33 @@ public void widgetSelected(SelectionEvent event) { Label emptyColumnLabel = new Label(parent, SWT.NONE); GridDataFactory.swtDefaults().applyTo(emptyColumnLabel); } + + /** + * Creates the button entry that indicates whether or not the project should run with project clean command. + * + * @param parent The parent composite. + */ + private void createProjectCleanButton(Composite parent) { + projectCleanCheckBox = new Button(parent, SWT.CHECK); + projectCleanCheckBox.setText("Clean project"); + projectCleanCheckBox.setSelection(false); + projectCleanCheckBox.setFont(font); + projectCleanCheckBox.addSelectionListener(new SelectionAdapter() { + + /** + * {@inheritDoc} + */ + @Override + public void widgetSelected(SelectionEvent event) { + setDirty(true); + updateLaunchConfigurationDialog(); + } + }); + GridDataFactory.swtDefaults().applyTo(projectCleanCheckBox); + + Label emptyColumnLabel = new Label(parent, SWT.NONE); + GridDataFactory.swtDefaults().applyTo(emptyColumnLabel); + } /** * Returns the default start parameters. diff --git a/tests/META-INF/MANIFEST.MF b/tests/META-INF/MANIFEST.MF index 149e619a..07a32b35 100644 --- a/tests/META-INF/MANIFEST.MF +++ b/tests/META-INF/MANIFEST.MF @@ -7,7 +7,9 @@ Bundle-Version: 25.0.3.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-21 Require-Bundle: junit-jupiter-api, org.eclipse.ui, - org.hamcrest.library + org.hamcrest.library, + org.eclipse.ui.console, + org.eclipse.text Import-Package: io.openliberty.tools.eclipse, io.openliberty.tools.eclipse.debug, io.openliberty.tools.eclipse.ui.dashboard, diff --git a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotGradleTest.java b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotGradleTest.java index 60993500..456d78b1 100644 --- a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotGradleTest.java +++ b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotGradleTest.java @@ -14,6 +14,7 @@ import static io.openliberty.tools.eclipse.test.it.utils.MagicWidgetFinder.context; import static io.openliberty.tools.eclipse.test.it.utils.MagicWidgetFinder.go; +import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.checkRunCleanProjectCheckBox; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.deleteLibertyToolsRunConfigEntriesFromAppRunAs; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.enableLibertyTools; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.getAppDebugAsMenu; @@ -24,6 +25,7 @@ import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.getDefaultSourceLookupTreeItemNoBot; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.getLibertyTreeItem; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.getLibertyTreeItemNoBot; +import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.getRunConfigurationsShell; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.launchCustomDebugFromDashboard; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.launchCustomRunFromDashboard; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.launchDashboardAction; @@ -487,6 +489,12 @@ public void testDashboardActions() { // Start dev mode. launchDashboardAction(GRADLE_APP_NAME, DashboardView.APP_MENU_ACTION_START); + try { + Thread.sleep(10000); // sleep for 1 min + } catch (InterruptedException e) { + // Handle interruption + Thread.currentThread().interrupt(); + } // Validate application is up and running. LibertyPluginTestUtils.validateApplicationOutcome(GRADLE_APP_NAME, true, testAppPath + "/build"); @@ -506,7 +514,7 @@ public void testDashboardActions() { } finally { // Stop dev mode. launchDashboardAction(GRADLE_APP_NAME, DashboardView.APP_MENU_ACTION_STOP); - + // Validate application stopped. LibertyPluginTestUtils.validateLibertyServerStopped(testAppPath + "/build"); @@ -666,6 +674,51 @@ public void testStartWithCustomRunAsConfig() { LibertyPluginTestUtils.validateLibertyServerStopped(testAppPath + "/build"); } } + + /** + * Tests the Clean project option provided under liberty run configuration option. Test will check + * if the application has started and also will check for the presence of project clean and dev mode commands + * from the console tab + */ + + @Test + public void testRunCleanProjectCheckbox() { + + // Delete any previously created configs. + deleteLibertyToolsRunConfigEntriesFromAppRunAs(GRADLE_APP_NAME); + + // Launch "Run Configurations" window and check "Clean project" + launchDashboardAction(GRADLE_APP_NAME, DashboardView.APP_MENU_ACTION_START_CONFIG); + Shell shell = getRunConfigurationsShell(); + checkRunCleanProjectCheckBox(shell, GRADLE_APP_NAME); + + // No need to run here. Just Apply and Close. + go("Apply", shell); + go("Close", shell); + + // Start dev mode. This should start locally. + launchDashboardAction(GRADLE_APP_NAME, DashboardView.APP_MENU_ACTION_START); + try { + Thread.sleep(10000); // sleep for 1 min + } catch (InterruptedException e) { + // Handle interruption + Thread.currentThread().interrupt(); + } + + LibertyPluginTestUtils.validateApplicationOutcome(GRADLE_APP_NAME, true, testAppPath + "/build"); + //Reads the text from the console output tab + String consoleText =LibertyPluginTestUtils.getConsoleOutput(); + Assertions.assertTrue(consoleText.contains("clean libertyDev"),"Console text should contain 'clean libertyDev'"); + // If there are issues with the workspace, close the error dialog. + pressWorkspaceErrorDialogProceedButton(bot); + + // Stop dev mode. + launchDashboardAction(GRADLE_APP_NAME, DashboardView.APP_MENU_ACTION_STOP); + + // Validate application stopped. + LibertyPluginTestUtils.validateLibertyServerStopped( testAppPath + "/build"); + + } /** * Tests the start, run tests, view test report, and stop run as shortcut actions. @@ -806,7 +859,6 @@ public void testDefaultJRECompliance() { Assertions.assertTrue(comboJREBox.isEnabled(), () -> "The JRE tab box showing Java installation \" + buildPathJRE + \" is not selected."); } finally { - go("Apply", configShell); go("Close", configShell); } } diff --git a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenTest.java b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenTest.java index 69632149..ee41c639 100644 --- a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenTest.java +++ b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/LibertyPluginSWTBotMavenTest.java @@ -15,6 +15,7 @@ import static io.openliberty.tools.eclipse.test.it.utils.MagicWidgetFinder.context; import static io.openliberty.tools.eclipse.test.it.utils.MagicWidgetFinder.go; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.checkRunInContainerCheckBox; +import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.checkRunCleanProjectCheckBox; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.deleteLibertyToolsRunConfigEntriesFromAppRunAs; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.enableLibertyTools; import static io.openliberty.tools.eclipse.test.it.utils.SWTBotPluginOperations.getAppDebugAsMenu; @@ -855,7 +856,6 @@ public void testDefaultJRECompliance() { Assertions.assertTrue(comboJREBox.isEnabled(), () -> "The JRE tab box showing Java installation \" + buildPathJRE + \" is not selected."); } finally { - go("Apply", configShell); go("Close", configShell); } } @@ -965,6 +965,46 @@ public void testLaunchConfigurationMatching() { } + /** + * Tests the Clean project option provided under liberty run configuration option. Test will check + * if the application has started and also will check for the presence of project clean and dev mode commands + * from the console tab + */ + + @Test + public void testRunCleanProjectCheckbox() { + + // Delete any previously created configs. + deleteLibertyToolsRunConfigEntriesFromAppRunAs(MVN_APP_NAME); + + // Launch "Run Configurations" window and check "Clean project" + launchDashboardAction(MVN_APP_NAME, DashboardView.APP_MENU_ACTION_START_CONFIG); + Shell shell = getRunConfigurationsShell(); + checkRunCleanProjectCheckBox(shell, MVN_APP_NAME); + + // No need to run here. Just Apply and Close. + go("Apply", shell); + go("Close", shell); + + // Start dev mode. This should start locally. + launchDashboardAction(MVN_APP_NAME, DashboardView.APP_MENU_ACTION_START); + + LibertyPluginTestUtils.validateApplicationOutcome(MVN_APP_NAME, true, projectPath.toAbsolutePath().toString() + "/target/liberty"); + //Reads the text from the console output tab + String consoleText =LibertyPluginTestUtils.getConsoleOutput(); + Assertions.assertTrue(consoleText.contains("clean io.openliberty.tools:liberty-maven-plugin:dev"), + "Console text should contain 'clean io.openliberty.tools:liberty-maven-plugin:dev'"); + // If there are issues with the workspace, close the error dialog. + pressWorkspaceErrorDialogProceedButton(bot); + + // Stop dev mode. + launchDashboardAction(MVN_APP_NAME, DashboardView.APP_MENU_ACTION_STOP); + + // Validate application stopped. + LibertyPluginTestUtils.validateLibertyServerStopped(projectPath.toAbsolutePath().toString() + "/target/liberty"); + + } + /** * Tests that the correct dependency projects are added to the debug source lookup list */ diff --git a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/LibertyPluginTestUtils.java b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/LibertyPluginTestUtils.java index f1247d2c..52e24dc1 100644 --- a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/LibertyPluginTestUtils.java +++ b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/LibertyPluginTestUtils.java @@ -14,6 +14,11 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; +import org.eclipse.ui.console.ConsolePlugin; +import org.eclipse.ui.console.IConsole; +import org.eclipse.ui.console.IConsoleManager; +import org.eclipse.ui.console.TextConsole; + import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -266,6 +271,29 @@ public static void validateLibertyToolsPreferencesSet() { assertNotNull(preferences, "preferences file not found for Liberty Tools"); } } + + + /** + * Reads and returns the text from the console output tab + * @return + */ + public static String getConsoleOutput() { + IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager(); + IConsole[] consoles = consoleManager.getConsoles(); + StringBuilder result = new StringBuilder(); + + // Iterate through each console + for (IConsole console : consoles) { + if (console instanceof TextConsole) { + TextConsole textConsole = (TextConsole) console; + // Append the console output to the result + result.append(textConsole.getDocument().get()); + } + } + + // Return the concatenated result from all text consoles + return result.toString(); + } /** * Returns true or false depending on if the input text is found in the target file diff --git a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/SWTBotPluginOperations.java b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/SWTBotPluginOperations.java index c37a9de8..71e5c214 100644 --- a/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/SWTBotPluginOperations.java +++ b/tests/src/main/java/io/openliberty/tools/eclipse/test/it/utils/SWTBotPluginOperations.java @@ -658,6 +658,24 @@ public static void checkRunInContainerCheckBox(Shell shell, String runDebugConfi go(button); } + + + /** + * Selects the project clean option under liberty in run configurations + * @param shell + * @param runDebugConfigName + */ + public static void checkRunCleanProjectCheckBox(Shell shell, String runDebugConfigName) { + + Object libertyConfigTree = getLibertyTreeItem(shell); + + Object appConfigEntry = find(runDebugConfigName, libertyConfigTree, + Option.factory().useContains(true).widgetClass(TreeItem.class).build()); + go(appConfigEntry); + Object button = find("Clean project", appConfigEntry, Option.factory().widgetClass(Button.class).build()); + + go(button); + } public static Object getAppInPackageExplorerTree(String appName) { openJavaPerspectiveViaMenu();