Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
Launcher | 48 | 123 | 48 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.bin; | |
22 | ||
23 | import java.io.File; | |
24 | import java.lang.management.ManagementFactory; | |
25 | import java.util.ArrayList; | |
26 | import java.util.List; | |
27 | ||
28 | import jalview.bin.argparser.Arg; | |
29 | import jalview.util.ChannelProperties; | |
30 | import jalview.util.ErrorLog; | |
31 | import jalview.util.LaunchUtils; | |
32 | ||
33 | /** | |
34 | * A Launcher class for Jalview. This class is used to launch Jalview from the | |
35 | * shadowJar when Getdown is not used or available. It attempts to take all the | |
36 | * command line arguments to pass on to the jalview.bin.Jalview class, but to | |
37 | * insert a -Xmx memory setting to a sensible default, using the --jvmmempc and | |
38 | * -jvmmemmax application arguments if specified. If not specified then system | |
39 | * properties will be looked for by jalview.bin.MemorySetting. If the user has | |
40 | * provided the JVM with a -Xmx setting directly and not set --jvmmempc or | |
41 | * --jvmmemmax then this setting will be used and system properties ignored. If | |
42 | * -Xmx is set as well as --jvmmempc or --jvmmemmax as argument(s) then the -Xmx | |
43 | * argument will NOT be passed on to the main application launch. | |
44 | * | |
45 | * @author bsoares | |
46 | * | |
47 | */ | |
48 | public class Launcher | |
49 | { | |
50 | private final static String startClass = "jalview.bin.Jalview"; | |
51 | ||
52 | // not setting this yet due to problem with Jmol | |
53 | private final static String headlessProperty = "java.awt.headless"; | |
54 | ||
55 | // used for headless macOS | |
56 | private final static String macosHeadlessProperty = "apple.awt.UIElement"; | |
57 | ||
58 | // arguments that assume headless mode | |
59 | private final static String[] assumeHeadlessArgs = { "headless", "output", | |
60 | "image", "structureimage" }; | |
61 | ||
62 | /** | |
63 | * main method for jalview.bin.Launcher. This restarts the same JRE's JVM with | |
64 | * the same arguments but with memory adjusted based on extracted --jvmmempc | |
65 | * and --jvmmemmax application arguments. If on a Mac then extra dock:icon and | |
66 | * dock:name arguments are also set. | |
67 | * | |
68 | * @param args | |
69 | */ | |
70 | 0 | public static void main(String[] args) |
71 | { | |
72 | 0 | if (!LaunchUtils.checkJavaVersion()) |
73 | { | |
74 | 0 | jalview.bin.Console |
75 | .errPrintln("WARNING - The Java version being used (Java " | |
76 | + LaunchUtils.getJavaVersion() | |
77 | + ") may lead to problems. This installation of Jalview should be used with Java " | |
78 | + LaunchUtils.getJavaCompileVersion() + "."); | |
79 | } | |
80 | ||
81 | 0 | ErrorLog.setPrefix("LAUNCHER - "); |
82 | ||
83 | 0 | String jvmmempc = null; |
84 | 0 | String jvmmemmax = null; |
85 | 0 | boolean debug = false; |
86 | 0 | boolean wait = true; |
87 | 0 | boolean quiet = false; |
88 | 0 | boolean headless = false; |
89 | 0 | boolean assumeheadless = false; |
90 | 0 | boolean gui = false; |
91 | 0 | boolean help = false; |
92 | 0 | boolean stdout = false; |
93 | // must set --debug before --launcher... | |
94 | 0 | boolean launcherstop = false; |
95 | 0 | boolean launcherprint = false; |
96 | 0 | boolean launcherwait = false; |
97 | 0 | ArrayList<String> arguments = new ArrayList<>(); |
98 | 0 | String previousArg = null; |
99 | // set debug first | |
100 | 0 | for (String arg : args) |
101 | { | |
102 | 0 | if (arg.equals("--debug")) |
103 | { | |
104 | 0 | debug = true; |
105 | } | |
106 | } | |
107 | 0 | for (String arg : args) |
108 | { | |
109 | 0 | if (arg.equals("--quiet")) |
110 | { | |
111 | 0 | quiet = true; |
112 | } | |
113 | 0 | else if (arg.equals("--gui")) |
114 | { | |
115 | 0 | gui = true; |
116 | } | |
117 | 0 | else if (arg.equals("--help")) |
118 | { | |
119 | 0 | help = true; |
120 | } | |
121 | 0 | else if (arg.equals("--version")) |
122 | { | |
123 | 0 | help = true; |
124 | } | |
125 | ||
126 | 0 | if (!assumeheadless) |
127 | { | |
128 | 0 | for (String a : assumeHeadlessArgs) |
129 | { | |
130 | 0 | if (arg.equals("--" + a) || arg.startsWith("--" + a + "=")) |
131 | { | |
132 | 0 | assumeheadless = true; |
133 | } | |
134 | } | |
135 | } | |
136 | ||
137 | 0 | if (arg.equals("--output=-") |
138 | || (arg.equals("-") && "--output".equals(previousArg))) | |
139 | { | |
140 | 0 | stdout = true; |
141 | } | |
142 | ||
143 | 0 | if (debug) |
144 | { | |
145 | 0 | if (arg.equals("--launcherprint")) |
146 | { | |
147 | 0 | launcherprint = true; |
148 | } | |
149 | 0 | else if (arg.equals("--launcherstop")) |
150 | { | |
151 | 0 | launcherstop = true; |
152 | } | |
153 | 0 | else if (arg.equals("--launcherwait")) |
154 | { | |
155 | 0 | launcherwait = true; |
156 | } | |
157 | else | |
158 | // this ends the launcher immediately | |
159 | 0 | if (arg.equals("--launchernowait")) |
160 | { | |
161 | 0 | wait = false; |
162 | } | |
163 | } | |
164 | 0 | previousArg = arg; |
165 | // Don't add the --launcher... args to Jalview launch | |
166 | 0 | if (arg.startsWith("--launcher")) |
167 | { | |
168 | 0 | continue; |
169 | } | |
170 | // jvmmempc and jvmmemmax args used to set memory and are not passed on to | |
171 | // startClass | |
172 | 0 | final String jvmmempcArg = Arg.JVMMEMPC.getName(); |
173 | 0 | final String jvmmemmaxArg = Arg.JVMMEMMAX.getName(); |
174 | 0 | if (arg.startsWith("-" + jvmmempcArg + "=")) |
175 | { | |
176 | 0 | jvmmempc = arg.substring(jvmmempcArg.length() + 2); |
177 | } | |
178 | 0 | else if (arg.startsWith("-" + jvmmemmaxArg + "=")) |
179 | { | |
180 | 0 | jvmmemmax = arg.substring(jvmmemmaxArg.length() + 2); |
181 | } | |
182 | // --doubledash versions | |
183 | 0 | else if (arg.startsWith("--" + jvmmempcArg + "=")) |
184 | { | |
185 | 0 | jvmmempc = arg.substring(jvmmempcArg.length() + 3); |
186 | } | |
187 | 0 | else if (arg.startsWith("--" + jvmmemmaxArg + "=")) |
188 | { | |
189 | 0 | jvmmemmax = arg.substring(jvmmemmaxArg.length() + 3); |
190 | } | |
191 | // retain arg | |
192 | else | |
193 | { | |
194 | 0 | arguments.add(arg); |
195 | } | |
196 | } | |
197 | 0 | if (help) |
198 | { | |
199 | // --help takes precedence over --gui | |
200 | 0 | headless = true; |
201 | } | |
202 | 0 | else if (gui) |
203 | { | |
204 | // --gui takes precedence over --headless | |
205 | 0 | headless = false; |
206 | } | |
207 | else | |
208 | { | |
209 | // --output arguments assume headless mode | |
210 | 0 | headless = assumeheadless; |
211 | } | |
212 | ||
213 | 0 | ErrorLog.setQuiet(quiet); |
214 | ||
215 | 0 | final String appName = ChannelProperties.getProperty("app_name"); |
216 | ||
217 | // if we're using jalview.bin.Launcher we always assume a console is in use | |
218 | 0 | final String javaBin = LaunchUtils.findJavaBin(true); |
219 | ||
220 | 0 | List<String> removeJvmArgs = new ArrayList<>(); |
221 | 0 | List<String> addJvmArgs = new ArrayList<>(); |
222 | // command.add(javaBin); | |
223 | ||
224 | 0 | String memSetting = null; |
225 | ||
226 | 0 | List<String> jvmArgs = ManagementFactory.getRuntimeMXBean() |
227 | .getInputArguments(); | |
228 | ||
229 | // use saved preferences if no cmdline args | |
230 | 0 | boolean useCustomisedSettings = LaunchUtils |
231 | .getBooleanUserPreference(MemorySetting.CUSTOMISED_SETTINGS); | |
232 | 0 | if (useCustomisedSettings) |
233 | { | |
234 | 0 | if (jvmmempc == null) |
235 | { | |
236 | 0 | jvmmempc = LaunchUtils |
237 | .getUserPreference(MemorySetting.MEMORY_JVMMEMPC); | |
238 | } | |
239 | 0 | if (jvmmemmax == null) |
240 | { | |
241 | 0 | jvmmemmax = LaunchUtils |
242 | .getUserPreference(MemorySetting.MEMORY_JVMMEMMAX); | |
243 | } | |
244 | } | |
245 | ||
246 | // add these settings if not already specified | |
247 | 0 | boolean memSet = false; |
248 | 0 | boolean dockIcon = false; |
249 | 0 | boolean dockName = false; |
250 | 0 | boolean headlessProp = false; |
251 | 0 | boolean macosHeadlessProp = false; |
252 | 0 | for (int i = 0; i < jvmArgs.size(); i++) |
253 | { | |
254 | 0 | String arg = jvmArgs.get(i); |
255 | 0 | if (arg.startsWith("-Xmx")) |
256 | { | |
257 | // only use -Xmx if jvmmemmax and jvmmempc have not been set | |
258 | 0 | if (jvmmempc == null && jvmmemmax == null) |
259 | { | |
260 | 0 | memSetting = arg; |
261 | 0 | memSet = true; |
262 | } | |
263 | } | |
264 | 0 | else if (arg.startsWith("-Xdock:icon")) |
265 | { | |
266 | 0 | dockIcon = true; |
267 | } | |
268 | 0 | else if (arg.startsWith("-Xdock:name")) |
269 | { | |
270 | 0 | dockName = true; |
271 | } | |
272 | 0 | else if (arg.startsWith("-D" + headlessProperty + "=")) |
273 | { | |
274 | 0 | headlessProp = true; |
275 | } | |
276 | 0 | else if (arg.startsWith("-D" + macosHeadlessProperty + "=")) |
277 | { | |
278 | 0 | macosHeadlessProp = true; |
279 | } | |
280 | } | |
281 | ||
282 | 0 | if (!memSet) |
283 | { | |
284 | 0 | long maxMemLong = MemorySetting.getMemorySetting(jvmmemmax, jvmmempc); |
285 | ||
286 | 0 | if (maxMemLong > 0) |
287 | { | |
288 | 0 | memSetting = "-Xmx" + Long.toString(maxMemLong); |
289 | 0 | memSet = true; |
290 | 0 | addJvmArgs.add(memSetting); |
291 | 0 | removeJvmArgs.add("-Xmx"); |
292 | } | |
293 | } | |
294 | ||
295 | 0 | if (LaunchUtils.isMac) |
296 | { | |
297 | 0 | if (!dockIcon) |
298 | { | |
299 | 0 | String dockIconPath = System.getProperty("launcher.appdir", ".") |
300 | + File.separator + "resource" + File.separator | |
301 | + "jalview_logo.png"; | |
302 | 0 | addJvmArgs.add("-Xdock:icon=" + dockIconPath); |
303 | } | |
304 | 0 | if (!dockName) |
305 | { | |
306 | // -Xdock:name=... doesn't actually work :( | |
307 | // Leaving it in in case it gets fixed | |
308 | 0 | addJvmArgs.add("-Xdock:name=" + appName); |
309 | // This also does not work for the dock | |
310 | 0 | addJvmArgs.add("-Dcom.apple.mrj.application.apple.menu.about.name=" |
311 | + appName); | |
312 | } | |
313 | } | |
314 | 0 | if (headless && !headlessProp) |
315 | { | |
316 | 0 | System.setProperty(headlessProperty, "true"); |
317 | /* not setting this in java invocation of running jalview due to problem with Jmol */ | |
318 | 0 | if (help) |
319 | { | |
320 | 0 | addJvmArgs.add("-D" + headlessProperty + "=true"); |
321 | } | |
322 | } | |
323 | 0 | if (headless && LaunchUtils.isMac && !macosHeadlessProp) |
324 | { | |
325 | 0 | System.setProperty(macosHeadlessProperty, "true"); |
326 | 0 | addJvmArgs.add("-D" + macosHeadlessProperty + "=true"); |
327 | } | |
328 | ||
329 | 0 | String scalePropertyArg = HiDPISetting.getScalePropertyArg(); |
330 | 0 | if (scalePropertyArg != null) |
331 | { | |
332 | 0 | ErrorLog.errPrintln("Running " + startClass + " with scale setting " |
333 | + scalePropertyArg); | |
334 | 0 | addJvmArgs.add(scalePropertyArg); |
335 | } | |
336 | ||
337 | 0 | int exitValue = LaunchUtils.startNewJvm(javaBin, removeJvmArgs, |
338 | addJvmArgs, null, null, null, startClass, null, null, arguments, | |
339 | launcherprint, launcherwait, launcherstop, debug, quiet); | |
340 | ||
341 | 0 | ErrorLog.errPrintln("JVM exited with value " + exitValue); |
342 | } | |
343 | ||
344 | } |