Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search for Liberty modules to use in Run/Debug config #1216

Merged
merged 12 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 24 additions & 103 deletions src/main/java/io/openliberty/tools/intellij/LibertyExplorer.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -106,115 +102,40 @@ 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<BuildFile> mavenBuildFiles;
ArrayList<BuildFile> gradleBuildFiles;
HashMap<String, ArrayList<Object>> 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);
// 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");
HashMap<String, ArrayList<Object>> 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<Object> settings = new ArrayList<Object>();
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<Object> settings = new ArrayList<Object>();
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);
Expand All @@ -224,7 +145,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();
Expand Down
87 changes: 86 additions & 1 deletion src/main/java/io/openliberty/tools/intellij/LibertyModules.java
turkeylurkey marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -10,17 +10,23 @@

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.*;

/**
* 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;

Expand All @@ -38,6 +44,67 @@ public synchronized static LibertyModules getInstance() {
return instance;
}

/**
* 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<BuildFile> 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.error("I/O error or error parsing Liberty Gradle projects in workspace", e);
}

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 project %s", virtualFile));
break;
}
try {
if (buildFile.getProjectType().equals(Constants.LIBERTY_MAVEN_PROJECT)) {
projectName = LibertyMavenUtil.getProjectNameFromPom(virtualFile);
} else {
projectName = LibertyGradleUtil.getProjectName(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, buildFile.getProjectType(), validContainerVersion));
}
}
return getInstance();
turkeylurkey marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Add tracked Liberty project to workspace, update project,
* projectType, name and validContainerVersion if already tracked.
Expand Down Expand Up @@ -101,6 +168,24 @@ public List<String> getLibertyBuildFilesAsString(Project project) {
return sBuildFiles;
}

/**
* Returns all Liberty modules for the given project
*
* @param project
* @return Liberty modules for the given project
*/
public List<LibertyModule> getLibertyModules(Project project) {
ArrayList<LibertyModule> 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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -39,13 +39,13 @@ public class LibertyRunConfiguration extends ModuleBasedConfiguration<RunConfigu
protected static Logger LOGGER = Logger.getInstance(LibertyRunConfiguration.class);

private final LibertyModules libertyModules;
private LibertyModule libertyModule;
@NonNls
private static final String RUN_IN_CONTAINER_TAG = "RUN_IN_CONTAINER";

public LibertyRunConfiguration(Project project, ConfigurationFactory factory, String name) {
super(name, getRunConfigurationModule(project), factory);
this.libertyModules = LibertyModules.getInstance();
// Find Liberty modules here to populate config field called "build file" and avoid NPE
this.libertyModules = LibertyModules.getInstance().rescanLibertyModules(project);
}

@NotNull
Expand Down Expand Up @@ -117,6 +117,7 @@ public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
@Nullable
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws ExecutionException {
LibertyModule libertyModule;
try {
libertyModule = libertyModules.getLibertyProjectFromString(getBuildFile());
} catch (NullPointerException e) {
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/io/openliberty/tools/intellij/util/BuildFile.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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);
}
turkeylurkey marked this conversation as resolved.
Show resolved Hide resolved
this.projectType = projectType;
}

Expand Down Expand Up @@ -58,6 +65,4 @@ public String getProjectName() {
public void setProjectName(String projectName) {
this.projectName = projectName;
}


}
Loading
Loading