Skip to content

Commit

Permalink
fix: Connect Quarkus run configuration with Services view support
Browse files Browse the repository at this point in the history
Fixes #1265

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr authored and fbricon committed Nov 23, 2023
1 parent 653fb62 commit 3ac9a73
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public class QuarkusConstants {
public static final String QUARKUS_SCHEDULED_ANNOTATION = "io.quarkus.scheduler.Scheduled";

public static final String QUARKUS_CORE_PREFIX = "io.quarkus:quarkus-core:";

public static final String QUARKUS_VERTX_HTTP_PREFIX = "io.quarkus:quarkus-vertx-http:";

public static final String QUARKUS_PREFIX = "quarkus";
public static final String QUARKUS_JAVADOC_PROPERTIES_FILE = "quarkus-javadoc.properties";
public static final String QUARKUS_EXTENSION_PROPERTIES = "META-INF/quarkus-extension.properties";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,38 +39,56 @@
public class QuarkusModuleUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(QuarkusModuleUtil.class);

private static final Pattern QUARKUS_CORE_PATTERN = Pattern.compile("quarkus-core-(\\d[a-zA-Z\\d-.]+?).jar");

public static final Pattern QUARKUS_STANDARD_VERSIONING = Pattern.compile("(\\d+).(\\d+).(\\d+)(.Final)?(-redhat-\\\\d+)?$");

public static final Pattern APPLICATION_PROPERTIES = Pattern.compile("application(-.+)?\\.properties");

public static final Pattern MICROPROFILE_CONFIG_PROPERTIES = Pattern.compile("microprofile-config(-.+)?\\.properties");

public static final Pattern APPLICATION_YAML = Pattern.compile("application(-.+)?\\.ya?ml");


/**
* Check if the module is a Quarkus project. Should check if some class if present
* but it seems PSI is not available when the module is added thus we rely on the
* library names.
* library names (io.quarkus:quarkus-core*).
*
* @param module the module to check
* @return yes if module is a Quarkus project
* @return true if module is a Quarkus project and false otherwise.
*/
public static boolean isQuarkusModule(Module module) {
return hasLibrary(module, QuarkusConstants.QUARKUS_CORE_PREFIX);
}

/**
* Check if the module is a Quarkus Web Application project. Should check if some class if present
* but it seems PSI is not available when the module is added thus we rely on the
* library names (io.quarkus:quarkus-vertx-http:*).
*
* @param module the module to check
* @return true if module is a Quarkus project and false otherwise.
*/
public static boolean isQuarkusWebAppModule(Module module) {
return hasLibrary(module, QuarkusConstants.QUARKUS_VERTX_HTTP_PREFIX);
}

private static boolean hasLibrary(Module module, String libraryNamePrefix) {
OrderEnumerator libraries = ModuleRootManager.getInstance(module).orderEntries().librariesOnly();
return libraries.process(new RootPolicy<Boolean>() {
@Override
public Boolean visitLibraryOrderEntry(@NotNull LibraryOrderEntry libraryOrderEntry, Boolean value) {
return value || isQuarkusLibrary(libraryOrderEntry);
return value || isLibrary(libraryOrderEntry, libraryNamePrefix);
}
}, false);
}

public static boolean isQuarkusLibrary(@NotNull LibraryOrderEntry libraryOrderEntry) {
private static boolean isLibrary(@NotNull LibraryOrderEntry libraryOrderEntry, String libraryNamePrefix) {
return libraryOrderEntry.getLibraryName() != null &&
libraryOrderEntry.getLibraryName().contains(QuarkusConstants.QUARKUS_CORE_PREFIX);
libraryOrderEntry.getLibraryName().contains(libraryNamePrefix);
}

private static final Pattern QUARKUS_CORE_PATTERN = Pattern.compile("quarkus-core-(\\d[a-zA-Z\\d-.]+?).jar");
public static final Pattern QUARKUS_STANDARD_VERSIONING = Pattern.compile("(\\d+).(\\d+).(\\d+)(.Final)?(-redhat-\\\\d+)?$");

/**
* Checks whether the quarkus version used in this module matches the given predicate.
* If we're unable to detect the Quarkus version, this method always returns false.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,7 @@
******************************************************************************/
package com.redhat.devtools.intellij.quarkus.run;

import com.intellij.execution.DefaultExecutionTarget;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.ExecutionTarget;
import com.intellij.execution.Executor;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ModuleBasedConfiguration;
import com.intellij.execution.configurations.RunConfiguration;
Expand Down Expand Up @@ -133,12 +127,14 @@ public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEn
telemetry.property("kind", executor.getId());
BuildToolDelegate toolDelegate = BuildToolDelegate.getDelegate(getModule());
allocateLocalPort();
RunProfileState state = null;
if (toolDelegate != null) {
telemetry.property("tool", toolDelegate.getDisplay());
// Create a Gradle or Maven run configuration in memory
RunnerAndConfigurationSettings settings = toolDelegate.getConfigurationDelegate(getModule(), this);
if (settings != null) {
long groupId = ExecutionEnvironment.getNextUnusedExecutionId();
doRunConfiguration(settings, executor, DefaultExecutionTarget.INSTANCE, groupId, null,
state = doRunConfiguration(settings, executor, DefaultExecutionTarget.INSTANCE, groupId, null,
desc -> desc.getComponent().putClientProperty(QuarkusConstants.QUARKUS_RUN_CONTEXT_KEY, new QuarkusRunContext(getModule())));
}
} else {
Expand All @@ -153,7 +149,7 @@ public void run(@NotNull ProgressIndicator indicator) {
}
});
}
return null;
return state;
}

