Skip to content

Commit

Permalink
Merge pull request #33826 from phillip-kruger/dev-ui-server-log-excep…
Browse files Browse the repository at this point in the history
…tion

Dev UI: add open in IDE feature
  • Loading branch information
phillip-kruger authored Jun 12, 2023
2 parents 35e0f9c + dcd0fa2 commit 197c921
Show file tree
Hide file tree
Showing 13 changed files with 493 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public static List<ProcessInfo> runningProcesses() {
ProcessHandle.Info info = p.info();
Optional<String> command = info.command();
if (command.isPresent()) {
result.add(new ProcessInfo(command.get(), info.arguments().orElse(null)));
result.add(new ProcessInfo(command.get(), info.commandLine().orElse(""), info.arguments().orElse(null)));
}
});
return result;
Expand All @@ -211,23 +211,29 @@ public static List<ProcessInfo> runningProcesses() {
private static class ProcessInfo {
// the executable pathname of the process.
private final String command;
private final String commandLine;
private final String[] arguments;

public ProcessInfo(String command, String[] arguments) {
public ProcessInfo(String command, String commandLine, String[] arguments) {
this.command = command;
this.commandLine = commandLine;
this.arguments = arguments;
}

public String getCommand() {
return command;
}

public String getCommandLine() {
return commandLine;
}

public String[] getArguments() {
return arguments;
}

private boolean containInCommand(String value) {
return this.command.contains(value);
return this.command.contains(value) || this.commandLine.contains(value);
}

private boolean containInArguments(String value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { beans } from 'build-time-data';
import '@vaadin/grid';
import '@vaadin/vertical-layout';
import 'qui-badge';
import 'qui-ide-link';

/**
* This component shows the Arc Beans
Expand Down Expand Up @@ -73,7 +74,9 @@ export class QwcArcBeans extends LitElement {
${bean.nonDefaultQualifiers.map(qualifier =>
html`${this._qualifierRenderer(qualifier)}`
)}
<code>${bean.providerType.name}</code>
<qui-ide-link fileName='${bean.providerType.name}'
lineNumber=0><code>${bean.providerType.name}</code></qui-ide-link>
</vaadin-vertical-layout>`;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { columnBodyRenderer } from '@vaadin/grid/lit.js';
import '@vaadin/grid';
import '@vaadin/vertical-layout';
import 'qui-badge';
import 'qui-ide-link';

/**
* This component shows the Arc Observers
Expand Down Expand Up @@ -89,9 +90,8 @@ export class QwcArcObservers extends LitElement {
}

_sourceRenderer(bean){
return html`
<code>${bean.declaringClass.name}</code><code class="method">#${bean.methodName}()</code>
`;
return html`<qui-ide-link fileName='${bean.declaringClass.name}'
lineNumber=0><code>${bean.declaringClass.name}</code><code class="method">#${bean.methodName}()</code></qui-ide-link>`;
}

_typeRenderer(bean){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'qui-badge';
import { removedBeans } from 'build-time-data';
import { removedDecorators } from 'build-time-data';
import { removedInterceptors } from 'build-time-data';
import 'qui-ide-link';

/**
* This component shows the Arc RemovedComponents
Expand Down Expand Up @@ -142,7 +143,8 @@ export class QwcArcRemovedComponents extends LitElement {
${bean.nonDefaultQualifiers.map(qualifier =>
html`${this._simpleNameRenderer(qualifier)}`
)}
<code>${bean.providerType.name}</code>
<qui-ide-link fileName='${bean.providerType.name}'
lineNumber=0><code>${bean.providerType.name}</code></qui-ide-link>
</vaadin-vertical-layout>`;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,31 @@
import static org.jboss.logmanager.Level.TRACE;
import static org.jboss.logmanager.Level.WARN;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.logging.Logger;
import org.mvnpm.importmap.Aggregator;
import org.mvnpm.importmap.Location;

Expand All @@ -40,8 +49,13 @@
import io.quarkus.deployment.IsDevelopment;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.ide.EffectiveIdeBuildItem;
import io.quarkus.deployment.ide.Ide;
import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
import io.quarkus.deployment.util.IoUtil;
import io.quarkus.dev.console.DevConsoleManager;
import io.quarkus.dev.spi.DevModeType;
import io.quarkus.devui.deployment.extension.Extension;
import io.quarkus.devui.spi.AbstractDevUIBuildItem;
import io.quarkus.devui.spi.DevUIContent;
Expand All @@ -61,6 +75,8 @@
* time
*/
public class BuildTimeContentProcessor {
private static final Logger log = Logger.getLogger(BuildTimeContentProcessor.class);

private static final String SLASH = "/";
private static final String DEV_UI = "dev-ui";
private static final String BUILD_TIME_PATH = "dev-ui-templates/build-time";
Expand Down Expand Up @@ -92,6 +108,7 @@ InternalImportMapBuildItem createKnownInternalImportMap(NonApplicationRootPathBu
internalImportMapBuildItem.add("qui-badge", contextRoot + "qui/qui-badge.js");
internalImportMapBuildItem.add("qui-alert", contextRoot + "qui/qui-alert.js");
internalImportMapBuildItem.add("qui-code-block", contextRoot + "qui/qui-code-block.js");
internalImportMapBuildItem.add("qui-ide-link", contextRoot + "qui/qui-ide-link.js");

// Echarts
internalImportMapBuildItem.add("echarts/", contextRoot + "echarts/");
Expand Down Expand Up @@ -217,7 +234,7 @@ void createBuildTimeConstJsTemplate(CurateOutcomeBuildItem curateOutcomeBuildIte
String value = DatabindCodec.prettyMapper().writeValueAsString(pageData.getValue());
data.put(key, value);
} catch (JsonProcessingException ex) {
ex.printStackTrace();
log.error("Could not create Json Data for Dev UI page", ex);
}
}
}
Expand Down Expand Up @@ -245,8 +262,8 @@ void gatherMvnpmJars(BuildProducer<MvnpmBuildItem> mvnpmProducer, CurateOutcomeB
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
try {
Enumeration<URL> jarsWithImportMaps = tccl.getResources(Location.IMPORTMAP_PATH);
Set<URL> jarUrls = new HashSet<URL>(Collections.list(jarsWithImportMaps));
for (URL jarUrl : jarUrls) {
while (jarsWithImportMaps.hasMoreElements()) {
URL jarUrl = jarsWithImportMaps.nextElement();
final JarURLConnection connection = (JarURLConnection) jarUrl.openConnection();
mvnpmJars.add(connection.getJarFileURL());
}
Expand Down Expand Up @@ -341,15 +358,17 @@ void createBuildTimeData(BuildProducer<BuildTimeConstBuildItem> buildTimeConstPr
BuildProducer<ThemeVarsBuildItem> themeVarsProducer,
List<InternalPageBuildItem> internalPages,
ExtensionsBuildItem extensionsBuildItem,
NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem) {
NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem,
LaunchModeBuildItem launchModeBuildItem,
Optional<EffectiveIdeBuildItem> effectiveIdeBuildItem) {

BuildTimeConstBuildItem internalBuildTimeData = new BuildTimeConstBuildItem(AbstractDevUIBuildItem.DEV_UI);

addThemeBuildTimeData(internalBuildTimeData, themeVarsProducer);
addMenuSectionBuildTimeData(internalBuildTimeData, internalPages, extensionsBuildItem);
addFooterTabBuildTimeData(internalBuildTimeData, extensionsBuildItem);
addVersionInfoBuildTimeData(internalBuildTimeData, nonApplicationRootPathBuildItem);

addIdeBuildTimeData(internalBuildTimeData, effectiveIdeBuildItem, launchModeBuildItem);
buildTimeConstProducer.produce(internalBuildTimeData);
}

Expand All @@ -372,6 +391,7 @@ private void addMenuSectionBuildTimeData(BuildTimeConstBuildItem internalBuildTi
List<InternalPageBuildItem> internalPages,
ExtensionsBuildItem extensionsBuildItem) {
// Menu section
@SuppressWarnings("unchecked")
List<Page> sectionMenu = new ArrayList();
Collections.sort(internalPages, (t, t1) -> {
return ((Integer) t.getPosition()).compareTo(t1.getPosition());
Expand All @@ -397,6 +417,7 @@ private void addMenuSectionBuildTimeData(BuildTimeConstBuildItem internalBuildTi
private void addFooterTabBuildTimeData(BuildTimeConstBuildItem internalBuildTimeData,
ExtensionsBuildItem extensionsBuildItem) {
// Add the Footer tabs
@SuppressWarnings("unchecked")
List<Page> footerTabs = new ArrayList();
Page serverLog = Page.webComponentPageBuilder().internal()
.namespace("devui-logstream")
Expand Down Expand Up @@ -444,6 +465,108 @@ private void addVersionInfoBuildTimeData(BuildTimeConstBuildItem internalBuildTi
internalBuildTimeData.addBuildTimeData("applicationInfo", applicationInfo);
}

private void addIdeBuildTimeData(BuildTimeConstBuildItem internalBuildTimeData,
Optional<EffectiveIdeBuildItem> effectiveIdeBuildItem,
LaunchModeBuildItem launchModeBuildItem) {

Map<String, Object> ideInfo = new HashMap<>();
boolean disable = launchModeBuildItem.getDevModeType().orElse(DevModeType.LOCAL) != DevModeType.LOCAL;
ideInfo.put("disable", disable);
if (effectiveIdeBuildItem.isPresent()) {
EffectiveIdeBuildItem eibi = effectiveIdeBuildItem.get();
if (!disable) {
// Add IDE info
Ide ide = eibi.getIde();
ideInfo.put("ideName", ide.name());
ideInfo.put("idePackages", getAllUserPackages());
}
}
internalBuildTimeData.addBuildTimeData("ideInfo", ideInfo);
}

private List<String> getAllUserPackages() {
List<Path> sourcesDir = DevConsoleManager.getHotReplacementContext().getSourcesDir();
List<String> packages = new ArrayList<>();

for (Path sourcePaths : sourcesDir) {
packages.addAll(sourcePackagesForRoot(sourcePaths));
}
return packages;
}

/**
* Return the most general packages used in the application
* <p>
* TODO: this likely covers almost all typical use cases, but probably needs some tweaks for extreme corner cases
*/
private List<String> sourcePackagesForRoot(Path langPath) {
if (!Files.exists(langPath)) {
return Collections.emptyList();
}
File[] rootFiles = langPath.toFile().listFiles();
List<Path> rootPackages = new ArrayList<>(1);
if (rootFiles != null) {
for (File rootFile : rootFiles) {
if (rootFile.isDirectory()) {
rootPackages.add(rootFile.toPath());
}
}
}
if (rootPackages.isEmpty()) {
return List.of("");
}
List<String> result = new ArrayList<>(rootPackages.size());
for (Path rootPackage : rootPackages) {
List<String> paths = new ArrayList<>();
SimpleFileVisitor<Path> simpleFileVisitor = new DetectPackageFileVisitor(paths);
try {
Files.walkFileTree(rootPackage, simpleFileVisitor);
if (paths.isEmpty()) {
continue;
}
String commonPath = commonPath(paths);
String rootPackageStr = commonPath.replace(langPath.toAbsolutePath().toString(), "")
.replace(File.separator, ".");
if (rootPackageStr.startsWith(".")) {
rootPackageStr = rootPackageStr.substring(1);
}
if (rootPackageStr.endsWith(".")) {
rootPackageStr = rootPackageStr.substring(0, rootPackageStr.length() - 1);
}
result.add(rootPackageStr);
} catch (IOException e) {
log.debug("Unable to determine the sources directories", e);
// just ignore it as it's not critical for the DevUI functionality
}
}
return result;
}

private String commonPath(List<String> paths) {
String commonPath = "";
List<String[]> dirs = new ArrayList<>(paths.size());
for (int i = 0; i < paths.size(); i++) {
dirs.add(i, paths.get(i).split(Pattern.quote(File.separator)));
}
for (int j = 0; j < dirs.get(0).length; j++) {
String thisDir = dirs.get(0)[j]; // grab the next directory name in the first path
boolean allMatched = true;
for (int i = 1; i < dirs.size() && allMatched; i++) { // look at the other paths
if (dirs.get(i).length < j) { //there is no directory
allMatched = false;
break;
}
allMatched = dirs.get(i)[j].equals(thisDir); //check if it matched
}
if (allMatched) {
commonPath += thisDir + File.separator;
} else {
break;
}
}
return commonPath;
}

private static final List<String> LEVELS = List.of(
OFF.getName(),
SEVERE.getName(),
Expand Down Expand Up @@ -624,4 +747,30 @@ static Color from(int hue, int saturation, int lightness, double alpha) {
return new Color(hue, saturation, lightness, alpha);
}
}

private static class DetectPackageFileVisitor extends SimpleFileVisitor<Path> {
private final List<String> paths;

public DetectPackageFileVisitor(List<String> paths) {
this.paths = paths;
}

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
boolean hasRegularFiles = false;
File[] files = dir.toFile().listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
hasRegularFiles = true;
break;
}
}
}
if (hasRegularFiles) {
paths.add(dir.toAbsolutePath().toString());
}
return FileVisitResult.CONTINUE;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.JandexReflection;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.jboss.logging.Logger;
Expand Down Expand Up @@ -663,10 +664,16 @@ private GACT getGACT(String artifactKey) {
}

private Class toClass(Type type) {
try {
return tccl.loadClass(type.name().toString());
} catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
if (type.kind().equals(Type.Kind.PRIMITIVE)) {
return JandexReflection.loadRawType(type);
} else if (type.kind().equals(Type.Kind.VOID)) {
throw new RuntimeException("Void method return detected, JsonRPC Method needs to return something.");
} else {
try {
return tccl.loadClass(type.name().toString());
} catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
}

Expand Down
Loading

0 comments on commit 197c921

Please sign in to comment.