-
Notifications
You must be signed in to change notification settings - Fork 9
/
MachineConfig.cs
executable file
·234 lines (205 loc) · 9.29 KB
/
MachineConfig.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
using System;
using System.Diagnostics;
using System.Globalization;
using System.Text.RegularExpressions;
namespace FreenetTray {
public enum JREType {
None,
JRE64Bit,
JRE32Bit,
}
public class MissingJRE: Exception { }
public class MachineConfig
{
private static bool isJVM8 = false;
///<summary>
/// Read the wrapper.conf file.
/// Read java.command, run it to detect x86/x64 JVM and java version.
/// Then adjust wrapper.conf with correct launch parameters
/// for Java 8 or Java 9+.
///</summary>
public static void CheckConfig(string pathConfig)
{
string pathJVM;
string[] lines = System.IO.File.ReadAllLines(pathConfig);
for (int i = 0; i < lines.Length; i++)
{
string line = lines[i];
/* ================================
* CHECK AND RUN JAVA COMMAND
*
*/
if (line.StartsWith("wrapper.java.command="))
{
string[] javcmd = Regex.Split(line, @"wrapper.java.command=");
if (javcmd.Length == 2)
{
if (javcmd[1].Length == 0) // empty string: no custom java.exe
{
lines[i] = "wrapper.java.command=java";
pathJVM = "java";
}
else
{
pathJVM = javcmd[1];
}
// launch JVM to get more info
GetJVMinfo(pathJVM);
}
else
{
FNLog.Debug("ERROR: Invalid 'wrapper.java.command' in wrapper.conf.");
}
}
/* ================================
* ENABLE OR DISABLE LAUNCH PARAMETERS FOR JAVA8 OR JAVA 9+
*
*/
if (line.StartsWith("wrapper.java.additional."))
{
if (isJVM8 &&
(line.Contains("--illegal-access=permit") ||
line.Contains("--add-opens=java.base/java.lang=ALL-UNNAMED") ||
line.Contains("--add-opens=java.base/java.util=ALL-UNNAMED") ||
line.Contains("--add-opens=java.base/java.io=ALL-UNNAMED")))
{
lines[i] = "# " + line;
FNLog.Debug("Disabling additional launch parameters.");
}
}
else if (line.StartsWith("#wrapper.java.additional.") ||
line.StartsWith("# wrapper.java.additional."))
{
if (!isJVM8 &&
(line.Contains("--illegal-access=permit") ||
line.Contains("--add-opens=java.base/java.lang=ALL-UNNAMED") ||
line.Contains("--add-opens=java.base/java.util=ALL-UNNAMED") ||
line.Contains("--add-opens=java.base/java.io=ALL-UNNAMED")))
{
lines[i] = line.Replace("# ", "").Replace("#", "");
FNLog.Debug("Enabling additional launch parameters.");
}
}
}
System.IO.File.WriteAllLines(pathConfig, lines); // overwrites file without warning
}
private static void GetJVMinfo(string pathJVM)
{
/* ================================
* Only run if the installer started tray.exe with "-welcome" arg.
* If OS did not have Java installed, the Freenet installer installed a JVM.
* This JVM's java.exe can be found in PATH.
* Problem: Installer starts tray.exe with old environment variables,
* meaning PATH does not contain Java.exe at this point.
* This results in "JVM not found" error.
* Solution: Read environment variables again.
*
*/
foreach (var arg in Environment.GetCommandLineArgs())
{
if( arg.Equals("-welcome") )
{
string machineEnv = System.Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
string currentEnv = System.Environment.GetEnvironmentVariable("Path");
if( !machineEnv.Equals(currentEnv) )
{
System.Environment.SetEnvironmentVariable("Path", machineEnv);
}
break;
}
}
/* ================================
* RUN JAVA AND GET JVM INFO
*
*/
using (System.Diagnostics.Process pProcess = new System.Diagnostics.Process())
{
pProcess.StartInfo.FileName = pathJVM;
pProcess.StartInfo.Arguments = "-XshowSettings:all";
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.RedirectStandardError = true; // java.exe writes this to StdErr
pProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
pProcess.StartInfo.CreateNoWindow = true;
string output = string.Empty;
pProcess.OutputDataReceived += (sender, args) => output += args.Data;
pProcess.ErrorDataReceived += (sender, args) => output += args.Data;
try
{
pProcess.Start();
pProcess.BeginOutputReadLine();
pProcess.BeginErrorReadLine();
pProcess.WaitForExit(5 * 1000); // 5s timeout
/* ================================
* CHECK JAVA.SPECIFICATION.VERSION
*
*/
// jvmVersion will be "" in case nothing was found in output
// can be "1.8" for Java 8, or, starting with Java 9, just "9", "10", ...
// you must not use "java.version" as this can be different for early access versions ("19-ea" instead of "19")
string jvmVersion = Regex.Match(output, @"java\.specification\.version = (\S+)").Groups[1].Value;
if (jvmVersion.Length != 0)
{
try
{
float fjvmVersion = float.Parse(jvmVersion, CultureInfo.InvariantCulture);
if (fjvmVersion < 1.9)
{
isJVM8 = true;
FNLog.Debug("JVM 8 detected.");
}
else
{
isJVM8 = false;
FNLog.Debug("JVM 9 or higher detected.");
}
}
catch (Exception e)
{
FNLog.Debug("ERROR converting to float:");
FNLog.Debug(e.ToString());
}
}
else
{
// inform user, but try starting Freenet anyway
// TODO: Adjust this in the future to default to JVM9+
FNLog.Debug("No java.specification.version found. Assuming JVM8.");
isJVM8 = true;
}
/* ================================
* CHECK JAVA 64-BIT OR 32-BIT
*
*/
// osArch will be "" in case nothing was found in output
string osArch = Regex.Match(output, @"os\.arch = (\w+)").Groups[1].Value;
if (osArch.Length != 0)
{
// os.arch on Windows can have four values: https://github.com/openjdk/jdk/blob/master/src/java.base/windows/native/libjava/java_props_md.c
if (osArch.Equals("amd64") || osArch.Equals("aarch64"))
{
GetBestAvailableJRE = JREType.JRE64Bit;
FNLog.Debug("64-bit JVM found");
}
else if (osArch.Equals("x86"))
{
GetBestAvailableJRE = JREType.JRE32Bit;
FNLog.Debug("32-bit JVM found");
}
}
else
{
GetBestAvailableJRE = JREType.None;
FNLog.Debug("No JVM found");
}
}
catch (Exception e)
{
Debug.WriteLine("ERROR running JVM:");
Debug.WriteLine(e.ToString());
}
}
}
public static JREType GetBestAvailableJRE { get; private set; } = JREType.None;
}
}