private void waitForPortAvailable(int port, ProgressIndicator monitor) throws IOException {
Expand Down Expand Up @@ -212,21 +208,19 @@ public int getPort() {
return port;
}

private static void doRunConfiguration(@NotNull RunnerAndConfigurationSettings configuration,
@NotNull Executor executor,
@Nullable ExecutionTarget targetOrNullForDefault,
@Nullable Long executionId,
@Nullable DataContext dataContext,
ProgramRunner.Callback callback) {
private static RunProfileState doRunConfiguration(@NotNull RunnerAndConfigurationSettings configuration,
@NotNull Executor executor,
@Nullable ExecutionTarget targetOrNullForDefault,
@Nullable Long executionId,
@Nullable DataContext dataContext,
ProgramRunner.Callback callback) throws ExecutionException {
ExecutionEnvironmentBuilder builder = createEnvironment(executor, configuration);
if (builder == null) {
return;
return null;
}

if (targetOrNullForDefault != null) {
builder.target(targetOrNullForDefault);
}
else {
} else {
builder.activeTarget();
}
if (executionId != null) {
Expand All @@ -235,7 +229,7 @@ private static void doRunConfiguration(@NotNull RunnerAndConfigurationSettings c
if (dataContext != null) {
builder.dataContext(dataContext);
}
ExecutionManager.getInstance(configuration.getConfiguration().getProject()).restartRunProfile(builder.build(callback));
return configuration.getConfiguration().getState(executor, builder.build(callback));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.intellij.quarkus.run.dashboard;

import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.dashboard.RunDashboardCustomizer;
import com.intellij.execution.dashboard.RunDashboardRunConfigurationNode;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil;
import com.redhat.devtools.intellij.quarkus.run.QuarkusRunConfiguration;
import com.redhat.devtools.intellij.quarkus.run.QuarkusRunContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;

/**
* Dashboard customizer for Quarkus to provide:
*
* <ul>
* <li>Open quarkus application in a browser.</li>
* <li>Open quarkus DevUI in a browser.</li>
* </ul>
*/
public class QuarkusRunDashboardCustomizer extends RunDashboardCustomizer {

@Override
public boolean isApplicable(@NotNull RunnerAndConfigurationSettings settings, @Nullable RunContentDescriptor descriptor) {
return settings.getConfiguration() instanceof QuarkusRunConfiguration;
}

@Override
public boolean updatePresentation(@NotNull PresentationData presentation, @NotNull RunDashboardRunConfigurationNode node) {
if (!(node.getConfigurationSettings().getConfiguration() instanceof QuarkusRunConfiguration)) {
return false;
}
node.putUserData(RunDashboardCustomizer.NODE_LINKS, null);
RunContentDescriptor descriptor = node.getDescriptor();
if (descriptor != null) {
ProcessHandler processHandler = descriptor.getProcessHandler();
if (processHandler != null && !processHandler.isProcessTerminated()) {
// The Quarkus run configuration is running
QuarkusRunConfiguration quarkusRunConfiguration = (QuarkusRunConfiguration) node.getConfigurationSettings().getConfiguration();
if (QuarkusModuleUtil.isQuarkusWebAppModule(quarkusRunConfiguration.getModule())) {
// It is a Web application, add links for:
// - Opening quarkus application in a browser
// - Opening DevUI in a browser
QuarkusRunContext runContext = new QuarkusRunContext(quarkusRunConfiguration.getModule());
// Add application Url as hyperlink
String applicationUrl = runContext.getApplicationURL();
String applicationLabel = applicationUrl;
presentation.addText(" ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
presentation.addText(applicationLabel, SimpleTextAttributes.LINK_ATTRIBUTES);

// Add DevUI Url as hyperlink
String devUIUrl = runContext.getDevUIURL();
String devUILabel = "Dev UI";
presentation.addText(" - ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
presentation.addText(devUILabel, SimpleTextAttributes.LINK_ATTRIBUTES);

Map<Object, Object> links = new HashMap<>();
links.put(applicationLabel, new SimpleColoredComponent.BrowserLauncherTag(applicationUrl));
links.put(devUILabel, new SimpleColoredComponent.BrowserLauncherTag(devUIUrl));
node.putUserData(RunDashboardCustomizer.NODE_LINKS, links);
}
}
}
return true;
}

}
3 changes: 3 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,12 @@
<projectService serviceImplementation="com.redhat.devtools.intellij.lsp4mp4ij.classpath.ClasspathResourceChangedManager"/>
<projectService serviceImplementation="com.redhat.devtools.intellij.lsp4mp4ij.psi.core.project.PsiMicroProfileProjectManager"/>
<projectService serviceImplementation="com.redhat.devtools.intellij.quarkus.QuarkusDeploymentSupport"/>

<!--Quarkus run config -->
<projectService serviceImplementation="com.redhat.devtools.intellij.quarkus.run.QuarkusRunConfigurationManager" />
<configurationType implementation="com.redhat.devtools.intellij.quarkus.run.QuarkusRunConfigurationType"/>
<consoleActionsPostProcessor implementation="com.redhat.devtools.intellij.quarkus.run.QuarkusRunConsolePostProcessor"/>
<runDashboardCustomizer implementation="com.redhat.devtools.intellij.quarkus.run.dashboard.QuarkusRunDashboardCustomizer"/>

<!-- Qute -->
<facetType implementation="com.redhat.devtools.intellij.qute.facet.QuteFacetType"/>
Expand Down

0 comments on commit 3ac9a73

Please sign in to comment.