-
Notifications
You must be signed in to change notification settings - Fork 2
/
App.java
789 lines (738 loc) · 32.2 KB
/
App.java
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package tappas;
import javafx.application.Platform;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TabPane;
import javafx.stage.Window;
import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
/**
*
* @author Hector del Risco - [email protected] & Pedro Salguero - [email protected]
*/
public class App {
// minimum application requirements
static final int MIN_CPUS = 4;
static final double MIN_MEMORY = 1.2; //aprox 6Gb ram
static final int MIN_DISKSPACE = 20;
// MAX_ACTIVE_PROJECTS - project numbers have associated CSS defined in style.css
// Note: Projects can be confusing for users as far as which data belongs to what project - more is not better
public static final int MAX_ACTIVE_PROJECTS = 3;
// log purge limits
public static final int MAX_LOG_LINES = 2500;
public static final int MAX_LOG_CHARS = MAX_LOG_LINES * 100;
// base file paths
public static final String macRscriptPath = "/usr/local/bin/Rscript";
// class data
int logLines = 0;
public Locale locale;
private String txtLog = "";
private String pid = "";
private Process rsVerProc = null;
private Process rsGetInstallPackages = null;
private Process rsDownloadPackages = null;
private String rsVer = "";
public boolean rsPackages = false;
public boolean rsDownload = false;
public String rsDownloadCheck = "";
private String rscriptVer = "Rscript version: N/A\nWARNING: You must have Rscript installed and in your environment path.";
private TaskHandler taskHandler = null;
private final String appRunPath = System.getProperty("user.dir");
private final AnnotationFiles annotationFiles;
// annotation annotation files available in the server
private ArrayList<AnnotationFiles.AnnotationFileInfo> lstServer = new ArrayList<>();
// downloads versions of tappAS available in the server
private ArrayList<String> lstDownloads = new ArrayList<>();
// application objects - must pass 'this' App object if instantiating before App constructor done (value has not been saved yet)
// WARN: create application logger before creating any other AppObjects
public final Logger logger = new Logger(this, Paths.get(appRunPath, DataApp.APPLOG_NAME).toString(), Logger.Level.Debug);
public final Controls ctls = new Controls(this);
public final UserPrefs userPrefs = new UserPrefs(this);
public final Resources resources = new Resources(this);
public final Export export = new Export(this);
public final DataApp data;
public final Tabs tabs;
public final AppController ctlr;
// access functions
public Locale getLocale() { return locale; }
public TaskHandler getTaskHandler() { return taskHandler; }
public ExecutorService getExecutor() { return taskHandler.getExecutor(); }
static boolean noGOExpansionLimits = false;
public static boolean isNoGOExpansionLimits() { return noGOExpansionLimits; }
public App() {
// set locale to US/UK, if neither, otherwise can run into issues with number formats in R packages
// need to validate this with computer set to a foreign locale to make sure there are no issues
// will log message if changed later on at initialization
locale = Locale.getDefault();
if(!locale.equals(Locale.UK) && !locale.equals(Locale.US)) {
Locale.setDefault(Locale.US);
locale = Locale.getDefault();
}
// instantiate required app objects
tabs = new Tabs(this);
data = new DataApp(this);
ctlr = new AppController(this);
annotationFiles = new AnnotationFiles(this);
}
public void initialize(TabPane tabPaneMain, TabPane tabPaneBottom) {
// set debug flag if command line option set
boolean logdbg = false;
String[] args = Tappas.getArgs();
if(args != null) {
for(String arg : args) {
switch (arg) {
case "-a":
logdbg = true;
System.out.println("Log debug messages enabled.");
break;
case "-ngel":
// temporary for development
noGOExpansionLimits = true;
System.out.println("GO expansion limits disabled.");
break;
}
}
}
// set logger level and log initial messages
logger.setLevel(logdbg? Logger.Level.Debug : Logger.Level.Info);
logDebug("Initializing application...");
if(!locale.equals(Locale.UK) && !locale.equals(Locale.US))
logDebug("Changed application locale to US/UK.");
// setup application task handler
taskHandler = new TaskHandler(this);
taskHandler.initialize(Math.max(2, Runtime.getRuntime().availableProcessors()));
// check for minimum application resources
// will just warn user but will allow application to run
// NOTE: we should not try to solve issues on computers that do not meet the minimum requirements
String str = checkMinResources();
if(!str.isEmpty()) {
ctls.alertWarning("Application Minimum Requirements NOT Met", str);
logWarning(str.replaceAll("\n\n", "\n"));
}
//Check if there is a new version of tappAS uploaded in our website
getTappASVersionFiles();
if(checkNewTappASVersion()){
String msg = "There is a new version of tappAS on the website. Visit \"https://app.tappas.org/downloads\" to download it.";
ctls.alertWarning("New version of tappAS found.", msg);
}
// initialize the application UI
ctlr.initialize();
if(tabs.initialize(tabPaneMain, tabPaneBottom)) {
data.initialize();
Platform.runLater(() -> {
// get annotation files lists: local, already downloaded, and from server
runServerList();
// get process id in the background, not essential
runPIDVersion();
logDebug("Post-initialization setup...");
ctlr.postInitialize();
logDebug("Post-initialization setup completed.");
// check to see if we got the Rscript path
checkRScriptPath();
/*if(rsVerProc == null && rsVer.isEmpty())
{
// most mac laptop computers seem to install Rscript in macRscriptPath
// but not make it available in the Path for Java to find it
if(Utils.isMacOS() && Files.exists(Paths.get(macRscriptPath))) {
// should provide a way to clear it or change it via app menu selection
logInfo("Setting Rscript file path for Mac OS to " + macRscriptPath);
data.writeRscriptFilepath(macRscriptPath);
runRscriptVersion();
}
else {
Window wnd = Tappas.getWindow();
DlgRscriptFilepath dlg = new DlgRscriptFilepath(null, wnd);
HashMap<String, String> results = dlg.showAndWait(new HashMap<>());
if(results != null) {
String filepath = results.get(DlgRscriptFilepath.FILE_PARAM);
data.writeRscriptFilepath(filepath);
runRscriptVersion();
}
}
}*/
});
logDebug("Application initialization completed.");
}
}
public void checkRScriptPath(){
// check to see if we got the Rscript path
if(rsVerProc == null && rsVer.isEmpty())
{
// most mac laptop computers seem to install Rscript in macRscriptPath
// but not make it available in the Path for Java to find it
if(Utils.isMacOS() && Files.exists(Paths.get(macRscriptPath))) {
// should provide a way to clear it or change it via app menu selection
logInfo("Setting Rscript file path for Mac OS to " + macRscriptPath);
data.writeRscriptFilepath(macRscriptPath);
runRscriptVersion();
}
else {
Window wnd = Tappas.getWindow();
DlgRscriptFilepath dlg = new DlgRscriptFilepath(null, wnd);
HashMap<String, String> results = dlg.showAndWait(new HashMap<>());
if(results != null) {
String filepath = results.get(DlgRscriptFilepath.FILE_PARAM);
data.writeRscriptFilepath(filepath);
runRscriptVersion();
}
}
}
}
public boolean shutdown() {
boolean exit = true;
if(taskHandler != null && taskHandler.getTasksCount() > 0) {
String msg = "You have some application task(s) running\nIf you exit, they will not complete properly.\nDo you still want to exit the application?\n\n";
if(ctls.alertConfirmation("Application Data Analysis Tasks Running", msg, ButtonType.CANCEL)) {
//allowCancel = false;
taskHandler.exit();
}
else
exit = false;
}
return exit;
}
public String getAppInfo() {
String info = Tappas.APP_NAME + " version: " + Tappas.APP_STRVER + "\n";
info += "User: " + System.getProperty("user.name") + "\n";
info += "ProcessID: " + pid + "\n";
info += "JavaFX: ver " + System.getProperties().getProperty("javafx.runtime.version") + "\n";
info += "OS: " + System.getProperty("os.name") + " ver " + System.getProperty("os.version") + "\n";
info += "Architecture: " + System.getProperty("os.arch") + "\n";
info += "Available processors, cores, for JVM: " + Runtime.getRuntime().availableProcessors() + "\n";
info += "Available memory, for JVM: " + String.format("%.02f",(Runtime.getRuntime().maxMemory()/((double)(1024*1024*1024)))) + " GB" + "\n";
info += rscriptVer + "\n";
return info;
}
//Create the last version of tappAS the user had to check if re-create goAncestors.obo file
//true for the same version and false if the usar run an older version of tappAS
public boolean checkAppLastVersion(){
return data.checkAppLastVersion();
}
public ArrayList<AnnotationFiles.AnnotationFileInfo> getAnnotationFilesList() {
return annotationFiles.getAnnotationFilesList(lstServer);
}
public boolean checkNewTappASVersion() {
boolean res = false;
if(lstDownloads.isEmpty())
return res;
else{
ArrayList<String> files = lstDownloads;
for(String file : files){
if(!file.startsWith("tappAS"))
continue;
String[] fields = file.split("\\.");
//tappAS . 0 . 99 . 01 . zip
int major = Integer.parseInt(fields[1]);
int minor = Integer.parseInt(fields[2]);
int rev = Integer.parseInt(fields[3]);
if(major > tappas.Tappas.APP_MAJOR_VER)
return true;
else if(major == tappas.Tappas.APP_MAJOR_VER){
if(minor > tappas.Tappas.APP_MINOR_VER)
return true;
else if(minor == tappas.Tappas.APP_MINOR_VER){
if(rev > tappas.Tappas.APP_STRREV)
return true;
}
}
}
}
return res;
}
//
// Project Functions
//
public int assignProjectNumber() {
int projectNum = 1;
boolean[] active = new boolean[MAX_ACTIVE_PROJECTS];
for(int i = 0; i < MAX_ACTIVE_PROJECTS; i++)
active[i] = false;
ArrayList<TabBase> lstTabBases = tabs.getActiveProjectsTabBase();
if(lstTabBases.size() < MAX_ACTIVE_PROJECTS) {
for(TabBase tb : lstTabBases) {
int num = tb.project.getProjectNumber();
if(num >= 1 && num <= MAX_ACTIVE_PROJECTS)
active[num-1] = true;
}
for(int num = 1; num <= MAX_ACTIVE_PROJECTS; num++) {
if(!active[num-1]) {
projectNum = num;
break;
}
}
}
return projectNum;
}
public ArrayList<Project.ProjectDef> getProjectsList() {
ArrayList<Project.ProjectDef> lst = new ArrayList<>();
File pfolder = new File(data.getAppProjectsFolder());
FilenameFilter filter = (File dir, String name) -> name.startsWith(DataProject.getProjectNamePrefix()) && name.endsWith(DataProject.getProjectNameExt());
File[] files = pfolder.listFiles(filter);
if(files != null) {
for (File file : files) {
HashMap<String, String> hm = new HashMap<>();
DataProject.loadProjectDef(hm, Paths.get(file.getAbsolutePath()).toString());
if(!hm.isEmpty()) {
// add to list if data format can be handled by this code
Project.ProjectDef pd = new Project.ProjectDef(hm);
if(DlgOpenProject.Params.isValidData(pd.dataVersion))
lst.add(pd);
}
}
}
Collections.sort(lst);
return lst;
}
public ArrayList<String> getProjectIdsList() {
ArrayList<String> ids = new ArrayList<>();
ArrayList<Project.ProjectDef> lst = getProjectsList();
lst.forEach((def) -> {
ids.add(def.id);
});
return ids;
}
public Project.ProjectDef getProjectDef(String id) {
Project.ProjectDef def = null;
HashMap<String, String> hm = new HashMap<>();
DataProject.loadProjectDef(hm, data.getProjectFolder(id));
if(!hm.isEmpty()){
def = new Project.ProjectDef(hm);
}
return def;
}
public Project getProject(Project.ProjectDef def) {
Project project = null;
ArrayList<TabBase> lstTB = tabs.getActiveProjectsTabBase();
for(TabBase tb : lstTB) {
if(tb.project != null) {
if(tb.project.getProjectId().equals(def.id)) {
project = tb.project;
break;
}
}
}
return project;
}
public boolean isProjectNameInUse(String name, String id) {
boolean inuse = false;
ArrayList<Project.ProjectDef> lst = getProjectsList();
for(Project.ProjectDef def : lst) {
if(!id.equals(def.id)) {
if(name.toLowerCase().equals(def.name.toLowerCase())) {
inuse = true;
break;
}
}
}
return inuse;
}
//
// Log Functions
//
public void setShowDebugMsg(boolean showdbg) { logger.setLevel(showdbg? Logger.Level.Debug : Logger.Level.Info); }
public boolean isShowDebugMsg() { return (logger.getLevel() == Logger.Level.Debug); }
public void logInfo(String msg) {
logger.logMsg(Logger.Level.Info, msg);
}
public void logDebug(String msg) {
logger.logMsg(Logger.Level.Debug, msg);
}
public void logWarning(String msg) {
logger.logMsg(Logger.Level.Warning, msg);
ctlr.showSeeAppLog(true);
}
public void logError(String msg) {
logger.logMsg(Logger.Level.Error, msg);
ctlr.showSeeAppLog(true);
}
public void logClear() {
logger.logClear();
ctlr.showSeeAppLog(false);
}
//
// Internal application use only - called from Tabs
//
public void clearLogDisplay() {
txtLog = "";
logLines = 0;
if(tabs != null)
tabs.clearLogDisplay();
}
public void updateLogDisplay(String msg) {
txtLog += msg;
// limit how much text in log display
int nchars = msg.length();
if(nchars > MAX_LOG_CHARS) {
if(tabs != null)
tabs.clearLogDisplay();
msg = txtLog.substring((int)(MAX_LOG_CHARS * 0.25));
int pos = msg.indexOf("\n");
if(pos != -1)
msg = msg.substring(pos+1);
txtLog = msg;
}
if(tabs != null)
tabs.updateLogDisplay(msg);
}
public String getAppLogContents() {
return txtLog;
}
//
// Custom Log File, e.g. data analysis log
// TODO: should pass the level or use a logger directly
//
public String getLogFromFile(String filepath, int maxLines) {
return Logger.getLogFromFile(filepath, maxLines);
}
public String getLogMsgLine(String msg, boolean first) {
return logger.getLogMsgLine(msg, first);
}
public void logMsgToFile(String msg, String filepath) {
Logger.logMsgToFile(msg, filepath);
}
//
// Internal functions
//
// Download tappAS Versions names
private void getTappASVersionFiles(){
// downloads
logDebug("Downloads Thread running");
/* seems to be working properly -- must change to new file names */
// get server annotation files
lstDownloads = annotationFiles.getServerDownloadsFilesList(DataApp.refDownloadsUrl);
if(lstDownloads.isEmpty())
logWarning("Unable to get server downloads files list.\nWARNING: The application will not be able to check if there are a new version of tappAS available.");
logDebug("ServerList thread exiting.");
}
// check for minimum application requirements - return proper message if requirements not met
private String checkMinResources() {
String msg = "";
int cpus = Runtime.getRuntime().availableProcessors();
logInfo("Available CPUs for JVM: " + cpus);
if(cpus < MIN_CPUS)
msg += (msg.isEmpty()? " " : "\n ") + "Min CPUs: " + MIN_CPUS + ", available: " + cpus;
if(!data.getAppDataFolder().isEmpty()) {
File f = new File(data.getAppDataFolder());
long fs = f.getFreeSpace() / (1024 * 1024 * 1024);
if(fs < MIN_DISKSPACE)
msg += (msg.isEmpty()? " " : "\n ") + "Min disk space: " + MIN_DISKSPACE + " GB, available: " + fs + " GB";
}
// max memory is determine by -Xmx or the JVM seems to determine the value based on a percentage of the available memory
// for example: with 32GB available, it returned 6GB, with 8GB it returned 1.78GB (how much memory is free probably impacts the value)
// Users can customize by passing values in the command line: java -Xmx4gb [-Xms4gb] -jar tappas.jar
double mem = Runtime.getRuntime().maxMemory()/((double)(1024*1024*1024));
logInfo("Available memory for JVM: " + String.format("%.02f", mem) + " GB");
if(mem < MIN_MEMORY)
msg += (msg.isEmpty()? " " : "\n ") + "Min memory for JVM: " + MIN_MEMORY + " GB, available: " + String.format("%.02f", mem) + " GB";
if(!msg.isEmpty()) {
msg = "Your computer does not meet the minimum application requirements:\n\n" + msg;
msg += "\n\nThe application may run but you could experience significant delays and/or errors.";
}
if(mem<0.5){
msg += "\n\nYou should run tappAS from console to get a better performance with following arguments:\n\n"
+ "java -jar -XmxsM tappas.jar \n";
}
return msg;
}
//
// Get Rscript Version Thread
//
public void runRscriptVersion() {
// run Rscript to get version
try {
data.loadRscriptPath();
rsVerProc = Runtime.getRuntime().exec(data.getRscriptFilepath() + " --version");
Thread thread = new RscriptThread();
thread.start();
} catch(Exception e) {
logWarning("Unable to get Rscript version: " + e.getMessage() + "\n WARNING: You must have Rscript installed and in your environment path.");
}
}
public void runGetInstalledPackages(String filepath) {
// run Rscript to get version
try {
data.loadRscriptPath();
rsGetInstallPackages = Runtime.getRuntime().exec(data.getRscriptFilepath() + " " + filepath);
Thread thread = new RscriptPackages();
// thread.start();
thread.run();
} catch(Exception e) {
logWarning("Unable to get R packages: " + e.getMessage());
}
}
public boolean runDownloadPackages(String filepath) {
// run Rscript to get version
boolean res = false;
try {
data.loadRscriptPath();
rsDownloadPackages = Runtime.getRuntime().exec(data.getRscriptFilepath() + " " + filepath);
RscriptDownloadPackages down = new RscriptDownloadPackages();
res = down.run();
// thread.start();
// thread.run();
} catch(Exception e) {
logWarning("Unable to get R packages: " + e.getMessage());
}
return res;
}
public boolean runDownloadPackagesThread(String filepath) {
// run Rscript to get version
boolean res = false;
try {
data.loadRscriptPath();
rsDownloadPackages = Runtime.getRuntime().exec(data.getRscriptFilepath() + " " + filepath);
Thread thread = new RscriptDownloadPackagesThread();
thread.run();
// thread.start();
// thread.run();
} catch(Exception e) {
logWarning("Unable to get R packages: " + e.getMessage());
}
return res;
}
private class RscriptPackages extends Thread {
@Override
public void run(){
logDebug("Rscript checking packages...");
try {
String rsver = "";
String line;
// note: the version output is sent to the error stream
BufferedReader input = new BufferedReader(new InputStreamReader(rsGetInstallPackages.getErrorStream()));
while ((line = input.readLine()) != null)
rsver = line;
try { input.close(); } catch(Exception e) { }
rsGetInstallPackages.waitFor();
int ev = rsGetInstallPackages.exitValue();
if(ev == 0 && !rsver.isEmpty()) {
String[] fields = rsver.split("\n");
if(fields.length == 1 && fields[0].equals("TRUE")) {
rsPackages = true;
}
}
} catch(Exception e) {
logError("Unable to get Rscript version: " + e.getMessage() + "\nWARNING: You must have Rscript installed and in your environment path.");
}
logDebug("Rscript check packages thread exiting.");
rsGetInstallPackages = null;
}
}
private class RscriptDownloadPackagesThread extends Thread {
@Override
public void run(){
logDebug("Rscript checking packages...");
try {
String rsver = "";
String line;
// note: the version output is sent to the error stream
BufferedReader input = new BufferedReader(new InputStreamReader(rsDownloadPackages.getErrorStream()));
while ((line = input.readLine()) != null){
if(line.contains("Error in ")){
rsDownload = false;
break;
}
rsver = line;
}
try { input.close(); } catch(Exception e) { }
rsDownloadPackages.waitFor();
int ev = rsDownloadPackages.exitValue();
if(ev == 0 && !rsver.isEmpty()) {
String[] fields = rsver.split("\n");
if(fields.length == 1 && fields[0].equals("TRUE")) {
rsDownload = true;
}
}
} catch(Exception e) {
rsDownloadCheck = "error";
logError("Unable to download R Packages: " + e.getMessage() + "\nWARNING: You must have Rscript installed and in your environment path.");
}
logDebug("Rscript download packages thread exiting.");
rsDownloadPackages = null;
rsDownloadCheck = "complete";
}
}
private class RscriptDownloadPackages {
public void RscriptDownloadPackages(){}
public boolean run(){
logDebug("Rscript checking packages...");
try {
String rsver = "";
String line;
// note: the version output is sent to the error stream
BufferedReader input = new BufferedReader(new InputStreamReader(rsDownloadPackages.getErrorStream()));
while ((line = input.readLine()) != null){
if(line.contains("Error:") || line.contains("Error in")){
rsDownload = false;
break;
}
rsver = line;
}
try { input.close(); } catch(Exception e) { }
rsDownloadPackages.waitFor();
int ev = rsDownloadPackages.exitValue();
if(ev == 0 && !rsver.isEmpty()) {
String[] fields = rsver.split("\n");
if(fields.length == 1 && fields[0].equals("TRUE")) {
rsDownload = true;
}
}
} catch(Exception e) {
rsDownloadCheck = "error";
logError("Unable to download R Packages: " + e.getMessage() + "\nWARNING: You must have Rscript installed and in your environment path.");
}
logDebug("Rscript download packages thread exiting.");
rsDownloadPackages = null;
rsDownloadCheck = "complete";
return rsDownload;
}
}
private class RscriptThread extends Thread {
@Override
public void run(){
logDebug("Rscript Thread running");
try {
String rsver = "";
String line;
// note: the version output is sent to the error stream
BufferedReader input = new BufferedReader(new InputStreamReader(rsVerProc.getErrorStream()));
while ((line = input.readLine()) != null)
rsver = line;
try { input.close(); } catch(Exception e) { }
rsVerProc.waitFor();
int ev = rsVerProc.exitValue();
if(ev == 0 && !rsver.isEmpty()) {
String[] fields = rsver.split("\n");
if(fields.length == 1) {
rsVer = rsver;
rscriptVer = rsver;
}
}
} catch(Exception e) {
logError("Unable to get Rscript version: " + e.getMessage() + "\nWARNING: You must have Rscript installed and in your environment path.");
}
logDebug("Rscript version thread exiting.");
rsVerProc = null;
}
}
//
// Get Application PID Thread
//
private void runPIDVersion() {
// run script to get version if not Windows
try {
if(System.getProperty("os.name").toLowerCase().startsWith("windows")) {
pid = "N/A";
}
else {
Thread thread = new PIDThread();
thread.start();
}
} catch(Exception e) {
logWarning("Unable to get application's PID.");
}
}
private class PIDThread extends Thread {
@Override
public void run(){
logDebug("PID thread running...");
Path runScriptPath = null;
try {
String line;
String outstr = "";
// note: the version output is sent to the error stream
runScriptPath = data.getTmpScriptFileFromResource("getPID.sh");
Process p = Runtime.getRuntime().exec(runScriptPath.toString());
if(p != null) {
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null)
outstr += line + "\n";
try { input.close(); } catch(Exception e) { }
p.waitFor();
int ev = p.exitValue();
if(ev == 0 && !outstr.isEmpty()) {
String[] fields = outstr.split("\n");
if(fields.length == 2) {
String[] subFields = fields[0].replaceAll("\\s+", " ").split(" ");
int idx = 0;
int idxPID = -1;
int idxPPID = -1;
for(String value : subFields) {
switch (value) {
case "PID":
idxPID = idx;
break;
case "PPID":
idxPPID = idx;
break;
}
idx++;
}
if(idxPID != -1 && idxPPID != -1) {
subFields = fields[1].replaceAll("\\s+", " ").split(" ");
logDebug("PID: " + subFields[idxPID] + ", PPID: " + subFields[idxPPID] + "\n");
pid = subFields[idxPPID];
}
}
}
}
else
logWarning("Unable to create process to get application's PID");
} catch(Exception e) {
logWarning("Unable to get aplication's PID: " + e.getMessage());
}
Utils.removeFile(runScriptPath);
logDebug("PID thread exiting.");
}
}
//
// Get List of Server Annotation Files Thread
//
public void runServerList() {
// run Rscript to get version
try {
Thread thread = new ServerListThread();
thread.start();
} catch(Exception e) {
logWarning("Unable to get server annotation files list: " + e.getMessage() + "\n WARNING: The application will not be able to download annotation files.");
}
}
private class ServerListThread extends Thread {
@Override
public void run(){
logDebug("ServerList Thread running");
/* seems to be working properly -- must change to new file names */
// get server annotation files
lstServer = annotationFiles.getServerFilesList(DataApp.refDataUrl);
if(lstServer.isEmpty())
logWarning("Unable to get server annotation files list.\nWARNING: The application will not be able to download annotation files.");
ArrayList<AnnotationFiles.AnnotationFileInfo> lst = annotationFiles.getAnnotationFilesList(lstServer);
for(AnnotationFiles.AnnotationFileInfo afi : lst)
System.out.println(afi.toString() + ", local: " + afi.local);
logDebug("ServerList thread exiting.");
}
}
//
// Data Classes
//
public static class AppResource {
String resName, fileName;
AppResource(String resName, String fileName) {
this.resName = resName;
this.fileName = fileName;
}
}
}