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 package ffx;
39
40 import edu.rit.pj.Comm;
41 import edu.rit.pj.cluster.Configuration;
42 import ffx.potential.Utilities;
43 import ffx.ui.LogHandler;
44 import ffx.ui.MainPanel;
45 import ffx.ui.ModelingShell;
46 import ffx.ui.OSXAdapter;
47 import ffx.utilities.FFXScript;
48 import groovy.lang.Script;
49 import org.apache.commons.io.FilenameUtils;
50 import org.apache.commons.lang3.SystemUtils;
51 import org.apache.commons.lang3.builder.ToStringBuilder;
52 import org.apache.commons.lang3.time.StopWatch;
53 import org.apache.log4j.PropertyConfigurator;
54
55 import javax.annotation.Nullable;
56 import javax.swing.ImageIcon;
57 import javax.swing.JFrame;
58 import javax.swing.SwingUtilities;
59 import javax.swing.UIManager;
60 import java.awt.GraphicsEnvironment;
61 import java.awt.Toolkit;
62 import java.awt.event.WindowAdapter;
63 import java.awt.event.WindowEvent;
64 import java.io.File;
65 import java.io.IOException;
66 import java.net.InetAddress;
67 import java.net.URL;
68 import java.net.UnknownHostException;
69 import java.util.ArrayList;
70 import java.util.Arrays;
71 import java.util.Date;
72 import java.util.List;
73 import java.util.Objects;
74 import java.util.Properties;
75 import java.util.logging.Handler;
76 import java.util.logging.Level;
77 import java.util.logging.LogManager;
78 import java.util.logging.Logger;
79
80 import static java.lang.String.format;
81
82
83
84
85
86
87
88 public final class Main extends JFrame {
89
90 private static final Logger logger = Logger.getLogger(Main.class.getName());
91
92 public static MainPanel mainPanel;
93
94 private static StopWatch stopWatch = new StopWatch();
95
96 private static LogHandler logHandler;
97
98 private static int schedulerPort;
99
100 private static Configuration configuration = null;
101
102 private static Comm world = null;
103
104 private static String hostName = null;
105
106 private static int procID = -1;
107
108 private static boolean printVersionAndExit = false;
109
110 private final Runnable initGUI =
111 new Runnable() {
112
113 public void run() {
114
115 Toolkit.getDefaultToolkit().setDynamicLayout(true);
116
117
118 Main.this.setTitle("Force Field X");
119 URL iconURL = getClass().getClassLoader().getResource("ffx/ui/icons/icon64.png");
120 if (iconURL != null) {
121 ImageIcon icon = new ImageIcon(iconURL);
122 Main.this.setIconImage(icon.getImage());
123 }
124 Main.this.addWindowListener(
125 new WindowAdapter() {
126 @Override
127 public void windowClosing(WindowEvent e) {
128 if (mainPanel != null) {
129 mainPanel.exit();
130 }
131 System.exit(0);
132 }
133 });
134
135 mainPanel = new MainPanel(Main.this);
136 mainPanel.setVisible(false);
137 logHandler.setMainPanel(mainPanel);
138 Main.this.add(mainPanel);
139 mainPanel.initialize();
140 Main.this.setVisible(true);
141 mainPanel.setVisible(true);
142 Main.this.setJMenuBar(mainPanel.getMainMenu());
143
144
145
146
147
148
149
150
151
152 if (SystemUtils.IS_OS_MAC_OSX) {
153 OSXAdapter osxAdapter = new OSXAdapter(mainPanel);
154 }
155
156 SwingUtilities.updateComponentTreeUI(SwingUtilities.getRoot(Main.this));
157 }
158 };
159
160
161
162
163
164
165
166 public Main(@Nullable File commandLineFile, List<String> argList) {
167 super("Force Field X");
168
169 stopWatch.start();
170
171
172 try {
173 SwingUtilities.invokeAndWait(initGUI);
174 } catch (Exception e) {
175 logger.warning(" Exception initializing the GUI.\n" + e);
176 }
177
178
179 if (commandLineFile != null) {
180 runScript(mainPanel.getModelingShell(), commandLineFile, argList);
181 }
182
183 if (logger.isLoggable(Level.FINE)) {
184 StringBuilder sb = new StringBuilder();
185 sb.append(format("\n Start-up Time (msec): %s.", stopWatch.getTime()));
186 Runtime runtime = Runtime.getRuntime();
187 runtime.gc();
188 long occupiedMemory = runtime.totalMemory() - runtime.freeMemory();
189 long KB = 1024;
190 sb.append(format("\n In-Use Memory (Kb): %d", occupiedMemory / KB));
191 sb.append(format("\n Free Memory (Kb): %d", runtime.freeMemory() / KB));
192 sb.append(format("\n Total Memory (Kb): %d", runtime.totalMemory() / KB));
193 logger.fine(sb.toString());
194 }
195 }
196
197
198
199
200
201
202 public static void main(String[] args) {
203
204 List<String> argList = new ArrayList<>();
205 File commandLineFile = initMain(args, argList);
206
207 try {
208
209 if (!GraphicsEnvironment.isHeadless()) {
210 startGraphicalUserInterface(commandLineFile, argList);
211 } else {
212 if (commandLineFile == null) {
213 logger.info(" No command line file supplied.");
214 } else {
215 startCommandLineInterface(commandLineFile, argList);
216 }
217 }
218 } catch (Throwable t) {
219 int statusCode = 1;
220 logger.info(" Uncaught exception: exiting with status code " + statusCode);
221 logger.info(Utilities.stackTraceToString(t));
222 System.exit(statusCode);
223 }
224 }
225
226
227
228
229
230
231
232
233
234 public static File initMain(String[] args, List<String> argList) {
235
236 args = processProperties(args);
237
238
239 startParallelJava(args);
240
241
242 startLogging();
243
244
245 environment();
246
247
248 header(args);
249
250
251 if (GraphicsEnvironment.isHeadless() && args.length < 2) {
252 if (args.length == 1 && args[0].toUpperCase().contains("TEST")) {
253 commandLineInterfaceHelp(true);
254 }
255 commandLineInterfaceHelp(false);
256 }
257
258
259 File commandLineFile = null;
260 int nArgs = args.length;
261 if (nArgs > 0) {
262 commandLineFile = new File(args[0]);
263
264 if (commandLineFile.exists()) {
265 commandLineFile = new File(FilenameUtils.normalize(commandLineFile.getAbsolutePath()));
266 }
267 }
268
269
270 if (nArgs > 1) {
271 argList.addAll(Arrays.asList(args).subList(1, nArgs));
272 }
273
274 return commandLineFile;
275 }
276
277
278
279
280
281
282
283 public static Script ffxScript(String[] args) {
284 List<String> argList = new ArrayList<>();
285 File commandLineFile = initMain(args, argList);
286 try {
287 if (commandLineFile == null) {
288 logger.info(" No command line file supplied.");
289 } else {
290 return startCommandLineInterface(commandLineFile, argList);
291 }
292 } catch (Throwable t) {
293 int statusCode = 1;
294 logger.info(" Uncaught exception: exiting with status code " + statusCode);
295 logger.info(Utilities.stackTraceToString(t));
296 System.exit(statusCode);
297 }
298 return null;
299 }
300
301
302 private static void commandLineInterfaceHelp(boolean listTestScripts) {
303 logger.info(" usage: ffxc [-D<property=value>] <command> [-options] <PDB|XYZ>");
304 if (listTestScripts) {
305 FFXScript.listGroovyScripts(false, true);
306 logger.info("\n For help on an experimental or test command use: ffxc <command> -h\n");
307 } else {
308 FFXScript.listGroovyScripts(true, false);
309 logger.info("\n To list experimental & test scripts: ffxc --test");
310 logger.info(" For help on a specific command use: ffxc <command> -h\n");
311 }
312 System.exit(0);
313 }
314
315
316 private static void environment() {
317 try {
318 InetAddress addr = InetAddress.getLocalHost();
319 hostName = addr.getHostName();
320 } catch (UnknownHostException e) {
321
322 }
323
324 String procString = System.getProperty("app.pid");
325 if (procString != null) {
326 procID = Integer.parseInt(procString);
327 } else {
328 procID = 0;
329 }
330
331 String dirString = System.getProperty("basedir");
332 File ffxDirectory;
333 if (dirString != null) {
334 ffxDirectory = new File(dirString);
335 } else {
336 ffxDirectory = new File(".");
337 }
338
339 try {
340 logger.fine(format(" Force Field X directory is %s", ffxDirectory.getCanonicalPath()));
341 } catch (Exception e) {
342
343 }
344 }
345
346
347 private static void header(String[] args) {
348 StringBuilder sb = new StringBuilder();
349 sb.append(MainPanel.border).append("\n");
350 sb.append(MainPanel.title).append("\n");
351 sb.append(MainPanel.aboutString).append("\n");
352 sb.append(MainPanel.border);
353
354
355 if (printVersionAndExit && GraphicsEnvironment.isHeadless()) {
356 logger.info(sb.toString());
357 System.exit(0);
358 }
359
360 sb.append("\n ").append(new Date());
361 sb.append(format("\n Process ID %d on %s.", procID, hostName));
362
363
364 if (args != null && args.length > 0) {
365 sb.append("\n\n Command line arguments:\n ");
366 sb.append(Arrays.toString(args));
367 sb.append("\n");
368 }
369
370 if (schedulerPort > 1) {
371 sb.append(format("\n Parallel Java:\n %s", world.toString()));
372 if (configuration != null) {
373 sb.append(
374 format(
375 "\n Scheduler %s on port %d.\n", configuration.getSchedulerHost(), schedulerPort));
376 }
377 }
378
379 logger.info(sb.toString());
380 }
381
382
383 private static String[] processProperties(String[] args) {
384 List<String> newArgs = new ArrayList<>();
385 for (String arg : args) {
386 arg = arg.trim();
387
388 if (arg.equals("-V") || arg.equals("--version")) {
389 printVersionAndExit = true;
390 }
391
392 if (arg.startsWith("-D")) {
393
394 arg = arg.substring(2);
395
396 if (arg.contains("=")) {
397 int equalsPosition = arg.indexOf("=");
398 String key = arg.substring(0, equalsPosition);
399 String value = arg.substring(equalsPosition + 1);
400
401 System.setProperty(key, value);
402 } else {
403 if (!arg.isEmpty()) {
404 System.setProperty(arg, "");
405 }
406 }
407 } else {
408
409 newArgs.add(arg);
410 }
411 }
412
413 args = new String[newArgs.size()];
414 newArgs.toArray(args);
415 return args;
416 }
417
418
419
420
421
422
423
424 private static Script startCommandLineInterface(File commandLineFile, List<String> argList) {
425 if (configuration == null) {
426 logger.info(" Starting up the command line interface.\n");
427 }
428 HeadlessMain m = new HeadlessMain(logHandler);
429 mainPanel = m.mainPanel;
430 return runScript(mainPanel.getModelingShell(), commandLineFile, argList);
431 }
432
433
434
435
436
437
438
439 private static void startGraphicalUserInterface(File commandLineFile, List<String> argList) {
440 logger.info(" Starting up the graphical user interface.");
441
442
443 UIManager.put("swing.boldMetal", Boolean.FALSE);
444 setDefaultLookAndFeelDecorated(false);
445
446
447
448
449
450 if (SystemUtils.IS_OS_MAC_OSX) {
451 OSXAdapter.setOSXProperties();
452 try {
453 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
454 } catch (Exception e) {
455
456 }
457 }
458
459
460 new Main(commandLineFile, argList);
461 }
462
463
464 private static void startLogging() {
465
466 try {
467 Logger defaultLogger = LogManager.getLogManager().getLogger("");
468 Handler[] defaultHandlers = defaultLogger.getHandlers();
469 for (Handler h : defaultHandlers) {
470 defaultLogger.removeHandler(h);
471 }
472 } catch (Exception e) {
473 String error = e.toString();
474 System.err.println(error);
475 }
476
477
478 Properties properties = new Properties();
479 properties.setProperty("log4j.threshold", "OFF");
480 properties.setProperty("log4j2.level", "OFF");
481 properties.setProperty("org.apache.logging.log4j.level", "OFF");
482 PropertyConfigurator.configure(properties);
483
484 Logger ffxLogger = Logger.getLogger("ffx");
485
486 for (Handler handler : ffxLogger.getHandlers()) {
487 ffxLogger.removeHandler(handler);
488 }
489
490
491 String logLevel = System.getProperty("ffx.log", "info");
492 Level tempLevel;
493 try {
494 tempLevel = Level.parse(logLevel.toUpperCase());
495 } catch (Exception e) {
496 tempLevel = Level.INFO;
497 }
498
499 Level level = tempLevel;
500 logHandler = new LogHandler();
501 logHandler.setLevel(level);
502 ffxLogger.addHandler(logHandler);
503 ffxLogger.setLevel(level);
504 }
505
506
507 private static void startParallelJava(String[] args) {
508
509
510 try {
511 configuration = new Configuration("cluster.txt");
512 } catch (IOException e) {
513
514 }
515
516
517 String numNodes = System.getProperty("pj.nn");
518 int requestedNodes = -1;
519 if (numNodes != null) {
520 try {
521 requestedNodes = Integer.parseInt(numNodes);
522 } catch (Exception e) {
523
524 }
525 }
526
527
528 String portString = System.getProperty("pj.port");
529 schedulerPort = -1;
530 if (portString != null) {
531 try {
532 schedulerPort = Integer.parseInt(portString);
533 } catch (Exception e) {
534
535 }
536 }
537
538
539 if (schedulerPort <= 0) {
540 if (requestedNodes <= 0) {
541
542 schedulerPort = 1;
543 } else if (configuration != null) {
544
545 schedulerPort = configuration.getSchedulerPort();
546 } else {
547
548 schedulerPort = 20617;
549 }
550 System.setProperty("pj.port", Integer.toString(schedulerPort));
551 }
552
553 try {
554 Comm.init(args);
555 world = Comm.world();
556 } catch (Exception e) {
557
558 String message = " Exception starting up the Parallel Java communication layer.";
559 System.err.println(message);
560 String error = e.toString();
561 System.err.println(error);
562 }
563 }
564
565 public static Script runScript(ModelingShell shell, File commandLineFile, List<String> argList) {
566
567 if (commandLineFile.exists()) {
568 return shell.runFFXScript(commandLineFile, argList);
569 } else {
570
571 String name = commandLineFile.getName();
572 Class<? extends Script> ffxScript = FFXScript.getScript(name);
573 if (ffxScript != null) {
574 return shell.runFFXScript(ffxScript, argList);
575 }
576 }
577 return null;
578 }
579
580
581
582
583
584
585 @Override
586 public String toString() {
587 ToStringBuilder toStringBuilder =
588 new ToStringBuilder(this)
589 .append("Up Time: " + stopWatch)
590 .append("Logger: " + logger.getName());
591 return toStringBuilder.toString();
592 }
593 }