Skip to content

Commit 8324b37

Browse files
committed
Fix NetBeans launch failure on unix shell for arguments with quotes et al
Backporting Netbeans PR #7908 (still under review) in order for the LSP server launch to work for launch arguments including the project path containing special characters like quotes, spaces, backticks and $. This is an interim patch to mitigate the effect on user experience, while the upstream PR is under review. It will be updated to the approved patch, as and when it is made available. This is partially related to #301, which only fixes for spaces in arguments. Additionally, the same diff is applied to script/bin/nbcode which is a copy of the netbeans java.lsp.server module's copy. Signed-off-by: Siddharth Srinivasan <[email protected]>
1 parent 1861da0 commit 8324b37

File tree

3 files changed

+253
-4
lines changed

3 files changed

+253
-4
lines changed

build.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
patches/7724.diff
5757
patches/7733.diff
5858
patches/7750.diff
59+
patches/7908-draft.diff
5960
patches/7910.diff
6061
patches/7921.diff
6162
patches/7923_draft.diff

patches/7908-draft.diff

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
diff --git a/java/java.lsp.server/script/bin/nbcode b/java/java.lsp.server/script/bin/nbcode
2+
index 326fe2d08a89..cea526130b6f 100755
3+
--- a/java/java.lsp.server/script/bin/nbcode
4+
+++ b/java/java.lsp.server/script/bin/nbcode
5+
@@ -52,7 +52,20 @@ if [ -f "$progdir/../etc/$APPNAME".conf ] ; then
6+
. "$progdir/../etc/$APPNAME".conf
7+
fi
8+
9+
-# XXX does not correctly deal with spaces in non-userdir params
10+
+doubleQuoteArg() {
11+
+ # wrap all arguments as "" strings, escape any internal back-slash, double-quote, $, or back-tick characters
12+
+ # use printf to avoid echo interpretation behaviors such as escapes and line continuation
13+
+ # Mac bsd_sed does not support group-0, so pattern uses group-1
14+
+ printf '"%s"' "`printf '%s' "$@" | sed -e 's@\([$\"\`\\]\)@\\\\\\1@g' `"
15+
+}
16+
+
17+
+singleQuoteArg() {
18+
+ # wrap all arguments as '' strings, escaping any internal single-quote characters
19+
+ # use printf to avoid echo interpretation behaviors such as escapes and line continuation
20+
+ # Mac bsd_sed does not support group-0, so pattern uses group-1
21+
+ printf "'%s'" "`printf '%s' "$@" | sed -e 's@'\''@'\''\\\\'\'''\''@g' `"
22+
+}
23+
+
24+
args=""
25+
26+
case "`uname`" in
27+
@@ -69,9 +82,11 @@ case "`uname`" in
28+
esac
29+
while [ $# -gt 0 ] ; do
30+
case "$1" in
31+
+ --jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome="$1"; fi
32+
+ ;;
33+
--userdir) shift; if [ $# -gt 0 ] ; then userdir="$1"; fi
34+
;;
35+
- *) args="$args \"$1\""
36+
+ *) args="$args `doubleQuoteArg \"$1\" `"
37+
;;
38+
esac
39+
shift
40+
@@ -121,8 +136,8 @@ case "`uname`" in
41+
Darwin*)
42+
eval exec sh '"$nbexec"' \
43+
--jdkhome '"$jdkhome"' \
44+
- -J-Xdock:name='"$APPNAME"' \
45+
- '"-J-Xdock:icon=$progdir/../../$APPNAME.icns"' \
46+
+ '-J-Xdock:name="$APPNAME"' \
47+
+ '-J-Xdock:icon="$progdir/../../$APPNAME.icns"' \
48+
--clusters '"$clusters"' \
49+
--userdir '"${userdir}"' \
50+
${default_options} \
51+
diff --git a/platform/o.n.bootstrap/launcher/unix/nbexec b/platform/o.n.bootstrap/launcher/unix/nbexec
52+
index 1d6ad6e53019..abac07411d43 100755
53+
--- a/platform/o.n.bootstrap/launcher/unix/nbexec
54+
+++ b/platform/o.n.bootstrap/launcher/unix/nbexec
55+
@@ -56,6 +56,20 @@ postfixcp=""
56+
57+
updater_class=org.netbeans.updater.UpdaterFrame
58+
59+
+doubleQuoteArg() {
60+
+ # wrap all arguments as "" strings, escape any internal back-slash, double-quote, $, or back-tick characters
61+
+ # use printf to avoid echo interpretation behaviors such as escapes and line continuation
62+
+ # Mac bsd_sed does not support group-0, so pattern uses group-1
63+
+ printf '"%s"' "`printf '%s' "$@" | sed -e 's@\([$\"\`\\]\)@\\\\\\1@g' `"
64+
+}
65+
+
66+
+singleQuoteArg() {
67+
+ # wrap all arguments as '' strings, escaping any internal single-quote characters
68+
+ # use printf to avoid echo interpretation behaviors such as escapes and line continuation
69+
+ # Mac bsd_sed does not support group-0, so pattern uses group-1
70+
+ printf "'%s'" "`printf '%s' "$@" | sed -e 's@'\''@'\''\\\\'\'''\''@g' `"
71+
+}
72+
+
73+
#
74+
# parse arguments
75+
#
76+
@@ -85,7 +99,7 @@ EOF
77+
nogui="nogui";
78+
args="$args --nogui"
79+
;;
80+
- --jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome=$1; fi
81+
+ --jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome="$1"; fi
82+
;;
83+
# this has to be here for purposes of updater.jar, but it should be
84+
# better to handle this argument inside the java launcher part
85+
@@ -117,8 +131,8 @@ EOF
86+
-psn*)
87+
shift;
88+
;;
89+
- -J*) jopt=`expr "X-$1" : 'X--J\(.*\)'`; jargs="$jargs '$jopt'";;
90+
- *) args="$args \"$1\"" ;;
91+
+ -J*) jopt=`expr "X-$1" : 'X--J\(.*\)'`; jargs="$jargs `singleQuoteArg \"$jopt\" `";;
92+
+ *) args="$args `doubleQuoteArg \"$1\" `";;
93+
esac
94+
shift
95+
done
96+
@@ -187,27 +201,27 @@ fi
97+
98+
jargs="$jargs -XX:+HeapDumpOnOutOfMemoryError"
99+
if [ -z "`echo $jargs | grep -- "-XX:HeapDumpPath="`" ] ; then
100+
- jargs="$jargs -XX:HeapDumpPath=\"${userdir}/var/log/heapdump.hprof\""
101+
+ jargs="$jargs -XX:HeapDumpPath=`doubleQuoteArg \"${userdir}/var/log/heapdump.hprof\" `"
102+
fi
103+
# rename old heap dump to .old
104+
mv "${userdir}/var/log/heapdump.hprof" "${userdir}/var/log/heapdump.hprof.old" > /dev/null 2>&1
105+
106+
jargs_without_clusters="$jargs -Djava.security.manager=allow"
107+
-jargs="-Dnetbeans.dirs=\"${clusters}\" $jargs_without_clusters"
108+
+jargs="-Dnetbeans.dirs=`doubleQuoteArg \"${clusters}\" ` $jargs_without_clusters"
109+
110+
if [ -z "$cachedirspecified" ]; then
111+
cachedir="${userdir}/var/cache"
112+
fi
113+
114+
if [ `uname` != Darwin -a -z "$nosplash" -a -f "${cachedir}/splash.png" -a ! -f "${userdir}/lock" ]; then
115+
- jargs="$jargs -splash:\"${cachedir}/splash.png\""
116+
+ jargs="$jargs -splash:`doubleQuoteArg \"${cachedir}/splash.png\" `"
117+
fi
118+
119+
jdkhome=`absolutize_path "$jdkhome"`
120+
121+
-args="--userdir \"${userdir}\" $args"
122+
+args="--userdir `doubleQuoteArg \"${userdir}\"` $args"
123+
124+
-args="--cachedir \"${cachedir}\" $args"
125+
+args="--cachedir `doubleQuoteArg \"${cachedir}\"` $args"
126+
127+
append_jars_to_cp() {
128+
dir="$1"
129+
@@ -279,7 +293,7 @@ build_cp() {
130+
}
131+
132+
do_run_updater() {
133+
- eval "\"$jdkhome/bin/java\"" -classpath "\"${updatercp}\"" "$jargs" "-Dnetbeans.user=\"$userdir\"" $updater_class "$args"
134+
+ eval '"$jdkhome/bin/java"' -classpath '"${updatercp}"' "$jargs" '-Dnetbeans.user="$userdir"' $updater_class "$args"
135+
construct_cp
136+
}
137+
138+
@@ -360,7 +374,7 @@ else
139+
fi
140+
141+
if [ ! -z "${DEFAULT_USERDIR_ROOT}" ] ; then
142+
- jargs="-Dnetbeans.default_userdir_root=\"${DEFAULT_USERDIR_ROOT}\" $jargs"
143+
+ jargs="-Dnetbeans.default_userdir_root=`doubleQuoteArg \"${DEFAULT_USERDIR_ROOT}\"` $jargs"
144+
unset DEFAULT_USERDIR_ROOT
145+
fi
146+
147+
@@ -427,7 +441,7 @@ while [ "$restart" ] ; do
148+
#
149+
delete_new_clusters_file
150+
rm -f "${restart_file}"
151+
- eval ${_NB_PROFILE_CMD} "\"${jdkhome}/bin/java\"" -Djdk.home="\"${jdkhome}\"" -classpath "\"$cp\"" \
152+
+ eval ${_NB_PROFILE_CMD} '"${jdkhome}/bin/java"' '-Djdk.home="${jdkhome}"' -classpath '"$cp"' \
153+
"$jargs" org.netbeans.Main "$args" '<&0' '&'
154+
PID=$!
155+
trap "kill $PID" EXIT
156+
diff --git a/platform/o.n.bootstrap/test/unit/src/org/netbeans/nbexec/NbExecPassesCorrectlyQuotedArgsTest.java b/platform/o.n.bootstrap/test/unit/src/org/netbeans/nbexec/NbExecPassesCorrectlyQuotedArgsTest.java
157+
index 3ccd38505fed..91923d6e4118 100644
158+
--- a/platform/o.n.bootstrap/test/unit/src/org/netbeans/nbexec/NbExecPassesCorrectlyQuotedArgsTest.java
159+
+++ b/platform/o.n.bootstrap/test/unit/src/org/netbeans/nbexec/NbExecPassesCorrectlyQuotedArgsTest.java
160+
@@ -22,9 +22,14 @@
161+
import java.io.IOException;
162+
import java.io.InputStream;
163+
import java.net.URL;
164+
+import java.nio.file.Files;
165+
+import java.nio.file.Path;
166+
import java.util.Arrays;
167+
import java.util.LinkedList;
168+
import java.util.List;
169+
+import java.util.Objects;
170+
+import java.util.stream.Collectors;
171+
+import java.util.stream.Stream;
172+
import org.netbeans.junit.NbTestCase;
173+
import org.openide.util.Lookup;
174+
import org.openide.util.Utilities;
175+
@@ -77,7 +82,57 @@ public void testStartsArePassedInUnparsed() throws Exception {
176+
fail(str + " should be there: " + a);
177+
}
178+
}
179+
-
180+
+
181+
+ public void testJdkHomePassed() throws Exception {
182+
+ File wd = new File(getWorkDir(), "jdk dir");
183+
+ wd.mkdirs();
184+
+ String origJdkHome = System.getProperty("java.home");
185+
+ Path origJdk = new File(origJdkHome).toPath();
186+
+ String[] linkNames = {
187+
+ "openjdk's jdkhome",
188+
+ "jdk \"latest\"",
189+
+ "current$JAVA_HOME",
190+
+ "link\"'d jdk"
191+
+ };
192+
+ Path[] links = new Path[linkNames.length];
193+
+ for (int i = 0; i < linkNames.length; i++) {
194+
+ links[i] = new File(wd, linkNames[i]).toPath();
195+
+ }
196+
+
197+
+ String[] args = {
198+
+ "1 * * * *",
199+
+ "a b",
200+
+ "c d",
201+
+ "$1",
202+
+ "$2",
203+
+ "$3\"`$2`'$1"
204+
+ };
205+
+
206+
+ for (Path link : links) {
207+
+ try {
208+
+ Path l = Files.createSymbolicLink(link, origJdk);
209+
+ if (link.compareTo(l) != 0) {
210+
+ fail("link creation mismatch: expected<" + link + "> != actual<" + l + ">");
211+
+ }
212+
+ System.setProperty("java.home", link.toString());
213+
+ String[] nbArgs = {
214+
+ "--jdkhome",
215+
+ link.toString()
216+
+ };
217+
+ run(wd, Stream.concat(Arrays.stream(nbArgs), Arrays.stream(args)).collect(Collectors.toList()).toArray(new String[]{}));
218+
+
219+
+ String[] gotArgs = MainCallback.getArgs(getWorkDir());
220+
+ assertNotNull("args passed in", gotArgs);
221+
+ for (int in = args.length, jn = gotArgs.length, i = 0, j = Math.max(0, jn - in); i < in ; i++, j++) {
222+
+ if (j >= jn || !Objects.equals(args[i], gotArgs[j]))
223+
+ fail("args do not match: expected<" + Arrays.toString(args) + "> != actual<" + Arrays.toString(gotArgs) + ">");
224+
+ }
225+
+ } finally {
226+
+ System.setProperty("java.home", origJdkHome);
227+
+ Files.delete(link);
228+
+ }
229+
+ }
230+
+ }
231+
232+
private void run(File workDir, String... args) throws Exception {
233+
URL u = Lookup.class.getProtectionDomain().getCodeSource().getLocation();

script/bin/nbcode

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,20 @@ if [ -f "$progdir/../etc/$APPNAME".conf ] ; then
5252
. "$progdir/../etc/$APPNAME".conf
5353
fi
5454

55-
# XXX does not correctly deal with spaces in non-userdir params
55+
doubleQuoteArg() {
56+
# wrap all arguments as "" strings, escape any internal back-slash, double-quote, $, or back-tick characters
57+
# use printf to avoid echo interpretation behaviors such as escapes and line continuation
58+
# Mac bsd_sed does not support group-0, so pattern uses group-1
59+
printf '"%s"' "`printf '%s' "$@" | sed -e 's@\([$\"\`\\]\)@\\\\\\1@g' `"
60+
}
61+
62+
singleQuoteArg() {
63+
# wrap all arguments as '' strings, escaping any internal single-quote characters
64+
# use printf to avoid echo interpretation behaviors such as escapes and line continuation
65+
# Mac bsd_sed does not support group-0, so pattern uses group-1
66+
printf "'%s'" "`printf '%s' "$@" | sed -e 's@'\''@'\''\\\\'\'''\''@g' `"
67+
}
68+
5669
args=""
5770

5871
case "`uname`" in
@@ -69,9 +82,11 @@ case "`uname`" in
6982
esac
7083
while [ $# -gt 0 ] ; do
7184
case "$1" in
85+
--jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome="$1"; fi
86+
;;
7287
--userdir) shift; if [ $# -gt 0 ] ; then userdir="$1"; fi
7388
;;
74-
*) args="$args \"$1\""
89+
*) args="$args `doubleQuoteArg \"$1\" `"
7590
;;
7691
esac
7792
shift
@@ -121,8 +136,8 @@ case "`uname`" in
121136
Darwin*)
122137
eval exec sh '"$nbexec"' \
123138
--jdkhome '"$jdkhome"' \
124-
-J-Xdock:name='"$APPNAME"' \
125-
'"-J-Xdock:icon=$progdir/../../$APPNAME.icns"' \
139+
'-J-Xdock:name="$APPNAME"' \
140+
'-J-Xdock:icon="$progdir/../../$APPNAME.icns"' \
126141
--clusters '"$clusters"' \
127142
--userdir '"${userdir}"' \
128143
${default_options} \

0 commit comments

Comments
 (0)