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