Prefer connecting via JMX to process. New UI for show/refresh/hide
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
|
||||
@@ -9,8 +9,8 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul
|
||||
org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
|
||||
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
|
||||
org.eclipse.jdt.core.compiler.compliance=11
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
|
||||
org.eclipse.jdt.core.compiler.compliance=17
|
||||
org.eclipse.jdt.core.compiler.problem.APILeak=warning
|
||||
org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
|
||||
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
||||
@@ -109,4 +109,4 @@ org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.release=enabled
|
||||
org.eclipse.jdt.core.compiler.source=11
|
||||
org.eclipse.jdt.core.compiler.source=17
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512.008 512.008" xml:space="preserve" fill="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g> <g> <path style="fill:#868491;" d="M280.01,464.008h-48c-4.422,0-8,3.578-8,8v8c0,17.648,14.352,32,32,32s32-14.352,32-32v-8 C288.01,467.586,284.432,464.008,280.01,464.008z"></path> </g> <g> <path style="fill:#5C546A;" d="M256.002,464.008H232.01c-4.422,0-8,3.578-8,8v8c0,17.646,14.347,31.995,31.992,31.999 L256.002,464.008L256.002,464.008z"></path> </g> <g> <path style="fill:#B4B6BC;" d="M381.983,49.895c-37.391-35.141-86.367-52.742-137.734-49.52 C150.639,6.2,75.014,84.286,72.092,178.149c-2.156,69.547,34.375,133.578,95.344,167.117c15.156,8.344,24.57,24.367,24.57,41.828 v60.914c0,17.648,14.352,32,32,32h64c17.648,0,32-14.352,32-32v-60.914c0-17.445,9.484-33.508,24.766-41.93 c58.742-32.406,95.234-94.156,95.234-161.156C440.006,133.43,418.858,84.547,381.983,49.895z"></path> </g> <g> <circle style="fill:#FFFFFF;" cx="256.002" cy="184.008" r="128"></circle> </g> <g> <g> <path style="fill:#868491;" d="M283.986,232.008c-10.633,0-16.07-6.203-20.031-10.727c-3.492-3.984-4.883-5.273-8-5.273 c-3.102,0-4.484,1.289-7.961,5.266c-3.734,4.273-9.383,10.734-20.016,10.734c-10.625,0-16.273-6.461-20.008-10.734 c-3.477-3.977-4.859-5.266-7.961-5.266c-4.422,0-8-3.578-8-8s3.578-8,8-8c10.625,0,16.273,6.461,20.008,10.734 c3.477,3.977,4.859,5.266,7.961,5.266s4.492-1.289,7.969-5.266c3.734-4.273,9.383-10.734,20.008-10.734 c10.633,0,16.07,6.203,20.031,10.727c3.492,3.984,4.883,5.273,8,5.273c3.109,0,4.5-1.289,7.992-5.266 c3.742-4.273,9.391-10.734,20.031-10.734c4.422,0,8,3.578,8,8s-3.578,8-8,8c-3.117,0-4.508,1.289-8,5.273 C300.267,225.555,294.619,232.008,283.986,232.008z"></path> </g> </g> <g> <g> <path style="fill:#5C546A;" d="M232.002,384.008c-3.68,0-6.992-2.555-7.813-6.297l-40-184c-0.938-4.32,1.805-8.578,6.117-9.523 c4.344-0.953,8.578,1.805,9.523,6.117l40,184c0.938,4.32-1.805,8.578-6.117,9.523 C233.135,383.954,232.564,384.008,232.002,384.008z"></path> </g> </g> <g> <g> <path style="fill:#5C546A;" d="M280.017,384.008c-0.563,0-1.133-0.055-1.711-0.18c-4.313-0.945-7.055-5.203-6.117-9.523l40-184 c0.945-4.313,5.164-7.063,9.523-6.117c4.313,0.945,7.055,5.203,6.117,9.523l-40,184 C287.01,381.454,283.697,384.008,280.017,384.008z"></path> </g> </g> <g> <path style="fill:#B4B6BC;" d="M190.633,376.008c0.851,3.593,1.374,7.293,1.374,11.086v60.914c0,17.648,14.352,32,32,32h64 c17.648,0,32-14.352,32-32v-60.914c0-3.79,0.527-7.491,1.384-11.086H190.633z"></path> </g> <g> <path style="fill:#868491;" d="M256.002,376.008h-65.369c0.851,3.593,1.374,7.293,1.374,11.086v60.914c0,17.648,14.352,32,32,32 h31.995V376.008z"></path> </g> <g> <g> <rect x="256.002" y="400.008" style="fill:#868491;" width="64" height="16"></rect> </g> </g> <g> <g> <rect x="256.006" y="432.008" style="fill:#868491;" width="64" height="16"></rect> </g> </g> <g> <g> <rect x="192.002" y="400.008" style="fill:#5C546A;" width="64" height="16"></rect> </g> </g> <g> <g> <rect x="192.002" y="432.008" style="fill:#5C546A;" width="64" height="16"></rect> </g> </g> </g> </g></svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 512.008 512.008" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#868491;" d="M280.01,464.008h-48c-4.422,0-8,3.578-8,8v8c0,17.648,14.352,32,32,32s32-14.352,32-32v-8
|
||||
C288.01,467.586,284.432,464.008,280.01,464.008z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#5C546A;" d="M256.002,464.008H232.01c-4.422,0-8,3.578-8,8v8c0,17.646,14.347,31.995,31.992,31.999
|
||||
L256.002,464.008L256.002,464.008z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFCD00;" d="M381.983,49.895c-37.391-35.141-86.367-52.742-137.734-49.52
|
||||
C150.639,6.2,75.014,84.286,72.092,178.149c-2.156,69.547,34.375,133.578,95.344,167.117c15.156,8.344,24.57,24.367,24.57,41.828
|
||||
v60.914c0,17.648,14.352,32,32,32h64c17.648,0,32-14.352,32-32v-60.914c0-17.445,9.484-33.508,24.766-41.93
|
||||
c58.742-32.406,95.234-94.156,95.234-161.156C440.006,133.43,418.858,84.547,381.983,49.895z"/>
|
||||
</g>
|
||||
<g>
|
||||
<circle style="fill:#FFE671;" cx="256.002" cy="184.008" r="128"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M283.986,232.008c-10.633,0-16.07-6.203-20.031-10.727c-3.492-3.984-4.883-5.273-8-5.273
|
||||
c-3.102,0-4.484,1.289-7.961,5.266c-3.734,4.273-9.383,10.734-20.016,10.734c-10.625,0-16.273-6.461-20.008-10.734
|
||||
c-3.477-3.977-4.859-5.266-7.961-5.266c-4.422,0-8-3.578-8-8s3.578-8,8-8c10.625,0,16.273,6.461,20.008,10.734
|
||||
c3.477,3.977,4.859,5.266,7.961,5.266s4.492-1.289,7.969-5.266c3.734-4.273,9.383-10.734,20.008-10.734
|
||||
c10.633,0,16.07,6.203,20.031,10.727c3.492,3.984,4.883,5.273,8,5.273c3.109,0,4.5-1.289,7.992-5.266
|
||||
c3.742-4.273,9.391-10.734,20.031-10.734c4.422,0,8,3.578,8,8s-3.578,8-8,8c-3.117,0-4.508,1.289-8,5.273
|
||||
C300.267,225.555,294.619,232.008,283.986,232.008z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#5C546A;" d="M232.002,384.008c-3.68,0-6.992-2.555-7.813-6.297l-40-184c-0.938-4.32,1.805-8.578,6.117-9.523
|
||||
c4.344-0.953,8.578,1.805,9.523,6.117l40,184c0.938,4.32-1.805,8.578-6.117,9.523
|
||||
C233.135,383.954,232.564,384.008,232.002,384.008z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#5C546A;" d="M280.017,384.008c-0.563,0-1.133-0.055-1.711-0.18c-4.313-0.945-7.055-5.203-6.117-9.523l40-184
|
||||
c0.945-4.313,5.164-7.063,9.523-6.117c4.313,0.945,7.055,5.203,6.117,9.523l-40,184
|
||||
C287.01,381.454,283.697,384.008,280.017,384.008z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#B4B6BC;" d="M190.633,376.008c0.851,3.593,1.374,7.293,1.374,11.086v60.914c0,17.648,14.352,32,32,32h64
|
||||
c17.648,0,32-14.352,32-32v-60.914c0-3.79,0.527-7.491,1.384-11.086H190.633z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#868491;" d="M256.002,376.008h-65.369c0.851,3.593,1.374,7.293,1.374,11.086v60.914c0,17.648,14.352,32,32,32
|
||||
h31.995V376.008z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="256.002" y="400.008" style="fill:#868491;" width="64" height="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="256.006" y="432.008" style="fill:#868491;" width="64" height="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="192.002" y="400.008" style="fill:#5C546A;" width="64" height="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<rect x="192.002" y="432.008" style="fill:#5C546A;" width="64" height="16"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2022 Pivotal, Inc.
|
||||
* Copyright (c) 2015, 2024 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -10,7 +10,6 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.eclipse.boot.dash;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -23,6 +22,7 @@ import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.eclipse.debug.core.model.IProcess;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.eclipse.jface.resource.ImageRegistry;
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
@@ -36,15 +36,12 @@ import org.springframework.ide.eclipse.boot.dash.model.BootDashModelContext;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.BootDashViewModel;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.DefaultBootDashModelContext;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.LocalBootDashModel;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.RunState;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.RunTargets;
|
||||
import org.springframework.ide.eclipse.boot.dash.util.LaunchConfRunStateTracker;
|
||||
import org.springframework.ide.eclipse.boot.dash.util.RunStateTracker.RunStateListener;
|
||||
import org.springframework.ide.eclipse.boot.launch.BootLaunchConfigurationDelegate;
|
||||
import org.springsource.ide.eclipse.commons.livexp.util.Log;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
@@ -195,35 +192,46 @@ public class BootDashActivator extends AbstractUIPlugin {
|
||||
|
||||
@Override
|
||||
public void stateChanged(ILaunchConfiguration owner) {
|
||||
if (BootLaunchConfigurationDelegate.getEnableJmx(owner) && BootLaunchConfigurationDelegate.getAutoConnect(owner)) {
|
||||
if (BootLaunchConfigurationDelegate.getEnableJmx(owner)) {
|
||||
IJavaProject project = JavaCore.create(BootLaunchConfigurationDelegate.getProject(owner));
|
||||
try {
|
||||
if (project != null && Arrays.stream(project.getResolvedClasspath(true)).anyMatch(BootPropertyTester::isActuatorJar)) {
|
||||
LocalBootDashModel localModel = (LocalBootDashModel) getModel().getSectionByTargetId(RunTargets.LOCAL.getId());
|
||||
LaunchConfRunStateTracker tracker = localModel.getLaunchConfRunStateTracker();
|
||||
RunState state = tracker.getState(owner);
|
||||
if (state == RunState.RUNNING || state == RunState.DEBUGGING) {
|
||||
switch (tracker.getState(owner)) {
|
||||
case RUNNING:
|
||||
case DEBUGGING:
|
||||
for (ILaunch l : DebugPlugin.getDefault().getLaunchManager().getLaunches()) {
|
||||
if (l.getLaunchConfiguration() == owner) {
|
||||
for (IProcess p : l.getProcesses()) {
|
||||
String pid = p.getAttribute(IProcess.ATTR_PROCESS_ID);
|
||||
if (pid != null) {
|
||||
CommandInfo cmd = new CommandInfo("sts/livedata/connect",
|
||||
Map.of("processKey", pid));
|
||||
|
||||
// The delay seems to be necessary for the moment. Although the process is created VM attach API may not work at early stages of the process run.
|
||||
// "VirtualMachine.list()" call may not list the newly created process which means the process is gone and triggers disconnect.
|
||||
// If lifecycle management is enabled the ready state seem to be a great indicator of a boot process fully started.
|
||||
// TODO: explore health endpoint perhaps instead of ready state under Admin endpoint.
|
||||
// Flux.fromIterable(servers).flatMap(s -> Mono.delay(Duration.ofMillis(500)).then(s.executeCommand(cmd))).subscribe();
|
||||
Mono.delay(Duration.ofMillis(500)).then(LiveProcessCommandsExecutor.getDefault().executeCommand(cmd)).subscribe();
|
||||
CommandInfo cmd = new CommandInfo("sts/livedata/localAdd", Map.of(
|
||||
"host", "127.0.0.1",
|
||||
"port", l.getAttribute(BootLaunchConfigurationDelegate.JMX_PORT),
|
||||
"urlScheme", "http",
|
||||
"jmxurl", "service:jmx:rmi:///jndi/rmi://127.0.0.1:%s/jmxrmi".formatted(l.getAttribute(BootLaunchConfigurationDelegate.JMX_PORT)),
|
||||
"manualConnect", !BootLaunchConfigurationDelegate.getAutoConnect(owner),
|
||||
"processId", pid,
|
||||
"processName", owner.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, p.getLabel()),
|
||||
"projectName", project.getProject().getName()
|
||||
));
|
||||
|
||||
LiveProcessCommandsExecutor.getDefault().executeCommand(cmd).subscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INACTIVE:
|
||||
for (ILaunch l : DebugPlugin.getDefault().getLaunchManager().getLaunches()) {
|
||||
if (l.getLaunchConfiguration() == owner && l.getAttribute(BootLaunchConfigurationDelegate.JMX_PORT) != null) {
|
||||
String jmxUrl = "service:jmx:rmi:///jndi/rmi://127.0.0.1:%s/jmxrmi".formatted(l.getAttribute(BootLaunchConfigurationDelegate.JMX_PORT));
|
||||
LiveProcessCommandsExecutor.getDefault().executeCommand("sts/livedata/localRemove", jmxUrl).subscribe();
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getLog().error("Failed to connect to Boot app", e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Pivotal Software, Inc.
|
||||
* Copyright (c) 2019, 2024 Pivotal Software, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -16,9 +16,9 @@ import java.util.Map.Entry;
|
||||
public class CommandInfo {
|
||||
|
||||
public final String command;
|
||||
public final Map<String,String> info;
|
||||
public final Map<String,?> info;
|
||||
|
||||
public CommandInfo(String command, Map<String, String> info) {
|
||||
public CommandInfo(String command, Map<String, ?> info) {
|
||||
super();
|
||||
this.command = command;
|
||||
this.info = info;
|
||||
@@ -27,7 +27,7 @@ public class CommandInfo {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder s = new StringBuilder("CommandInfo("+command+", {\n");
|
||||
for (Entry<String, String> e : info.entrySet()) {
|
||||
for (Entry<String, ?> e : info.entrySet()) {
|
||||
s.append(" "+e.getKey() +": "+e.getValue()+"\n");
|
||||
}
|
||||
s.append("})");
|
||||
|
||||
@@ -57,4 +57,12 @@ public final class DefaultLiveProcessCommandExecutor implements LiveProcessComma
|
||||
))).thenAccept(l -> {}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> executeCommand(String command, Object... params) {
|
||||
return Mono.fromFuture(BootLsCommandUtils.getLanguageServers(command).collectAll(ls -> ls.getWorkspaceService().executeCommand(new ExecuteCommandParams(
|
||||
command,
|
||||
ImmutableList.of(params)
|
||||
))).thenAccept(l -> {}));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019, 2023 Pivotal Software, Inc.
|
||||
* Copyright (c) 2019, 2024 Pivotal Software, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -77,15 +77,24 @@ public class LiveDataConnectionManagementActions extends AbstractDisposable impl
|
||||
public ExecuteCommandAction(CommandInfo commandInfo) {
|
||||
super(params);
|
||||
this.commandInfo = commandInfo;
|
||||
String command = commandInfo.command;
|
||||
int lastSlash = command.lastIndexOf("/");
|
||||
String humanReadableCommand = command.substring(lastSlash+1);
|
||||
humanReadableCommand = humanReadableCommand.substring(0, 1).toUpperCase() + humanReadableCommand.substring(1);
|
||||
this.projectName = commandInfo.info.get("projectName");
|
||||
label = humanReadableCommand + " "+commandInfo.info.get("label");
|
||||
this.projectName = (String) commandInfo.info.get("projectName");
|
||||
label = computeLabel(commandInfo);
|
||||
this.setText(label);
|
||||
}
|
||||
|
||||
private String computeLabel(CommandInfo commandInfo) {
|
||||
switch (commandInfo.command) {
|
||||
case "sts/livedata/connect":
|
||||
return "Show Live Data from: %s".formatted(commandInfo.info.get("label"));
|
||||
case "sts/livedata/refresh":
|
||||
return "Refresh Live Data from: %s".formatted(commandInfo.info.get("label"));
|
||||
case "sts/livedata/disconnect":
|
||||
return "Hide Live Data from: %s".formatted(commandInfo.info.get("label"));
|
||||
default:
|
||||
}
|
||||
return (String) commandInfo.info.get("label");
|
||||
}
|
||||
|
||||
public String getProjectName() {
|
||||
return projectName;
|
||||
}
|
||||
@@ -115,7 +124,7 @@ public class LiveDataConnectionManagementActions extends AbstractDisposable impl
|
||||
}
|
||||
|
||||
public String getProcessId() {
|
||||
return commandInfo.info.get("processId");
|
||||
return (String) commandInfo.info.get("processId");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019, 2023 Pivotal Software, Inc.
|
||||
* Copyright (c) 2019, 2024 Pivotal Software, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
@@ -17,6 +17,7 @@ public interface LiveProcessCommandsExecutor {
|
||||
|
||||
Flux<CommandInfo> listCommands();
|
||||
Mono<Void> executeCommand(CommandInfo cmd);
|
||||
Mono<Void> executeCommand(String command, Object... params);
|
||||
|
||||
static LiveProcessCommandsExecutor getDefault() {
|
||||
return new DefaultLiveProcessCommandExecutor();
|
||||
|
||||
Reference in New Issue
Block a user