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