From dc0035d68a1f11cf2c302e991dd2caab547a2da7 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 7 Jan 2025 19:13:04 -0500 Subject: [PATCH 01/12] Refactor Liberty module detection into LibertyModules class Signed-off-by: Paul Gooderham --- .../tools/intellij/LibertyExplorer.java | 126 ++++-------------- .../tools/intellij/LibertyModules.java | 101 +++++++++++++- .../LibertyRunConfiguration.java | 4 +- 3 files changed, 125 insertions(+), 106 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java b/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java index fbec073db..2453f0a28 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2024 IBM Corporation. + * Copyright (c) 2020, 2025 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -20,7 +20,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DoubleClickListener; import com.intellij.ui.PopupHandler; import com.intellij.ui.components.JBScrollPane; @@ -30,18 +29,15 @@ import io.openliberty.tools.intellij.actions.LibertyToolbarActionGroup; import io.openliberty.tools.intellij.util.*; import org.jetbrains.annotations.NotNull; -import org.xml.sax.SAXException; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreePath; -import javax.xml.parsers.ParserConfigurationException; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -106,115 +102,39 @@ public static ActionToolbar buildActionToolbar(Tree tree) { * @return Tree object of all valid Liberty Gradle and Liberty Maven projects */ public static Tree buildTree(Project project, Color backgroundColor) { - LibertyModules libertyModules = LibertyModules.getInstance(); - // clear all stored Liberty modules for current project - libertyModules.removeForProject(project); - DefaultMutableTreeNode top = new DefaultMutableTreeNode("Root node"); - - ArrayList mavenBuildFiles; - ArrayList gradleBuildFiles; - HashMap> map = new HashMap<>(); - try { - mavenBuildFiles = LibertyProjectUtil.getMavenBuildFiles(project); - gradleBuildFiles = LibertyProjectUtil.getGradleBuildFiles(project); - } catch (IOException | SAXException | ParserConfigurationException e) { - LOGGER.warn("Could not find Liberty Maven or Gradle projects in workspace", - e); + LibertyModules libertyModules = LibertyModules.getInstance().scanLibertyModules(project); + if (libertyModules == null) { return null; } + DefaultMutableTreeNode top = new DefaultMutableTreeNode("Root node"); + HashMap> projectMap = new HashMap<>(); - if (mavenBuildFiles.isEmpty() && gradleBuildFiles.isEmpty()) { - return null; - } - - for (BuildFile buildFile : mavenBuildFiles) { - // create a new Liberty project - VirtualFile virtualFile = buildFile.getBuildFile(); - String projectName = null; - if (virtualFile == null) { - LOGGER.error(String.format("Could not resolve current Maven project %s", virtualFile)); - break; - } - LibertyModuleNode node; - try { - projectName = LibertyMavenUtil.getProjectNameFromPom(virtualFile); - } catch (Exception e) { - LOGGER.warn(String.format("Could not resolve project name from build file: %s", virtualFile), e); - } - if (projectName == null) { - if (virtualFile.getParent() != null) { - projectName = virtualFile.getParent().getName(); - } else { - projectName = project.getName(); - } - } - - boolean validContainerVersion = buildFile.isValidContainerVersion(); - LibertyModule module = libertyModules.addLibertyModule(new LibertyModule(project, virtualFile, projectName, Constants.LIBERTY_MAVEN_PROJECT, validContainerVersion)); - node = new LibertyModuleNode(module); + for (LibertyModule libertyModule : libertyModules.getLibertyModules(project)) { + LibertyModuleNode node = new LibertyModuleNode(libertyModule); top.add(node); ArrayList settings = new ArrayList(); - settings.add(virtualFile); - settings.add(Constants.LIBERTY_MAVEN_PROJECT); - map.put(projectName, settings); + settings.add(libertyModule.getBuildFile()); + settings.add(libertyModule.getProjectType()); + projectMap.put(libertyModule.getName(), settings); // ordered to align with IntelliJ's right-click menu - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_START, module)); - // check if Liberty Maven Plugin is 3.3-M1+ + node.add(new LibertyActionNode(Constants.LIBERTY_DEV_START, libertyModule)); + // check if Liberty Maven Plugin is 3.3-M1+ or Liberty Gradle Plugin is 3.1-M1+ // if version is not specified in pom, assume latest version as downloaded from maven central + boolean validContainerVersion = libertyModule.isValidContainerVersion(); if (validContainerVersion) { - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_START_CONTAINER, module)); + node.add(new LibertyActionNode(Constants.LIBERTY_DEV_START_CONTAINER, libertyModule)); } - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_CUSTOM_START, module)); - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_STOP, module)); - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_TESTS, module)); - node.add(new LibertyActionNode(Constants.VIEW_INTEGRATION_TEST_REPORT, module)); - node.add(new LibertyActionNode(Constants.VIEW_UNIT_TEST_REPORT, module)); - } - - for (BuildFile buildFile : gradleBuildFiles) { - VirtualFile virtualFile = buildFile.getBuildFile(); - String projectName = null; - if (virtualFile == null) { - LOGGER.error(String.format("Could not resolve current Gradle project %s", buildFile)); - break; - } - LibertyModuleNode node; - try { - projectName = LibertyGradleUtil.getProjectName(virtualFile); - } catch (Exception e) { - LOGGER.warn(String.format("Could not resolve project name for project %s", virtualFile), e); - } - if (projectName == null) { - if (virtualFile.getParent() != null) { - projectName = virtualFile.getParent().getName(); - } else { - projectName = project.getName(); - } - } - - boolean validContainerVersion = buildFile.isValidContainerVersion(); - LibertyModule module = libertyModules.addLibertyModule(new LibertyModule(project, virtualFile, projectName, Constants.LIBERTY_GRADLE_PROJECT, validContainerVersion)); - node = new LibertyModuleNode(module); - - top.add(node); - ArrayList settings = new ArrayList(); - settings.add(virtualFile); - settings.add(Constants.LIBERTY_GRADLE_PROJECT); - map.put(projectName, settings); - - // ordered to align with IntelliJ's right-click menu - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_START, module)); - // check if Liberty Gradle Plugin is 3.1-M1+ - // TODO: handle version specified in a gradle.settings file - if (buildFile.isValidContainerVersion()) { - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_START_CONTAINER, module)); + node.add(new LibertyActionNode(Constants.LIBERTY_DEV_CUSTOM_START, libertyModule)); + node.add(new LibertyActionNode(Constants.LIBERTY_DEV_STOP, libertyModule)); + node.add(new LibertyActionNode(Constants.LIBERTY_DEV_TESTS, libertyModule)); + if (libertyModule.getProjectType().equals(Constants.LIBERTY_MAVEN_PROJECT)) { + node.add(new LibertyActionNode(Constants.VIEW_INTEGRATION_TEST_REPORT, libertyModule)); + node.add(new LibertyActionNode(Constants.VIEW_UNIT_TEST_REPORT, libertyModule)); + } else if (libertyModule.getProjectType().equals(Constants.LIBERTY_GRADLE_PROJECT)) { + node.add(new LibertyActionNode(Constants.VIEW_GRADLE_TEST_REPORT, libertyModule)); } - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_CUSTOM_START, module)); - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_STOP, module)); - node.add(new LibertyActionNode(Constants.LIBERTY_DEV_TESTS, module)); - node.add(new LibertyActionNode(Constants.VIEW_GRADLE_TEST_REPORT, module)); } Tree tree = new Tree(top); @@ -224,7 +144,7 @@ public static Tree buildTree(Project project, Color backgroundColor) { DataManager.registerDataProvider(tree, newDataProvider); TreeDataProvider treeDataProvider = (TreeDataProvider) DataManager.getDataProvider(tree); - treeDataProvider.setProjectMap(map); + treeDataProvider.setProjectMap(projectMap); tree.addTreeSelectionListener(e -> { Object node = e.getPath().getLastPathComponent(); diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java index 3624bbe4b..a79da6e11 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022 IBM Corporation. + * Copyright (c) 2022, 2025 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -10,10 +10,15 @@ package io.openliberty.tools.intellij; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import io.openliberty.tools.intellij.util.*; +import org.xml.sax.SAXException; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; import java.nio.file.Paths; import java.util.*; @@ -21,6 +26,7 @@ * Singleton to save the Liberty modules in the open project */ public class LibertyModules { + private final static Logger LOGGER = Logger.getInstance(LibertyModules.class); private static LibertyModules instance = null; @@ -38,6 +44,81 @@ public synchronized static LibertyModules getInstance() { return instance; } + /** + * Scan the project for the modules that are Liberty apps. + * @return null if there are no Liberty modules + */ + public LibertyModules scanLibertyModules(Project project) { + synchronized (libertyModules) { + removeForProject(project); + ArrayList mavenBuildFiles; + ArrayList gradleBuildFiles; + HashMap> projectMap = new HashMap<>(); + try { + mavenBuildFiles = LibertyProjectUtil.getMavenBuildFiles(project); + gradleBuildFiles = LibertyProjectUtil.getGradleBuildFiles(project); + } catch (IOException | SAXException | ParserConfigurationException e) { + LOGGER.warn("Could not find Liberty Maven or Gradle projects in workspace", e); + return null; + } + + if (mavenBuildFiles.isEmpty() && gradleBuildFiles.isEmpty()) { + return null; + } + + for (BuildFile buildFile : mavenBuildFiles) { + // create a new Liberty project + VirtualFile virtualFile = buildFile.getBuildFile(); + String projectName = null; + if (virtualFile == null) { + LOGGER.error(String.format("Could not resolve current Maven project %s", virtualFile)); + break; + } + try { + projectName = LibertyMavenUtil.getProjectNameFromPom(virtualFile); + } catch (Exception e) { + LOGGER.warn(String.format("Could not resolve project name from build file: %s", virtualFile), e); + } + if (projectName == null) { + if (virtualFile.getParent() != null) { + projectName = virtualFile.getParent().getName(); + } else { + projectName = project.getName(); + } + } + + boolean validContainerVersion = buildFile.isValidContainerVersion(); + addLibertyModule(new LibertyModule(project, virtualFile, projectName, Constants.LIBERTY_MAVEN_PROJECT, validContainerVersion)); + } + + for (BuildFile buildFile : gradleBuildFiles) { + VirtualFile virtualFile = buildFile.getBuildFile(); + String projectName = null; + if (virtualFile == null) { + LOGGER.error(String.format("Could not resolve current Gradle project %s", buildFile)); + break; + } + LibertyModuleNode node; + try { + projectName = LibertyGradleUtil.getProjectName(virtualFile); + } catch (Exception e) { + LOGGER.warn(String.format("Could not resolve project name for project %s", virtualFile), e); + } + if (projectName == null) { + if (virtualFile.getParent() != null) { + projectName = virtualFile.getParent().getName(); + } else { + projectName = project.getName(); + } + } + + boolean validContainerVersion = buildFile.isValidContainerVersion(); + addLibertyModule(new LibertyModule(project, virtualFile, projectName, Constants.LIBERTY_GRADLE_PROJECT, validContainerVersion)); + } + } + return getInstance(); + } + /** * Add tracked Liberty project to workspace, update project, * projectType, name and validContainerVersion if already tracked. @@ -101,6 +182,24 @@ public List getLibertyBuildFilesAsString(Project project) { return sBuildFiles; } + /** + * Returns all Liberty modules for the given project + * + * @param project + * @return Liberty modules for the given project + */ + public List getLibertyModules(Project project) { + ArrayList supportedLibertyModules = new ArrayList<>(); + synchronized (libertyModules) { + libertyModules.values().forEach(libertyModule -> { + if (project.equals(libertyModule.getProject())) { + supportedLibertyModules.add(libertyModule); + } + }); + } + return supportedLibertyModules; + } + /** * Returns all Liberty modules with the supported project type(s) for the given project * ex. all Liberty Maven projects diff --git a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java index ae636f75b..b59364c82 100644 --- a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java +++ b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022, 2024 IBM Corporation. + * Copyright (c) 2022, 2025 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -39,7 +39,6 @@ public class LibertyRunConfiguration extends ModuleBasedConfiguration getConfigurationEditor() { @Nullable @Override public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws ExecutionException { + LibertyModule libertyModule; try { libertyModule = libertyModules.getLibertyProjectFromString(getBuildFile()); } catch (NullPointerException e) { From a8e236bdf8d84a917ca35d4096236a38dc0e1a1d Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 7 Jan 2025 21:12:07 -0500 Subject: [PATCH 02/12] Scan for Liberty modules in the Liberty run configuration constructor to avoid NPE Signed-off-by: Paul Gooderham --- .../LibertyRunConfiguration.java | 2 +- .../intellij/util/LibertyProjectUtil.java | 60 +++++++++++++------ 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java index b59364c82..2ba4e1886 100644 --- a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java +++ b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java @@ -44,7 +44,7 @@ public class LibertyRunConfiguration extends ModuleBasedConfiguration getBuildFiles(Project project, String buildFileType, BuildFileFilter filter) throws ParserConfigurationException, SAXException, IOException { ArrayList buildFiles = new ArrayList(); if (buildFileType.equals(Constants.LIBERTY_MAVEN_PROJECT)) { - Collection mavenFiles = FilenameIndex.getVirtualFilesByName("pom.xml", GlobalSearchScope.projectScope(project)); - for (VirtualFile mavenFile : mavenFiles) { - BuildFile buildFile = LibertyMavenUtil.validPom(mavenFile); - // check if valid pom.xml, or if part of Liberty project - if (filter.matches(project, buildFile, mavenFile)) { - buildFile.setBuildFile(mavenFile); - buildFiles.add(buildFile); + Collection mavenFiles = readIndex(project, "pom.xml"); + if (mavenFiles != null) { + for (VirtualFile mavenFile : mavenFiles) { + BuildFile buildFile = LibertyMavenUtil.validPom(mavenFile); + // check if valid pom.xml, or if part of Liberty project + if (filter.matches(project, buildFile, mavenFile)) { + buildFile.setBuildFile(mavenFile); + buildFiles.add(buildFile); + } } } } else if (buildFileType.equals(Constants.LIBERTY_GRADLE_PROJECT)) { - Collection gradleFiles = FilenameIndex.getVirtualFilesByName("build.gradle", GlobalSearchScope.projectScope(project)); - for (VirtualFile gradleFile : gradleFiles) { - try { - BuildFile buildFile = LibertyGradleUtil.validBuildGradle(gradleFile); - // check if valid build.gradle, or if part of Liberty project - if (filter.matches(project, buildFile, gradleFile)) { - buildFile.setBuildFile(gradleFile); - buildFiles.add(buildFile); + Collection gradleFiles = readIndex(project, "build.gradle"); + if (gradleFiles != null) { + for (VirtualFile gradleFile : gradleFiles) { + try { + BuildFile buildFile = LibertyGradleUtil.validBuildGradle(gradleFile); + // check if valid build.gradle, or if part of Liberty project + if (filter.matches(project, buildFile, gradleFile)) { + buildFile.setBuildFile(gradleFile); + buildFiles.add(buildFile); + } + } catch (Exception e) { + LOGGER.error(String.format("Error parsing build.gradle %s", gradleFile), e.getMessage()); } - } catch (Exception e) { - LOGGER.error(String.format("Error parsing build.gradle %s", gradleFile), e.getMessage()); } } } return buildFiles; } + // Wrap the search for files in a executeOnPooledThread() method to handle the slow operations on EDT issue + // and in a runReadAction() to handle the read action required problem. + private static Collection readIndex(Project project, String name) { + try { + Computable> virtualFilesComputation = () -> FilenameIndex.getVirtualFilesByName(name, GlobalSearchScope.projectScope(project)); + Callable> readAction = () -> ApplicationManager.getApplication().runReadAction(virtualFilesComputation); + Future> filesFuture = ApplicationManager.getApplication().executeOnPooledThread(readAction); + return filesFuture.get(); + } catch (ExecutionException | InterruptedException e) { + return null; + } + } + /** * * @param buildFile maven or gradle build file in the form of PsiFile From cf9d63b8331c1ae90443ed5653a7ec709244d256 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 8 Jan 2025 18:09:27 -0500 Subject: [PATCH 03/12] Document project type in BuildFile and validate the value Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/intellij/util/BuildFile.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/util/BuildFile.java b/src/main/java/io/openliberty/tools/intellij/util/BuildFile.java index c23e667d6..9e3a3294d 100644 --- a/src/main/java/io/openliberty/tools/intellij/util/BuildFile.java +++ b/src/main/java/io/openliberty/tools/intellij/util/BuildFile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2024 IBM Corporation. + * Copyright (c) 2020, 2025 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -25,7 +25,14 @@ public String getProjectType() { return projectType; } + /** + * Liberty project type must be Gradle or Maven. + * @param projectType + */ public void setProjectType(String projectType) { + if (!Constants.LIBERTY_GRADLE_PROJECT.equals(projectType) && !Constants.LIBERTY_MAVEN_PROJECT.equals(projectType)) { + throw new IllegalArgumentException("Only Gradle and Maven project types are supported: " + projectType); + } this.projectType = projectType; } @@ -58,6 +65,4 @@ public String getProjectName() { public void setProjectName(String projectName) { this.projectName = projectName; } - - } From 77791110574dbd70ae5fa84132b0e9026693c7ba Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 8 Jan 2025 18:39:11 -0500 Subject: [PATCH 04/12] When scanning for Liberty modules handle Maven and Gradle in one loop for simplicity Signed-off-by: Paul Gooderham --- .../tools/intellij/LibertyExplorer.java | 2 +- .../tools/intellij/LibertyModules.java | 60 +++++++------------ 2 files changed, 22 insertions(+), 40 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java b/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java index 2453f0a28..123167e8f 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java @@ -103,7 +103,7 @@ public static ActionToolbar buildActionToolbar(Tree tree) { */ public static Tree buildTree(Project project, Color backgroundColor) { LibertyModules libertyModules = LibertyModules.getInstance().scanLibertyModules(project); - if (libertyModules == null) { + if (libertyModules.isEmpty()) { return null; } DefaultMutableTreeNode top = new DefaultMutableTreeNode("Root node"); diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java index a79da6e11..adc8144a8 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java @@ -44,65 +44,47 @@ public synchronized static LibertyModules getInstance() { return instance; } + public boolean isEmpty() { + return libertyModules.isEmpty(); + } /** * Scan the project for the modules that are Liberty apps. * @return null if there are no Liberty modules */ public LibertyModules scanLibertyModules(Project project) { synchronized (libertyModules) { - removeForProject(project); - ArrayList mavenBuildFiles; - ArrayList gradleBuildFiles; - HashMap> projectMap = new HashMap<>(); + removeForProject(project); // remove previous data, if any + + ArrayList buildFiles = new ArrayList<>(); try { - mavenBuildFiles = LibertyProjectUtil.getMavenBuildFiles(project); - gradleBuildFiles = LibertyProjectUtil.getGradleBuildFiles(project); + buildFiles.addAll(LibertyProjectUtil.getMavenBuildFiles(project)); + buildFiles.addAll(LibertyProjectUtil.getGradleBuildFiles(project)); } catch (IOException | SAXException | ParserConfigurationException e) { LOGGER.warn("Could not find Liberty Maven or Gradle projects in workspace", e); return null; } - if (mavenBuildFiles.isEmpty() && gradleBuildFiles.isEmpty()) { - return null; - } - - for (BuildFile buildFile : mavenBuildFiles) { - // create a new Liberty project + for (BuildFile buildFile : buildFiles) { + // create a new Liberty Module object for this project VirtualFile virtualFile = buildFile.getBuildFile(); String projectName = null; if (virtualFile == null) { - LOGGER.error(String.format("Could not resolve current Maven project %s", virtualFile)); + LOGGER.error(String.format("Could not resolve current project %s", virtualFile)); break; } - try { - projectName = LibertyMavenUtil.getProjectNameFromPom(virtualFile); - } catch (Exception e) { - LOGGER.warn(String.format("Could not resolve project name from build file: %s", virtualFile), e); + if (virtualFile.getName().equals("pom.xml")) { + buildFile.setProjectType(Constants.LIBERTY_MAVEN_PROJECT); + } else { + buildFile.setProjectType(Constants.LIBERTY_GRADLE_PROJECT); } - if (projectName == null) { - if (virtualFile.getParent() != null) { - projectName = virtualFile.getParent().getName(); + try { + if (buildFile.getProjectType().equals(Constants.LIBERTY_MAVEN_PROJECT)) { + projectName = LibertyMavenUtil.getProjectNameFromPom(virtualFile); } else { - projectName = project.getName(); + projectName = LibertyGradleUtil.getProjectName(virtualFile); } - } - - boolean validContainerVersion = buildFile.isValidContainerVersion(); - addLibertyModule(new LibertyModule(project, virtualFile, projectName, Constants.LIBERTY_MAVEN_PROJECT, validContainerVersion)); - } - - for (BuildFile buildFile : gradleBuildFiles) { - VirtualFile virtualFile = buildFile.getBuildFile(); - String projectName = null; - if (virtualFile == null) { - LOGGER.error(String.format("Could not resolve current Gradle project %s", buildFile)); - break; - } - LibertyModuleNode node; - try { - projectName = LibertyGradleUtil.getProjectName(virtualFile); } catch (Exception e) { - LOGGER.warn(String.format("Could not resolve project name for project %s", virtualFile), e); + LOGGER.warn(String.format("Could not resolve project name from build file: %s", virtualFile), e); } if (projectName == null) { if (virtualFile.getParent() != null) { @@ -113,7 +95,7 @@ public LibertyModules scanLibertyModules(Project project) { } boolean validContainerVersion = buildFile.isValidContainerVersion(); - addLibertyModule(new LibertyModule(project, virtualFile, projectName, Constants.LIBERTY_GRADLE_PROJECT, validContainerVersion)); + addLibertyModule(new LibertyModule(project, virtualFile, projectName, buildFile.getProjectType(), validContainerVersion)); } } return getInstance(); From 9323fe99c4d744f17f39c41ba09555c4e7784494 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 8 Jan 2025 18:48:27 -0500 Subject: [PATCH 05/12] Set project type on build file so we do not have to derive it later Signed-off-by: Paul Gooderham --- .../java/io/openliberty/tools/intellij/LibertyModules.java | 5 ----- .../openliberty/tools/intellij/util/LibertyProjectUtil.java | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java index adc8144a8..9f8814b0d 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java @@ -72,11 +72,6 @@ public LibertyModules scanLibertyModules(Project project) { LOGGER.error(String.format("Could not resolve current project %s", virtualFile)); break; } - if (virtualFile.getName().equals("pom.xml")) { - buildFile.setProjectType(Constants.LIBERTY_MAVEN_PROJECT); - } else { - buildFile.setProjectType(Constants.LIBERTY_GRADLE_PROJECT); - } try { if (buildFile.getProjectType().equals(Constants.LIBERTY_MAVEN_PROJECT)) { projectName = LibertyMavenUtil.getProjectNameFromPom(virtualFile); diff --git a/src/main/java/io/openliberty/tools/intellij/util/LibertyProjectUtil.java b/src/main/java/io/openliberty/tools/intellij/util/LibertyProjectUtil.java index 487232864..11604a611 100644 --- a/src/main/java/io/openliberty/tools/intellij/util/LibertyProjectUtil.java +++ b/src/main/java/io/openliberty/tools/intellij/util/LibertyProjectUtil.java @@ -199,6 +199,7 @@ private static ArrayList getBuildFiles(Project project, String buildF // check if valid pom.xml, or if part of Liberty project if (filter.matches(project, buildFile, mavenFile)) { buildFile.setBuildFile(mavenFile); + buildFile.setProjectType(buildFileType); buildFiles.add(buildFile); } } @@ -212,6 +213,7 @@ private static ArrayList getBuildFiles(Project project, String buildF // check if valid build.gradle, or if part of Liberty project if (filter.matches(project, buildFile, gradleFile)) { buildFile.setBuildFile(gradleFile); + buildFile.setProjectType(buildFileType); buildFiles.add(buildFile); } } catch (Exception e) { From 1d39ee0f48022c1891dabc123d6f28128e1f23f1 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 8 Jan 2025 19:06:07 -0500 Subject: [PATCH 06/12] Scan Gradle files regardless of error scanning Maven files and do not return null Signed-off-by: Paul Gooderham --- .../java/io/openliberty/tools/intellij/LibertyModules.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java index 9f8814b0d..f23a4f2ac 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java @@ -58,10 +58,13 @@ public LibertyModules scanLibertyModules(Project project) { ArrayList buildFiles = new ArrayList<>(); try { buildFiles.addAll(LibertyProjectUtil.getMavenBuildFiles(project)); + } catch (IOException | SAXException | ParserConfigurationException e) { + LOGGER.error("I/O error or error parsing Liberty Maven projects in workspace", e); + } + try { // search for Gradle files even if Maven files experience error buildFiles.addAll(LibertyProjectUtil.getGradleBuildFiles(project)); } catch (IOException | SAXException | ParserConfigurationException e) { - LOGGER.warn("Could not find Liberty Maven or Gradle projects in workspace", e); - return null; + LOGGER.error("I/O error or error parsing Liberty Gradle projects in workspace", e); } for (BuildFile buildFile : buildFiles) { From 3548ff07b23e64a5f7017dd1676c185b4f1e8a2f Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 8 Jan 2025 19:12:24 -0500 Subject: [PATCH 07/12] Document why we need to scan for liberty modules Signed-off-by: Paul Gooderham --- .../tools/intellij/runConfiguration/LibertyRunConfiguration.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java index 2ba4e1886..879e7a284 100644 --- a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java +++ b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java @@ -44,6 +44,7 @@ public class LibertyRunConfiguration extends ModuleBasedConfiguration Date: Thu, 9 Jan 2025 11:41:40 -0500 Subject: [PATCH 08/12] Add test tracing to UIBotTestUtils.openLibertyToolWindow() Signed-off-by: Paul Gooderham --- .../java/io/openliberty/tools/intellij/it/UIBotTestUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java b/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java index 23bf08fce..6d5ba35ab 100644 --- a/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java +++ b/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java @@ -437,6 +437,7 @@ public static void openAndValidateLibertyToolWindow(RemoteRobot remoteRobot, Str * @param remoteRobot The RemoteRobot instance. */ public static void openLibertyToolWindow(RemoteRobot remoteRobot) { + TestUtils.printTrace(TestUtils.TraceSevLevel.INFO, "UIBotTestUtils.openLibertyToolWindow Entry"); int maxRetries = 6; Exception error = null; for (int i = 0; i < maxRetries; i++) { @@ -466,6 +467,7 @@ public static void openLibertyToolWindow(RemoteRobot remoteRobot) { if (error != null) { throw new RuntimeException("Unable to open the Liberty tool window.", error); } + TestUtils.printTrace(TestUtils.TraceSevLevel.INFO, "UIBotTestUtils.openLibertyToolWindow Exit"); } /** From e5e1065e84419a43750ec02d5f2c5a3840e5e9df Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 10 Jan 2025 15:46:12 -0500 Subject: [PATCH 09/12] Consolidate two loops in LibertyProjectUtil.getBuildFiles Signed-off-by: Paul Gooderham --- .../intellij/util/LibertyProjectUtil.java | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/util/LibertyProjectUtil.java b/src/main/java/io/openliberty/tools/intellij/util/LibertyProjectUtil.java index 11604a611..a61762964 100644 --- a/src/main/java/io/openliberty/tools/intellij/util/LibertyProjectUtil.java +++ b/src/main/java/io/openliberty/tools/intellij/util/LibertyProjectUtil.java @@ -189,40 +189,34 @@ public static void setFocusToWidget(Project project, ShellTerminalWidget widget) // Search the filename index to find valid build files (Maven and Gradle) for the current project private static ArrayList getBuildFiles(Project project, String buildFileType, BuildFileFilter filter) throws ParserConfigurationException, SAXException, IOException { - ArrayList buildFiles = new ArrayList(); - + ArrayList collectedBuildFiles = new ArrayList(); + Collection indexedVFiles; if (buildFileType.equals(Constants.LIBERTY_MAVEN_PROJECT)) { - Collection mavenFiles = readIndex(project, "pom.xml"); - if (mavenFiles != null) { - for (VirtualFile mavenFile : mavenFiles) { - BuildFile buildFile = LibertyMavenUtil.validPom(mavenFile); - // check if valid pom.xml, or if part of Liberty project - if (filter.matches(project, buildFile, mavenFile)) { - buildFile.setBuildFile(mavenFile); - buildFile.setProjectType(buildFileType); - buildFiles.add(buildFile); + indexedVFiles = readIndex(project, "pom.xml"); + } else { + indexedVFiles = readIndex(project, "build.gradle"); + } + if (indexedVFiles != null) { + for (VirtualFile vFile : indexedVFiles) { + try { + BuildFile buildFile; + if (buildFileType.equals(Constants.LIBERTY_MAVEN_PROJECT)) { + buildFile = LibertyMavenUtil.validPom(vFile); + } else { + buildFile = LibertyGradleUtil.validBuildGradle(vFile); } - } - } - } else if (buildFileType.equals(Constants.LIBERTY_GRADLE_PROJECT)) { - Collection gradleFiles = readIndex(project, "build.gradle"); - if (gradleFiles != null) { - for (VirtualFile gradleFile : gradleFiles) { - try { - BuildFile buildFile = LibertyGradleUtil.validBuildGradle(gradleFile); - // check if valid build.gradle, or if part of Liberty project - if (filter.matches(project, buildFile, gradleFile)) { - buildFile.setBuildFile(gradleFile); - buildFile.setProjectType(buildFileType); - buildFiles.add(buildFile); - } - } catch (Exception e) { - LOGGER.error(String.format("Error parsing build.gradle %s", gradleFile), e.getMessage()); + // check if valid pom.xml or build.gradle, or if part of Liberty project + if (filter.matches(project, buildFile, vFile)) { + buildFile.setBuildFile(vFile); + buildFile.setProjectType(buildFileType); + collectedBuildFiles.add(buildFile); } + } catch (Exception e) { + LOGGER.error(String.format("Error parsing build file %s", vFile), e.getMessage()); } } } - return buildFiles; + return collectedBuildFiles; } // Wrap the search for files in a executeOnPooledThread() method to handle the slow operations on EDT issue From dcb57d46de41efa99e6af9d5e079c62ee54c1b5f Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 10 Jan 2025 20:42:14 -0500 Subject: [PATCH 10/12] Fix test failure when you close one project and open another Signed-off-by: Paul Gooderham --- .../java/io/openliberty/tools/intellij/LibertyExplorer.java | 3 ++- .../java/io/openliberty/tools/intellij/LibertyModules.java | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java b/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java index 123167e8f..f52d4c7ec 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java @@ -103,7 +103,8 @@ public static ActionToolbar buildActionToolbar(Tree tree) { */ public static Tree buildTree(Project project, Color backgroundColor) { LibertyModules libertyModules = LibertyModules.getInstance().scanLibertyModules(project); - if (libertyModules.isEmpty()) { + // This singleton may contain entries from old projects if you close a project and open another + if (libertyModules.getLibertyModules(project).isEmpty()) { return null; } DefaultMutableTreeNode top = new DefaultMutableTreeNode("Root node"); diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java index f23a4f2ac..15509ea17 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java @@ -44,9 +44,6 @@ public synchronized static LibertyModules getInstance() { return instance; } - public boolean isEmpty() { - return libertyModules.isEmpty(); - } /** * Scan the project for the modules that are Liberty apps. * @return null if there are no Liberty modules From 35c3458a3dd3314ad7fef000bdd047ae99003d6a Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 13 Jan 2025 12:10:52 -0500 Subject: [PATCH 11/12] Log errors using Run/Debug using style of other tests. Update copyright Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/intellij/it/UIBotTestUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java b/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java index 6d5ba35ab..51a4cc6f3 100644 --- a/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java +++ b/src/test/java/io/openliberty/tools/intellij/it/UIBotTestUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023, 2024 IBM Corporation. + * Copyright (c) 2023, 2025 IBM Corporation. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -2243,9 +2243,9 @@ public static void selectConfigUsingMenu(RemoteRobot remoteRobot, String cfgName // Exit loop if successful break; } catch (WaitForConditionTimeoutException e) { - System.err.println("Attempt " + (attempt + 1) + " failed: Timeout while trying to find or interact with menu items."); + TestUtils.printTrace(TestUtils.TraceSevLevel.INFO, "Attempt " + (attempt + 1) + " failed: Timeout while trying to find or interact with menu items. Retrying..."); } catch (Exception e) { - System.err.println("Attempt " + (attempt + 1) + " failed: " + e.getMessage()); + TestUtils.printTrace(TestUtils.TraceSevLevel.INFO, "Attempt " + (attempt + 1) + " failed: " + e.getMessage() + " Retrying..."); } if (attempt == 4) { // If the last attempt fails From f54d73948f5f3637e67baf3faadcc81aa432c5c3 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 14 Jan 2025 18:38:57 -0500 Subject: [PATCH 12/12] Add LibertyModules.rescan... to scan without clearing the list Signed-off-by: Paul Gooderham --- .../openliberty/tools/intellij/LibertyModules.java | 13 +++++++++++-- .../runConfiguration/LibertyRunConfiguration.java | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java index 15509ea17..13188c12c 100644 --- a/src/main/java/io/openliberty/tools/intellij/LibertyModules.java +++ b/src/main/java/io/openliberty/tools/intellij/LibertyModules.java @@ -45,13 +45,22 @@ public synchronized static LibertyModules getInstance() { } /** - * Scan the project for the modules that are Liberty apps. - * @return null if there are no Liberty modules + * Remove existing data and scan the project for the modules that are Liberty apps. + * @return this singleton, the list will be empty if there are no Liberty modules */ public LibertyModules scanLibertyModules(Project project) { synchronized (libertyModules) { removeForProject(project); // remove previous data, if any + return rescanLibertyModules(project); + } + } + /** + * Scan the project for the modules that are Liberty apps and update any existing entries. + * @return this singleton, the list will be empty if there are no Liberty modules + */ + public LibertyModules rescanLibertyModules(Project project) { + synchronized (libertyModules) { ArrayList buildFiles = new ArrayList<>(); try { buildFiles.addAll(LibertyProjectUtil.getMavenBuildFiles(project)); diff --git a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java index 879e7a284..a76cc411b 100644 --- a/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java +++ b/src/main/java/io/openliberty/tools/intellij/runConfiguration/LibertyRunConfiguration.java @@ -45,7 +45,7 @@ public class LibertyRunConfiguration extends ModuleBasedConfiguration