All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.base.devserver.OpenInCurrentIde Maven / Gradle / Ivy

There is a newer version: 24.6.2
Show newest version
/*
 * Copyright 2000-2023 Vaadin Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.vaadin.base.devserver;

import java.io.File;
import java.lang.ProcessHandle.Info;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.open.OSUtils;
import com.vaadin.open.Open;

/**
 * Util for opening a file in the currently used IDE.
 * 

* Supports detecting VS Code, Eclipse and IntelliJ. */ public final class OpenInCurrentIde { private OpenInCurrentIde() { // Utils only } /** * Opens the given file at the given line number in the IDE used to launch * the current Java application. *

* If you are running the Java application from the command line or from an * unsupported IDE, then this method does nothing. * * @param file * the file to open * @param lineNumber * the line number to highlight * @return true if the file was opened, false otherwise */ public static boolean openFile(File file, int lineNumber) { String absolutePath = file.getAbsolutePath(); Optional maybeIdeCommand = findIdeCommandInfo(); if (!maybeIdeCommand.isPresent()) { getLogger().debug("Unable to detect IDE from process tree"); printProcessTree(msg -> getLogger().debug(msg)); return false; } Info processInfo = maybeIdeCommand.get(); if (isVSCode(processInfo)) { return Open.open("vscode://file" + absolutePath + ":" + lineNumber); } else if (isIdea(processInfo)) { try { run(getBinary(processInfo), "--line", lineNumber + "", absolutePath); return true; } catch (Exception e) { getLogger().error("Unable to launch IntelliJ IDEA", e); } } else if (isEclipse(processInfo)) { if (OSUtils.isMac()) { try { run("open", "-a", getBinary(processInfo), absolutePath); return true; } catch (Exception e) { getLogger().error("Unable to launch Eclipse", e); } } else { try { run(getBinary(processInfo), absolutePath + ":" + lineNumber); return true; } catch (Exception e) { getLogger().error("Unable to launch Eclipse", e); } } } return false; } static String getBinary(Info info) { String cmd = info.command().get(); if (isIdea(info)) { return getIdeaBinary(info); } else if (isEclipse(info)) { return cmd.replaceFirst("/Contents/MacOS/eclipse$", ""); } return cmd; } private static Logger getLogger() { return LoggerFactory.getLogger(OpenInCurrentIde.class); } public static void main(String[] args) { // This is so it will be easier to debug problems in the future printProcessTree(System.out::println); } private static void printProcessTree(Consumer printer) { for (Info info : getProcessTree()) { printer.accept("Process tree:"); info.command() .ifPresent(value -> printer.accept("Command: " + value)); info.commandLine().ifPresent( value -> printer.accept("Command line: " + value)); info.arguments().ifPresent(values -> { for (int i = 0; i < values.length; i++) { printer.accept("Arguments[" + i + "]: " + values[i]); } }); printer.accept(""); } } private static void run(String command, String... arguments) throws Exception { List cmd = new ArrayList<>(); cmd.add(command); cmd.addAll(Arrays.asList(arguments)); ProcessBuilder pb = new ProcessBuilder().command(cmd); pb.start().waitFor(); } private static List getProcessTree() { return getParentProcesses().stream().map(p -> p.info()) .collect(Collectors.toList()); } private static Optional findIdeCommandInfo() { return findIdeCommand(getProcessTree()); } static Optional findIdeCommand(List processes) { for (Info info : processes) { if (isIdea(info) || isVSCode(info) || isEclipse(info)) { return Optional.of(info); } } return Optional.empty(); } private static String getCommandAndArguments(Info info) { return info.commandLine().orElse(null); } private static List getParentProcesses() { List proceses = new ArrayList<>(); ProcessHandle p = ProcessHandle.current(); while (p != null) { proceses.add(p); p = p.parent().orElse(null); } return proceses; } static boolean isEclipse(Info info) { Optional cmd = info.command(); if (cmd.isPresent()) { String lowerCmd = cmd.get().toLowerCase(Locale.ENGLISH); // Eclipse has a lot of other products like Temurin and Adoptium so // we cannot check with "contains" return lowerCmd.endsWith("eclipse") || lowerCmd.endsWith("eclipse.exe"); } return false; } static boolean isIdea(Info info) { return getIdeaBinary(info) != null; } private static String getIdeaBinary(Info info) { String commandAndArguments = getCommandAndArguments(info); if (commandAndArguments != null && commandAndArguments.contains("idea_rt.jar")) { String replaced = commandAndArguments .replaceFirst(".*[:;]([^:;]*)(idea_rt.jar).*", "$1$2"); if (!replaced.equals(commandAndArguments)) { File binFolder = new File( new File(replaced).getParentFile().getParentFile(), "bin"); Optional bin = Stream.of("idea", "idea.sh", "idea.bat") .map(binName -> new File(binFolder, binName)) .filter(binaryFile -> binaryFile.exists()).findFirst(); if (bin.isPresent()) { return bin.get().getAbsolutePath(); } } } return info.command().filter(cmd -> cmd.contains("idea")).orElse(null); } static boolean isVSCode(Info info) { String termProgram = System.getenv("TERM_PROGRAM"); if ("vscode".equalsIgnoreCase(termProgram)) { return true; } String cmd = getCommandAndArguments(info); if (cmd != null) { String cmdLower = cmd.toLowerCase(Locale.ENGLISH); if (cmdLower.contains("vscode") || cmdLower.contains("vs code") || cmdLower.contains("code helper") || cmdLower.contains("visual studio code")) { return true; } } return false; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy