Skip to content
Draft
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
3 changes: 3 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,9 @@ jobs:
- name: ide/docker.api
run: ant $OPTS -f ide/docker.api test

- name: ide/dlight.nativeexecution
run: ant $OPTS -f ide/dlight.nativeexecution test

- name: ide/docker.ui
run: ant $OPTS -f ide/docker.ui test

Expand Down
2 changes: 1 addition & 1 deletion ide/dlight.nativeexecution/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
is.autoload=true
javac.release=11
javac.release=17
javac.compilerargs=-Xlint -Xlint:-serial
javadoc.arch=${basedir}/arch.xml
project.license=apache20-asf
Expand Down
9 changes: 9 additions & 0 deletions ide/dlight.nativeexecution/nbproject/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@
<specification-version>2.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.libs.jna.platform</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>2</release-version>
<specification-version>2.22</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.extexecution</code-name-base>
<build-prerequisite/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.netbeans.modules.nativeexecution;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
Expand All @@ -31,6 +32,7 @@
import org.netbeans.modules.nativeexecution.api.util.MacroMap;
import org.netbeans.modules.nativeexecution.api.util.ProcessUtils;
import org.netbeans.modules.nativeexecution.api.util.ProcessUtils.ExitStatus;
import org.netbeans.modules.nativeexecution.api.util.Shell;
import org.netbeans.modules.nativeexecution.api.util.Signal;
import org.netbeans.modules.nativeexecution.api.util.UnbufferSupport;
import org.netbeans.modules.nativeexecution.api.util.WindowsSupport;
Expand All @@ -51,11 +53,14 @@ public abstract class NbNativeProcess extends AbstractNativeProcess {
private final String nbStartPath;
private volatile ProcessStatusEx statusEx;

@SuppressWarnings("this-escape")
public NbNativeProcess(final NativeProcessInfo info) {
super(new NativeProcessInfo(info, true));
String _nbStartPath = null;
try {
_nbStartPath = NbStartUtility.getInstance().getPath(getExecutionEnvironment());
_nbStartPath = NbStartUtility
.getInstance(getExecutionEnvironment().isLocal())
.getPath(getExecutionEnvironment());
} catch (IOException ex) {
} finally {
nbStartPath = _nbStartPath;
Expand All @@ -71,12 +76,27 @@ protected final void create() throws Throwable {
private List<String> getCommand() {
List<String> command = new ArrayList<>();

command.add(nbStartPath);
File wslPath = new File(System.getenv("windir"), "system32/wsl.exe");
Shell activeShell = null;
if(isWindows()) {
activeShell = WindowsSupport.getInstance().getActiveShell();
}
if (activeShell != null && activeShell.type == Shell.ShellType.WSL) {
command.add(wslPath.getAbsolutePath());
command.add(WindowsSupport.getInstance().convertToWSL(nbStartPath));
} else {
command.add(nbStartPath);
}


String wdir = info.getWorkingDirectory(true);
if (wdir != null && !wdir.isEmpty()) {
command.add("--dir"); // NOI18N
command.add(fixForWindows(wdir));
if (activeShell != null && activeShell.type == Shell.ShellType.WSL) {
command.add(WindowsSupport.getInstance().convertToWSL(wdir));
} else {
command.add(fixForWindows(wdir));
}
}

if (!info.isPtyMode()) {
Expand Down Expand Up @@ -127,13 +147,26 @@ private List<String> getCommand() {
Map<String, String> userDefinedMap = userEnv.getUserDefinedMap();

for (Map.Entry<String, String> entry : userDefinedMap.entrySet()) {
if (isWindows() && entry.getKey().equalsIgnoreCase("PATH")) { // NOI18N
if (isWindows() && entry.getKey().equalsIgnoreCase("PATH") && WindowsSupport.getInstance().getActiveShell().type != Shell.ShellType.WSL) { // NOI18N
command.add("--env"); // NOI18N
command.add(entry.getKey() + "=" + WindowsSupport.getInstance().convertToAllShellPaths(entry.getValue())); // NOI18N
continue;
}
command.add("--env"); // NOI18N
command.add(entry.getKey() + "=" + entry.getValue()); // NOI18N
String setCall = entry.getKey() + "=" + entry.getValue();
if (isWindows() && WindowsSupport.getInstance().getActiveShell().type == Shell.ShellType.WSL) {
// the environment must be escaped so that it is passed
// to the inner shell
command.add(
"\""
+ setCall
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("$", "\\$")
+ "\""); // NOI18N
} else {
command.add(setCall);
}
}
}

Expand All @@ -150,23 +183,21 @@ private List<String> getCommand() {
}

private void readProcessInfo(InputStream fromProcessStream) throws IOException {
String line;

while (!(line = readLine(fromProcessStream).trim()).isEmpty()) {
for(String line = readLine(fromProcessStream); ! line.isBlank(); line = readLine(fromProcessStream)) {
addProcessInfo(line);
}

String pidProperty = getProcessInfo("PID"); // NOI18N

if (pidProperty == null) {
InputStream error = getErrorStream();
while (!(line = readLine(error).trim()).isEmpty()) {
for(String line = readLine(error); ! line.isBlank(); line = readLine(error)) {
LOG.info(line);
}
throw new InternalError("Failed to get process PID"); // NOI18N
}

setPID(Integer.parseInt(pidProperty)); // NOI18N
setPID(Integer.parseInt(pidProperty)); // NOI18N
}

@Override
Expand Down Expand Up @@ -240,7 +271,11 @@ protected boolean isWindows() {
}

protected String fixForWindows(String path) {
return isWindows() ? WindowsSupport.getInstance().convertToCygwinPath(path) : path;
if(isWindows() && WindowsSupport.getInstance().getActiveShell().type == Shell.ShellType.CYGWIN) {
return WindowsSupport.getInstance().convertToCygwinPath(path);
} else {
return path;
}
}

private boolean destroyed() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -50,6 +49,7 @@ public PtyNativeProcess(final NativeProcessInfo info) {
}

@Override
@SuppressWarnings({"deprecation", "AssignmentToForLoopParameter"})
protected void create() throws Throwable {
ExecutionEnvironment env = info.getExecutionEnvironment();
Pty pty = info.getPty();
Expand Down Expand Up @@ -116,7 +116,7 @@ protected void create() throws Throwable {
info.setCommandLine(null);
final String path = PtyUtility.getInstance().getPath(env);
info.setExecutable(path);
info.setArguments(newArgs.toArray(new String[0]));
info.setArguments(newArgs.toArray(String[]::new));

// no need to preload unbuffer in case of running in internal terminal
info.setUnbuffer(false);
Expand Down Expand Up @@ -145,9 +145,8 @@ protected void create() throws Throwable {

String pidLine = null;
String ttyLine = null;
String line;

while ((line = readLine(inputStream)) != null) {
for(String line = readLine(inputStream); line != null; line = readLine(inputStream)) {
line = line.trim();
if (line.isEmpty()) {
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public NativeProcessBuilder setCommandLine(String commandLine) {
}

/**
* Register passed <tt>NativeProcess.Listener</tt>.
* Register passed {@code NativeProcess.Listener}.
*
* @param listener NativeProcess.Listener to be registered to receive
* process's state change events.
Expand Down Expand Up @@ -170,11 +170,8 @@ public NativeProcess call() throws IOException {
throw new UserQuestionException("No connection to " + execEnv.getDisplayName()) {// NOI18N
@Override
public void confirmed() throws IOException {
RequestProcessor.getDefault().post(new Runnable() {
@Override
public void run() {
ConnectionManager.getInstance().connect(execEnv);
}
RequestProcessor.getDefault().post(() -> {
ConnectionManager.getInstance().connect(execEnv);
});
}

Expand All @@ -185,7 +182,7 @@ public String getLocalizedMessage() {
};
}

if (externalTerminal == null && NbStartUtility.getInstance().isSupported(info.getExecutionEnvironment())) {
if (externalTerminal == null && NbStartUtility.getInstance(info.getExecutionEnvironment().isLocal()).isSupported(info.getExecutionEnvironment())) {
if (info.getExecutionEnvironment().isLocal()) {
process = new NbLocalNativeProcess(info);
} else {
Expand All @@ -199,21 +196,17 @@ public String getLocalizedMessage() {
process = new RemoteNativeProcess(info);
} else {
if (externalTerminal != null) {
boolean canProceed = true;
boolean available = externalTerminal.isAvailable(info.getExecutionEnvironment());

if (!available) {
if (Boolean.getBoolean("nativeexecution.mode.unittest") || "true".equals(System.getProperty("cnd.command.line.utility"))) { // NOI18N
System.err.println(loc("NativeProcessBuilder.processCreation.NoTermianl.text"));
} else {
NativeExecutionUserNotification.getDefault().notify(loc("NativeProcessBuilder.processCreation.NoTermianl.text"), // NOI18N
NativeExecutionUserNotification.Descriptor.WARNING);
// DialogDisplayer.getDefault().notify(
// new NotifyDescriptor.Message(loc("NativeProcessBuilder.processCreation.NoTermianl.text"), // NOI18N
// NotifyDescriptor.WARNING_MESSAGE));
NativeExecutionUserNotification.getDefault().notify(loc("NativeProcessBuilder.processCreation.NoTermianl.text"), // NOI18N
NativeExecutionUserNotification.Descriptor.WARNING);
}
canProceed = false;
} else {
boolean canProceed = true;
if (Utilities.isWindows()) {
Shell shell = WindowsSupport.getInstance().getActiveShell();
if (shell == null) {
Expand All @@ -222,9 +215,6 @@ public String getLocalizedMessage() {
} else {
NativeExecutionUserNotification.getDefault().notify(loc("NativeProcessBuilder.processCreation.NoShell.text"), // NOI18N
NativeExecutionUserNotification.Descriptor.WARNING);
// DialogDisplayer.getDefault().notify(
// new NotifyDescriptor.Message(loc("NativeProcessBuilder.processCreation.NoShell.text"), // NOI18N
// NotifyDescriptor.WARNING_MESSAGE));
}
canProceed = false;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* This is a very light-weigth version of ExecutionService from org.netbeans.api.extexecution
* @author ak119685
*/
@SuppressWarnings("deprecation") // org.netbeans.api.extexecution.input.LineProcessor is API
public final class NativeProcessExecutionService {
Comment on lines +37 to 38
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the migration to the new API happened in past already and this is all unused public API by now.

suggestion:

instead of suppressing deprecation warnings, @Deprecate (already unused) newService(...) and the private ExecutionTask class. I believe this communicates a bit better what happened while also having the same effect of not generating javac warnings since a deprecated method may use other deprecated things.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The friend list of dlight.nativeexecution is awefully long. I don't intent to modify the API, so from my POV adding @Deprecated is not correct as the APIs in dlight.nativeexecution are not deprecated.

Copy link
Member

@mbien mbien Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the deprecation note was likely overlooked while implementing the split emilianbold/netbeans-releases@989e691#diff-995af13546863b00d18871524135eb30d93cbf6063e573f1aac795638012e292 since the parameters are deprecated.

Before I noticed that it wasn't used I added a second method and deprecated the first. This way API users are not forced to use deprecated classes.

diff --git a/ide/dlight.nativeexecution/src/org/netbeans/modules/nativeexecution/api/NativeProcessExecutionService.java b/ide/dlight.nativeexecution/src/org/netbeans/modules/nativeexecution/api/NativeProcessExecutionService.java
index de62c90..31194f9 100644
--- a/ide/dlight.nativeexecution/src/org/netbeans/modules/nativeexecution/api/NativeProcessExecutionService.java
+++ b/ide/dlight.nativeexecution/src/org/netbeans/modules/nativeexecution/api/NativeProcessExecutionService.java
@@ -26,7 +26,7 @@
 import java.util.concurrent.Future;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.netbeans.api.extexecution.input.LineProcessor;
+import org.netbeans.api.extexecution.base.input.LineProcessor;
 import org.netbeans.modules.nativeexecution.api.util.ProcessUtils;
 import org.netbeans.modules.nativeexecution.support.NativeTaskExecutorService;
 
@@ -34,7 +34,6 @@
  * This is a very light-weigth version of ExecutionService from org.netbeans.api.extexecution
  * @author ak119685
  */
-@SuppressWarnings("deprecation") // org.netbeans.api.extexecution.input.LineProcessor is API
 public final class NativeProcessExecutionService {
 
     private final ExecutionTask task;
@@ -45,6 +44,14 @@
         this.descr = descr;
     }
 
+    /**
+     * @deprecated Use {@link #newService(NativeProcessBuilder, LineProcessor, LineProcessor, String)} instead.
+     */
+    @Deprecated
+    public static NativeProcessExecutionService newService(NativeProcessBuilder npb, org.netbeans.api.extexecution.input.LineProcessor outProcessor, org.netbeans.api.extexecution.input.LineProcessor errProcessor, String descr) {
+        return newService(npb, new LPWrapper(outProcessor), new LPWrapper(errProcessor), descr);
+    }
+
     public static NativeProcessExecutionService newService(NativeProcessBuilder npb, LineProcessor outProcessor, LineProcessor errProcessor, String descr) {
         ExecutionTask task = new ExecutionTask(npb, outProcessor, errProcessor, descr);
         return new NativeProcessExecutionService(task, descr);
@@ -155,4 +162,30 @@
             return result;
         }
     }
+    
+    @SuppressWarnings("deprecation")
+    private final static class LPWrapper implements LineProcessor {
+
+        private final org.netbeans.api.extexecution.input.LineProcessor delegate;
+        
+        private LPWrapper(org.netbeans.api.extexecution.input.LineProcessor delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public void processLine(String line) {
+            delegate.processLine(line);
+        }
+
+        @Override
+        public void reset() {
+            delegate.reset();
+        }
+
+        @Override
+        public void close() {
+            delegate.close();
+        }
+    }
+    
 }


Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to change/modify/enhance the API. I'm willing to drop the @SuppressWarnings annotations if you consider that more acceptable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok understood. The @SuppressWarnings itself are probably fine - they don't make it worse at least ;). Its just an indication that there never was a followup on the unfinished API split (somewhat similar to #8940).


private final ExecutionTask task;
Expand Down Expand Up @@ -79,17 +80,14 @@ public ExecutionTask(NativeProcessBuilder npb, LineProcessor outProcessor, LineP
this.descr = descr;
}

@Override
public synchronized Integer call() throws Exception {
if (process != null) {
throw new IllegalThreadStateException("Already started!"); // NOI18N
}

int result = -1;

InputStream is = null;
BufferedReader br = null;
Future<Boolean> errorProcessingDone = null;

try {
if (outProcessor != null) {
outProcessor.reset();
Expand All @@ -101,32 +99,26 @@ public synchronized Integer call() throws Exception {

process = npb.call();

errorProcessingDone = NativeTaskExecutorService.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
InputStream is = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = br.readLine()) != null) {
if (errProcessor != null) {
errProcessor.processLine(line);
} else {
ProcessUtils.logError(Level.FINE, log, process);
}
Future<Boolean> errorProcessingDone = NativeTaskExecutorService.submit(() -> {
InputStream is = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for (String line = br.readLine(); line != null; line = br.readLine()) {
if (errProcessor != null) {
errProcessor.processLine(line);
} else {
ProcessUtils.logError(Level.FINE, log, process);
}
return true;
}
return true;
}, "reading process err"); //NOI18N

is = process.getInputStream();
InputStream is = process.getInputStream();

if (is != null) {
// LATER: shouldn't it use ProcessUtils.getReader?
br = new BufferedReader(new InputStreamReader(is));
String line;

try {
while ((line = br.readLine()) != null) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
for (String line = br.readLine(); line != null; line = br.readLine()) {
if (outProcessor != null) {
outProcessor.processLine(line);
}
Expand All @@ -136,6 +128,7 @@ public Boolean call() throws Exception {
Thread.interrupted();
}
}

errorProcessingDone.get(); // just to wait until error processing is done
} catch (Throwable th) {
log.log(Level.FINE, descr, th.getMessage());
Expand All @@ -148,10 +141,6 @@ public Boolean call() throws Exception {
log.log(Level.FINE, descr, th.getMessage());
}

if (br != null) {
br.close();
}

if (process != null) {
try {
result = process.exitValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private Future<Integer> runTerm() {
// Allows user to use his favorite one.
processBuilder.getEnvironment().put("TERM", termType); // NOI18N
} else {
processBuilder.getEnvironment().put("TERM", "xterm" /*IOEmulation.getEmulation(descriptor.inputOutput)*/); // NOI18N
processBuilder.getEnvironment().put("TERM", "xterm-256color" /*IOEmulation.getEmulation(descriptor.inputOutput)*/); // NOI18N
}
} else {
processBuilder.getEnvironment().put("TERM", "dumb"); // NOI18N
Expand Down
Loading
Loading