001/* 002 * Copyright 2010-2019 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.main; 020 021import java.awt.EventQueue; 022import java.beans.PropertyVetoException; 023import java.io.File; 024import java.nio.channels.FileLock; 025import java.util.ArrayList; 026import java.util.List; 027 028import javax.swing.JDesktopPane; 029import javax.swing.JFrame; 030import javax.swing.JInternalFrame; 031import javax.swing.JOptionPane; 032import javax.swing.WindowConstants; 033 034import icy.action.ActionManager; 035import icy.common.Version; 036import icy.file.FileUtil; 037import icy.file.Loader; 038import icy.gui.dialog.ConfirmDialog; 039import icy.gui.dialog.IdConfirmDialog; 040import icy.gui.dialog.IdConfirmDialog.Confirmer; 041import icy.gui.frame.ExitFrame; 042import icy.gui.frame.IcyExternalFrame; 043import icy.gui.frame.SplashScreenFrame; 044import icy.gui.frame.progress.AnnounceFrame; 045import icy.gui.frame.progress.ToolTipFrame; 046import icy.gui.inspector.InspectorPanel; 047import icy.gui.main.MainFrame; 048import icy.gui.main.MainInterface; 049import icy.gui.main.MainInterfaceBatch; 050import icy.gui.main.MainInterfaceGui; 051import icy.gui.system.NewVersionFrame; 052import icy.gui.util.LookAndFeelUtil; 053import icy.image.cache.ImageCache; 054import icy.imagej.ImageJPatcher; 055import icy.math.UnitUtil; 056import icy.network.NetworkUtil; 057import icy.plugin.PluginDescriptor; 058import icy.plugin.PluginInstaller; 059import icy.plugin.PluginLauncher; 060import icy.plugin.PluginLoader; 061import icy.plugin.PluginUpdater; 062import icy.plugin.abstract_.Plugin; 063import icy.preferences.ApplicationPreferences; 064import icy.preferences.GeneralPreferences; 065import icy.preferences.IcyPreferences; 066import icy.preferences.PluginPreferences; 067import icy.sequence.Sequence; 068import icy.system.AppleUtil; 069import icy.system.IcyExceptionHandler; 070import icy.system.IcySecurityManager; 071import icy.system.SingleInstanceCheck; 072import icy.system.SystemUtil; 073import icy.system.audit.Audit; 074import icy.system.thread.ThreadUtil; 075import icy.update.IcyUpdater; 076import icy.util.StringUtil; 077import icy.workspace.WorkspaceInstaller; 078import icy.workspace.WorkspaceLoader; 079import ij.ImageJ; 080import vtk.vtkNativeLibrary; 081import vtk.vtkVersion; 082 083/** 084 * <h3>Icy - copyright 2019 Institut Pasteur</h3> An open community platform for bio image analysis<br> 085 * <i>http://icy.bioimageanalysis.org</i><br> 086 * <br> 087 * Icy has been created by the Bio Image Analysis team at Institut Pasteur<br> 088 * <i>https://research.pasteur.fr/fr/team/bioimage-analysis</i><br> 089 * <br> 090 * Icy is free and open source, it has been funded both by Institut Pasteur and the FBI consortium<br> 091 * <i>https://france-bioimaging.org</i><br> 092 * <br> 093 * Source code is always provided in the main application package (in the icy.jar archive file) but can be also browsed 094 * from the GitHub repository<br> 095 * <i>https://github.com/Icy-imaging/Icy-Kernel</i><br> 096 * <br> 097 * 098 * @author Stephane Dallongeville 099 * @author Fabrice de Chaumont 100 */ 101public class Icy 102{ 103 public static final String LIB_PATH = "lib"; 104 public static final int EXIT_FORCE_DELAY = 3000; 105 106 /** 107 * Icy Version 108 */ 109 public static Version version = new Version("2.0.1.0"); 110 111 /** 112 * Main interface 113 */ 114 private static MainInterface mainInterface = null; 115 116 /** 117 * Unique instance checker 118 */ 119 static FileLock lock = null; 120 121 /** 122 * private splash for initial loading 123 */ 124 static SplashScreenFrame splashScreen = null; 125 126 /** 127 * VTK library loaded flag 128 */ 129 static boolean vtkLibraryLoaded = false; 130 131 /** 132 * ITK library loaded flag 133 */ 134 static boolean itkLibraryLoaded = false; 135 136 /** 137 * No splash screen flag (default = false) 138 */ 139 static boolean noSplash = false; 140 /** 141 * Exiting flag 142 */ 143 static boolean exiting = false; 144 145 /** 146 * Startup parameters 147 */ 148 static String[] args; 149 static String[] pluginArgs; 150 static String startupPluginName; 151 static Plugin startupPlugin; 152 static String startupImage; 153 154 /** 155 * internals 156 */ 157 static ExitFrame exitFrame = null; 158 static Thread terminer = null; 159 160 /** 161 * @param args 162 * Received from the command line. 163 */ 164 public static void main(String[] args) 165 { 166 boolean headless = false; 167 168 try 169 { 170 System.out.println("Initializing..."); 171 System.out.println(); 172 173 // handle arguments (must be the first thing to do) 174 headless = handleAppArgs(args); 175 176 // force headless if we have a headless system 177 if (!headless && SystemUtil.isHeadLess()) 178 headless = true; 179 180 // initialize preferences 181 IcyPreferences.init(); 182 183 // check if Icy is already running 184 lock = SingleInstanceCheck.lock("icy"); 185 if (lock == null) 186 { 187 // we always accept multi instance in headless mode 188 if (!headless) 189 { 190 // we need to use our custom ConfirmDialog as 191 // Icy.getMainInterface().isHeadless() will return false here 192 final Confirmer confirmer = new Confirmer("Confirmation", 193 "Icy is already running on this computer. Start anyway ?", JOptionPane.YES_NO_OPTION, 194 ApplicationPreferences.ID_SINGLE_INSTANCE); 195 196 ThreadUtil.invokeNow(confirmer); 197 198 if (!confirmer.getResult()) 199 { 200 System.out.println("Exiting..."); 201 // save preferences 202 IcyPreferences.save(); 203 // and quit 204 System.exit(0); 205 return; 206 } 207 } 208 } 209 210 // fix possible IllegalArgumentException on Swing sorting 211 System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); 212 213 if (!headless && !noSplash) 214 { 215 // prepare splashScreen (ok to create it here as we are not yet in substance laf) 216 splashScreen = new SplashScreenFrame(); 217 218 // It's important to initialize AWT now (with InvokeNow(...) for instance) to avoid 219 // the JVM deadlock bug (id: 5104239). It happen when the AWT thread is initialized 220 // while others threads load some new library with ClassLoader.loadLibrary 221 222 // display splash NOW (don't use ThreadUtil as headless is still false here) 223 EventQueue.invokeAndWait(new Runnable() 224 { 225 @Override 226 public void run() 227 { 228 // display splash screen 229 splashScreen.setVisible(true); 230 } 231 }); 232 } 233 234 // set LOCI debug level (do it immediately as it can quickly show some log messages) 235 loci.common.DebugTools.enableLogging("ERROR"); 236 237 // fast start 238 new Thread(new Runnable() 239 { 240 @Override 241 public void run() 242 { 243 // force image cache initialization so GUI won't wait after it (need preferences init) 244 ImageCache.isEnabled(); 245 } 246 }, "Initializer 1").start(); 247 new Thread(new Runnable() 248 { 249 @Override 250 public void run() 251 { 252 // initialize network (need preferences init) 253 NetworkUtil.init(); 254 } 255 }, "Initializer 2").start(); 256 new Thread(new Runnable() 257 { 258 @Override 259 public void run() 260 { 261 // load plugins classes (need preferences init) 262 PluginLoader.reloadAsynch(); 263 WorkspaceLoader.reloadAsynch(); 264 } 265 }, "Initializer 3").start(); 266 267 try 268 { 269 // patches ImageJ classes (need to be done before instancing ImageJ) 270 ImageJPatcher.applyPatches(); 271 } 272 catch (Throwable t) 273 { 274 System.err.println("Error while patching ImageJ classes:"); 275 IcyExceptionHandler.showErrorMessage(t, false); 276 } 277 278 // build main interface 279 if (headless) 280 mainInterface = new MainInterfaceBatch(); 281 else 282 mainInterface = new MainInterfaceGui(); 283 } 284 catch (Throwable t) 285 { 286 // any error at this point is fatal 287 fatalError(t, headless); 288 } 289 290 if (!headless) 291 { 292 // do it on AWT thread NOW as this is what we want first 293 ThreadUtil.invokeNow(new Runnable() 294 { 295 @Override 296 public void run() 297 { 298 try 299 { 300 // init Look And Feel (need mainInterface instance) 301 LookAndFeelUtil.init(); 302 // init need "mainInterface" variable to be initialized 303 getMainInterface().init(); 304 } 305 catch (Throwable t) 306 { 307 // any error here is fatal 308 fatalError(t, false); 309 } 310 } 311 }); 312 } 313 else 314 { 315 // simple main interface init 316 getMainInterface().init(); 317 } 318 319 // splash screen initialized --> hide it 320 if (splashScreen != null) 321 { 322 // then do less important stuff later 323 ThreadUtil.invokeLater(new Runnable() 324 { 325 @Override 326 public void run() 327 { 328 // we can now hide splash as we have interface 329 splashScreen.dispose(); 330 splashScreen = null; 331 } 332 }); 333 } 334 335 // show general informations 336 System.out.println(SystemUtil.getJavaName() + " " + SystemUtil.getJavaVersion() + " (" 337 + SystemUtil.getJavaArchDataModel() + " bit)"); 338 System.out.println("Running on " + SystemUtil.getOSName() + " " + SystemUtil.getOSVersion() + " (" 339 + SystemUtil.getOSArch() + ")"); 340 System.out.println("Number of processors : " + SystemUtil.getNumberOfCPUs()); 341 System.out.println("System total memory : " + UnitUtil.getBytesString(SystemUtil.getTotalMemory())); 342 System.out.println("System available memory : " + UnitUtil.getBytesString(SystemUtil.getFreeMemory())); 343 System.out.println("Max java memory : " + UnitUtil.getBytesString(SystemUtil.getJavaMaxMemory())); 344 // image cache 345 if (ImageCache.isEnabled()) 346 { 347 System.out.println("Image cache initialized (reserved memory = " + ApplicationPreferences.getCacheMemoryMB() 348 + " MB, disk cache location = " + ApplicationPreferences.getCachePath() + ")"); 349 } 350 else 351 { 352 System.err.println("Couldn't initialize image cache (cache is disabled)"); 353 // disable virtual mode button from inspector 354 final InspectorPanel inspector = getMainInterface().getInspector(); 355 if (inspector != null) 356 inspector.imageCacheDisabled(); 357 } 358 if (headless) 359 System.out.println("Headless mode."); 360 System.out.println(); 361 362 // initialize OSX specific GUI stuff 363 if (!headless && SystemUtil.isMac()) 364 AppleUtil.init(); 365 // initialize security 366 IcySecurityManager.init(); 367 // initialize exception handler 368 IcyExceptionHandler.init(); 369 // initialize action manager 370 ActionManager.init(); 371 // prepare native library files (need preferences init) 372 nativeLibrariesInit(); 373 374 // changed version ? 375 if (!ApplicationPreferences.getVersion().equals(Icy.version)) 376 { 377 // not headless ? 378 if (!headless) 379 { 380 // display the new version information 381 final String changeLog = Icy.getChangeLog(); 382 383 // show the new version frame 384 if (!StringUtil.isEmpty(changeLog)) 385 { 386 ThreadUtil.invokeNow(new Runnable() 387 { 388 @Override 389 public void run() 390 { 391 new NewVersionFrame(Icy.getChangeLog()); 392 } 393 }); 394 } 395 } 396 397 // force check update for the new version 398 GeneralPreferences.setLastUpdateCheckTime(0); 399 } 400 401 // HTTPS not supported ? 402 if (!NetworkUtil.isHTTPSSupported()) 403 { 404 // final String text1 = "Your version of java does not support HTTPS connection required by the future new web site."; 405 // final String text2 = "You need to upgrade java to 7u111 (Java 7) or 8u101 (Java 8) at least to be able to use online features in future."; 406 final String text1 = "Your version of java does not support HTTPS protocol which will be used soon by the new web site."; 407 final String text2 = "You need to upgrade your version of java to 7u111 (Java 7) or 8u101 (Java 8) at least to use online features (as search or plugin update) in future."; 408 // final String text2 = "You won't be able to use online features (as search or plugin update) in future until you update your version of java (Java 409 // 7u111 or Java 410 // 8u101 minimum)."; 411 412 System.err.println("Warning: " + text1); 413 System.err.println(text2); 414 415 // TODO: change message when new web site is here 416 if (!Icy.getMainInterface().isHeadLess()) 417 new ToolTipFrame("<html><b>WARNING:</b> " + text1 + "<br>" + text2 + "</html>", 0, 418 "httpsNotSupportedWarning"); 419 // new ToolTipFrame("<html><b>" + text1 + "<br>" + text2 + "</b></html>", 0, "httpsNotSupported"); 420 } 421 422 final long currentTime = System.currentTimeMillis(); 423 final long halfDayInterval = 1000 * 60 * 60 * 12; 424 425 // check only once per 12 hours slice 426 if (currentTime > (GeneralPreferences.getLastUpdateCheckTime() + halfDayInterval)) 427 { 428 // check for core update 429 if (GeneralPreferences.getAutomaticUpdate()) 430 IcyUpdater.checkUpdate(true); 431 // check for plugin update 432 if (PluginPreferences.getAutomaticUpdate()) 433 PluginUpdater.checkUpdate(true); 434 435 // update last update check time 436 GeneralPreferences.setLastUpdateCheckTime(currentTime); 437 } 438 439 // update version info 440 ApplicationPreferences.setVersion(Icy.version); 441 // set LOCI debug level 442 // loci.common.DebugTools.enableLogging("ERROR"); 443 // set OGL debug level 444 // SystemUtil.setProperty("jogl.verbose", "TRUE"); 445 // SystemUtil.setProperty("jogl.debug", "TRUE"); 446 447 System.out.println(); 448 System.out.println("Icy Version " + version + " started !"); 449 System.out.println(); 450 451 checkParameters(); 452 453 // handle startup arguments 454 if (startupImage != null) 455 Icy.getMainInterface().addSequence(Loader.loadSequence(FileUtil.getGenericPath(startupImage), 0, false)); 456 457 // wait while updates are occurring before starting command line plugin... 458 while (PluginUpdater.isCheckingForUpdate() || PluginInstaller.isProcessing() 459 || WorkspaceInstaller.isProcessing()) 460 ThreadUtil.sleep(1); 461 462 if (startupPluginName != null) 463 { 464 PluginLoader.waitWhileLoading(); 465 466 final PluginDescriptor plugin = PluginLoader.getPlugin(startupPluginName); 467 468 if (plugin == null) 469 { 470 System.err.println("Could not launch plugin '" + startupPluginName + "': the plugin was not found."); 471 System.err.println("Be sure you correctly wrote the complete class name and respected the case."); 472 System.err.println("Ex: plugins.mydevid.analysis.MyPluginClass"); 473 } 474 else 475 startupPlugin = PluginLauncher.start(plugin); 476 } 477 478 // headless mode ? we can exit now... 479 if (headless) 480 exit(false); 481 } 482 483 private static boolean handleAppArgs(String[] args) 484 { 485 final List<String> pluginArgsList = new ArrayList<String>(); 486 487 startupImage = null; 488 startupPluginName = null; 489 startupPlugin = null; 490 boolean execute = false; 491 boolean headless = false; 492 493 // save the base arguments 494 Icy.args = args; 495 496 for (String arg : args) 497 { 498 // store plugin arguments 499 if (startupPluginName != null) 500 pluginArgsList.add(arg); 501 else if (execute) 502 startupPluginName = arg; 503 // special flag to disabled JCL (needed for development) 504 else if (arg.equalsIgnoreCase("--disableJCL") || arg.equalsIgnoreCase("-dJCL")) 505 PluginLoader.setJCLDisabled(true); 506 // headless mode 507 else if (arg.equalsIgnoreCase("--headless") || arg.equalsIgnoreCase("-hl")) 508 headless = true; 509 // disable splash-screen 510 else if (arg.equalsIgnoreCase("--nosplash") || arg.equalsIgnoreCase("-ns")) 511 noSplash = true; 512 // execute plugin 513 else if (arg.equalsIgnoreCase("--execute") || arg.equalsIgnoreCase("-x")) 514 execute = true; 515 // assume image name ? 516 else 517 startupImage = arg; 518 } 519 520 // save the plugin arguments 521 Icy.pluginArgs = pluginArgsList.toArray(new String[pluginArgsList.size()]); 522 523 return headless; 524 } 525 526 static void checkParameters() 527 { 528 // we are using a 32 bits JVM with a 64 bits OS --> warn the user 529 if (SystemUtil.isWindows64() && SystemUtil.is32bits()) 530 { 531 final String text = "You're using a 32 bits Java with a 64 bits OS, try to upgrade to 64 bits java for better performance !"; 532 533 System.out.println("Warning: " + text); 534 535 if (!Icy.getMainInterface().isHeadLess()) 536 new ToolTipFrame("<html>" + text + "</html>", 15, "badJavaArchTip"); 537 } 538 539 // we are using java 6 on OSX --> warn the user 540 final double javaVersion = SystemUtil.getJavaVersionAsNumber(); 541 542 if ((javaVersion > 0) && (javaVersion < 7d) && SystemUtil.isMac()) 543 { 544 final String text = "It looks like you're using a old version of Java (1.6)<br>" 545 + "It's recommended to use last JDK 8 for OSX for a better user experience.<br>See the <a href=\"http://icy.bioimageanalysis.org/faq#35\">FAQ</a> to get information about how to update java."; 546 547 System.out.println("Warning: " + text); 548 549 if (!Icy.getMainInterface().isHeadLess()) 550 new ToolTipFrame("<html>" + text + "</html>", 15, "outdatedJavaOSX"); 551 } 552 553 // detect bad memory setting 554 if ((ApplicationPreferences.getMaxMemoryMB() <= 128) && (ApplicationPreferences.getMaxMemoryMBLimit() > 256)) 555 { 556 final String text = "Your maximum memory setting is low, you should increase it in Preferences."; 557 558 System.out.println("Warning: " + text); 559 560 if (!Icy.getMainInterface().isHeadLess()) 561 new ToolTipFrame("<html>" + text + "</html>", 15, "lowMemoryTip"); 562 } 563 else if (ApplicationPreferences.getMaxMemoryMB() < (ApplicationPreferences.getDefaultMemoryMB() / 2)) 564 { 565 if (!Icy.getMainInterface().isHeadLess()) 566 { 567 new ToolTipFrame( 568 "<html><b>Tip:</b> you can increase your maximum memory in preferences setting.</html>", 15, 569 "maxMemoryTip"); 570 } 571 } 572 573 if (!Icy.getMainInterface().isHeadLess()) 574 { 575 ToolTipFrame tooltip; 576 577 // welcome tip ! 578 tooltip = new ToolTipFrame( 579 "<html>Access the main menu by clicking on top left icon<br>" + "<img src=\"" 580 + Icy.class.getResource("/res/image/help/main_menu.png").toString() + "\" /></html>", 581 30, "mainMenuTip"); 582 tooltip.setSize(456, 240); 583 584 // new Image Cache ! 585 tooltip = new ToolTipFrame("<html>" + "<img src=\"" 586 + Icy.class.getResource("/res/image/help/virtual_mode.jpg").toString() + "\" /><br>" 587 + "This new button allow to enable/disable Icy <b>virtual mode</b>.<br><br>" 588 + "Virtual mode will force all new created images to be in <i>virtual mode</i> which mean their data can be stored on disk to spare memory.<br>" 589 + "Note that <i>virtual mode</i> is still experimental and <b>some plugins don't support it</b> (processed data can be lost) so use it carefully and only if you're running out of memory.<br>" 590 + "<i>You can change the image caching settings in Icy preferences</i></html>", 30, "virtualMode"); 591 tooltip.setSize(380, 240); 592 } 593 } 594 595 static void fatalError(Throwable t, boolean headless) 596 { 597 // hide splashScreen if needed 598 if ((splashScreen != null) && (splashScreen.isVisible())) 599 splashScreen.dispose(); 600 601 // show error in console 602 IcyExceptionHandler.showErrorMessage(t, true); 603 // and show error in dialog if not headless 604 if (!headless) 605 { 606 JOptionPane.showMessageDialog(null, IcyExceptionHandler.getErrorMessage(t, true), "Fatal error", 607 JOptionPane.ERROR_MESSAGE); 608 } 609 610 // exit with error code 1 611 System.exit(1); 612 } 613 614 /** 615 * Restart application with user confirmation 616 */ 617 public static void confirmRestart() 618 { 619 confirmRestart(null); 620 } 621 622 /** 623 * Restart application with user confirmation (custom message) 624 */ 625 public static void confirmRestart(String message) 626 { 627 final String mess; 628 629 if (StringUtil.isEmpty(message)) 630 mess = "Application need to be restarted so changes can take effect. Do it now ?"; 631 else 632 mess = message; 633 634 if (ConfirmDialog.confirm(mess)) 635 // restart application now 636 exit(true); 637 } 638 639 /** 640 * Show announcement to restart application 641 */ 642 public static void announceRestart() 643 { 644 announceRestart(null); 645 } 646 647 /** 648 * Show announcement to restart application (custom message) 649 */ 650 public static void announceRestart(String message) 651 { 652 final String mess; 653 654 if (StringUtil.isEmpty(message)) 655 mess = "Application need to be restarted so changes can take effet."; 656 else 657 mess = message; 658 659 if (Icy.getMainInterface().isHeadLess()) 660 { 661 // just display this message 662 System.out.println(mess); 663 } 664 else 665 { 666 new AnnounceFrame(mess, "Restart Now", new Runnable() 667 { 668 @Override 669 public void run() 670 { 671 // restart application now 672 exit(true); 673 } 674 }, 20); 675 } 676 } 677 678 /** 679 * Returns <code>true</code> if application can exit.<br> 680 * Shows a confirmation dialog if setting requires it or if it's unsafe to exit now. 681 */ 682 public static boolean canExit(boolean showConfirm) 683 { 684 // we first check if externals listeners allow existing 685 if (!getMainInterface().canExitExternal()) 686 return false; 687 688 // headless mode --> allow exit 689 if (Icy.getMainInterface().isHeadLess()) 690 return true; 691 692 // PluginInstaller or WorkspaceInstaller not running 693 final boolean safeExit = (!PluginInstaller.isProcessing()) && (!WorkspaceInstaller.isProcessing()); 694 695 // not safe, need confirmation 696 if (!safeExit) 697 { 698 if (!ConfirmDialog.confirm("Quit the application", 699 "Some processes are not yet completed, are you sure you want to quit ?", 700 ConfirmDialog.YES_NO_CANCEL_OPTION)) 701 return false; 702 703 return true; 704 } 705 else if (showConfirm && GeneralPreferences.getExitConfirm()) 706 { 707 // we need user confirmation 708 if (!IdConfirmDialog.confirm("Quit the application ?", GeneralPreferences.ID_CONFIRM_EXIT)) 709 return false; 710 711 return true; 712 } 713 714 return true; 715 } 716 717 /** 718 * Exit Icy, returns <code>true</code> if the operation should success.<br> 719 * Note that the method is asynchronous so you still have a bit of time to execute some stuff before the application 720 * actually exit. 721 */ 722 public static boolean exit(final boolean restart) 723 { 724 // check we can exit application 725 if (!canExit(!restart)) 726 return false; 727 728 // already existing 729 if (exiting && terminer.isAlive()) 730 { 731 // set focus on exit frame 732 if (exitFrame != null) 733 exitFrame.requestFocus(); 734 // return true; 735 return true; 736 } 737 738 // we don't want to be in EDT here and avoid BG runner 739 // as we test for BG runner completion 740 terminer = new Thread(new Runnable() 741 { 742 @Override 743 public void run() 744 { 745 // mark the application as exiting 746 exiting = true; 747 748 System.out.println("Exiting..."); 749 750 final ImageJ ij = Icy.getMainInterface().getImageJ(); 751 752 // clean ImageJ exit 753 if (ij != null) 754 ij.quit(); 755 756 // get main frame 757 final MainFrame mainFrame = Icy.getMainInterface().getMainFrame(); 758 759 // disconnect from chat (not needed but preferred) 760 // if (mainFrame != null) 761 // mainFrame.getChat().disconnect("Icy closed"); 762 763 // close all icyFrames (force wait completion) 764 ThreadUtil.invokeNow(new Runnable() 765 { 766 @Override 767 public void run() 768 { 769 // for (IcyFrame frame : IcyFrame.getAllFrames()) 770 // frame.close(); 771 // close all JInternalFrames 772 final JDesktopPane desktopPane = Icy.getMainInterface().getDesktopPane(); 773 774 if (desktopPane != null) 775 { 776 for (JInternalFrame frame : desktopPane.getAllFrames()) 777 { 778 // if (frame instanceof IcyInternalFrame) 779 // { 780 // final IcyInternalFrame iFrame = (IcyInternalFrame) frame; 781 // if (!iFrame.isClosed()) 782 // iFrame.close(true); 783 // if (iFrame.getDefaultCloseOperation() != 784 // WindowConstants.DISPOSE_ON_CLOSE) 785 // iFrame.dispose(); 786 // } 787 // else 788 // { 789 try 790 { 791 frame.setClosed(true); 792 } 793 catch (PropertyVetoException e) 794 { 795 // if (frame.getDefaultCloseOperation() != 796 // WindowConstants.DISPOSE_ON_CLOSE) 797 frame.dispose(); 798 } 799 // } 800 } 801 } 802 803 // then close all external frames except main frame 804 for (JFrame frame : Icy.getMainInterface().getExternalFrames()) 805 { 806 if (frame != mainFrame) 807 { 808 if (frame instanceof IcyExternalFrame) 809 { 810 final IcyExternalFrame iFrame = (IcyExternalFrame) frame; 811 iFrame.close(); 812 if (iFrame.getDefaultCloseOperation() != WindowConstants.DISPOSE_ON_CLOSE) 813 iFrame.dispose(); 814 } 815 else 816 frame.dispose(); 817 } 818 } 819 } 820 }); 821 822 // stop daemon plugin 823 PluginLoader.stopDaemons(); 824 // shutdown background processor after frame close 825 ThreadUtil.shutdown(); 826 827 // headless mode 828 if (Icy.getMainInterface().isHeadLess()) 829 { 830 // final long start = System.currentTimeMillis(); 831 // // wait 10s max for background processors completed theirs tasks 832 // while (!ThreadUtil.isShutdownAndTerminated() && ((System.currentTimeMillis() 833 // - start) < 10 * 1000)) 834 // ThreadUtil.sleep(1); 835 836 // wait that background processors completed theirs tasks 837 while (!ThreadUtil.isShutdownAndTerminated()) 838 ThreadUtil.sleep(1); 839 } 840 else 841 { 842 // need to create the exit frame in EDT 843 ThreadUtil.invokeNow(new Runnable() 844 { 845 @Override 846 public void run() 847 { 848 // create and display the exit frame 849 exitFrame = new ExitFrame(EXIT_FORCE_DELAY); 850 } 851 }); 852 853 // wait that background processors completed theirs tasks 854 while (!ThreadUtil.isShutdownAndTerminated() && !exitFrame.isForced()) 855 ThreadUtil.sleep(1); 856 857 // need to dispose the exit frame in EDT (else we can have deadlock) 858 ThreadUtil.invokeNow(new Runnable() 859 { 860 @Override 861 public void run() 862 { 863 // can close the exit frame now 864 exitFrame.dispose(); 865 } 866 }); 867 } 868 869 // need to dispose the main frame in EDT (else we can have deadlock) 870 ThreadUtil.invokeNow(new Runnable() 871 { 872 @Override 873 public void run() 874 { 875 // finally close the main frame 876 if (mainFrame != null) 877 mainFrame.dispose(); 878 } 879 }); 880 881 // save preferences 882 IcyPreferences.save(); 883 // save audit data 884 Audit.save(); 885 // cache cleanup 886 ImageCache.end(); 887 888 // clean up native library files 889 // unPrepareNativeLibraries(); 890 891 // release lock 892 if (lock != null) 893 SingleInstanceCheck.release(lock); 894 895 final boolean doUpdate = IcyUpdater.getWantUpdate(); 896 897 // launch updater if needed 898 if (doUpdate || restart) 899 IcyUpdater.launchUpdater(doUpdate, restart); 900 901 // good exit 902 System.exit(0); 903 } 904 }); 905 906 terminer.setName("Icy Shutdown"); 907 terminer.start(); 908 909 return true; 910 } 911 912 /** 913 * @param force 914 * @deprecated use <code>exit(boolean)</code> instead 915 */ 916 @Deprecated 917 public static boolean exit(final boolean restart, boolean force) 918 { 919 return exit(restart); 920 } 921 922 /** 923 * Return true is VTK library loaded. 924 */ 925 public static boolean isVtkLibraryLoaded() 926 { 927 return vtkLibraryLoaded; 928 } 929 930 /** 931 * Return true is VTK library loaded. 932 */ 933 public static boolean isItkLibraryLoaded() 934 { 935 return itkLibraryLoaded; 936 } 937 938 /** 939 * @deprecated Use {@link MainInterface#isHeadLess()} instead. 940 */ 941 @Deprecated 942 public static boolean isHeadLess() 943 { 944 return getMainInterface().isHeadLess(); 945 } 946 947 /** 948 * Return true is the application is currently exiting. 949 */ 950 public static boolean isExiting() 951 { 952 return exiting; 953 } 954 955 /** 956 * Return the main Icy interface. 957 */ 958 public static MainInterface getMainInterface() 959 { 960 // batch mode 961 if (mainInterface == null) 962 mainInterface = new MainInterfaceBatch(); 963 964 return mainInterface; 965 } 966 967 /** 968 * Returns the command line arguments 969 */ 970 public static String[] getCommandLineArgs() 971 { 972 return args; 973 } 974 975 /** 976 * Returns the plugin command line arguments 977 */ 978 public static String[] getCommandLinePluginArgs() 979 { 980 return pluginArgs; 981 } 982 983 /** 984 * Clear the plugin command line arguments.<br> 985 * This method should be called after the launching plugin actually 'consumed' the startup 986 * arguments. 987 */ 988 public static void clearCommandLinePluginArgs() 989 { 990 pluginArgs = new String[0]; 991 } 992 993 /** 994 * Returns the startup plugin if any 995 */ 996 public static Plugin getStartupPlugin() 997 { 998 return startupPlugin; 999 } 1000 1001 /** 1002 * Return content of the <code>CHANGELOG.txt</code> file 1003 */ 1004 public static String getChangeLog() 1005 { 1006 if (FileUtil.exists("CHANGELOG.txt")) 1007 return new String(FileUtil.load("CHANGELOG.txt", false)); 1008 1009 return ""; 1010 } 1011 1012 /** 1013 * Return content of the <code>COPYING.txt</code> file 1014 */ 1015 public static String getLicense() 1016 { 1017 if (FileUtil.exists("COPYING.txt")) 1018 return new String(FileUtil.load("COPYING.txt", false)); 1019 1020 return ""; 1021 } 1022 1023 /** 1024 * Return content of the <code>README.txt</code> file 1025 */ 1026 public static String getReadMe() 1027 { 1028 if (FileUtil.exists("README.txt")) 1029 return new String(FileUtil.load("README.txt", false)); 1030 1031 return ""; 1032 } 1033 1034 /** 1035 * @deprecated Uses <code>Icy.getMainInterface().addSequence(Sequence)</code> instead. 1036 */ 1037 @Deprecated 1038 public static void addSequence(final Sequence sequence) 1039 { 1040 Icy.getMainInterface().addSequence(sequence); 1041 } 1042 1043 static void nativeLibrariesInit() 1044 { 1045 // build the local native library path 1046 final String libPath = LIB_PATH + FileUtil.separator + SystemUtil.getOSArchIdString(); 1047 final File libFile = new File(libPath); 1048 1049 // get all files in local native library path 1050 final File[] files = FileUtil.getFiles(libFile, null, true, true, false); 1051 final ArrayList<String> directories = new ArrayList<String>(); 1052 1053 // add base local native library path to user library paths 1054 directories.add(libFile.getAbsolutePath()); 1055 // add base temporary native library path to user library paths 1056 directories.add(SystemUtil.getTempLibraryDirectory()); 1057 1058 for (File f : files) 1059 { 1060 if (f.isDirectory()) 1061 { 1062 // add all directories to user library paths 1063 final String filePath = f.getAbsolutePath(); 1064 if (!directories.contains(filePath)) 1065 directories.add(filePath); 1066 } 1067 } 1068 1069 // add lib folder for unix system 1070 if (SystemUtil.isUnix()) 1071 { 1072 directories.add("/lib"); 1073 directories.add("/usr/lib"); 1074 1075 if (SystemUtil.is64bits()) 1076 { 1077 directories.add("/lib64"); 1078 directories.add("/lib/x86_64"); 1079 directories.add("/lib/x86_64-linux-gnu"); 1080 directories.add("/usr/lib64"); 1081 directories.add("/usr/lib/x86_64"); 1082 directories.add("/usr/lib/x86_64-linux-gnu"); 1083 } 1084 else 1085 { 1086 directories.add("/lib/x86"); 1087 directories.add("/lib/x86-linux-gnu"); 1088 directories.add("/usr/lib/x86"); 1089 directories.add("/usr/lib/x86-linux-gnu"); 1090 } 1091 } 1092 1093 if (!SystemUtil.addToJavaLibraryPath(directories.toArray(new String[directories.size()]))) 1094 System.err.println("Native libraries may not load correctly."); 1095 1096 // load native libraries 1097 loadVtkLibrary(libPath); 1098 // loadItkLibrary(libPath); 1099 1100 // disable native lib support for JAI as we don't provide them (for the moment) 1101 SystemUtil.setProperty("com.sun.media.jai.disableMediaLib", "true"); 1102 } 1103 1104 private static void loadVtkLibrary(String libPath) 1105 { 1106 final String vtkLibPath = libPath + FileUtil.separator + "vtk"; 1107 1108 // we load it directly from inner lib path if possible 1109 System.setProperty("vtk.lib.dir", vtkLibPath); 1110 1111 vtkLibraryLoaded = false; 1112 try 1113 { 1114 // if (SystemUtil.isUnix()) 1115 // { 1116 // vtkNativeLibrary.LoadAllNativeLibraries(); 1117 // 1118 // // assume VTK loaded if at least 1 native library is loaded 1119 // for (vtkNativeLibrary lib : vtkNativeLibrary.values()) 1120 // if (lib.IsLoaded()) 1121 // vtkLibraryLoaded = true; 1122 // } 1123 // else 1124 { 1125 loadLibrary(vtkLibPath, "vtkalglib"); 1126 loadLibrary(vtkLibPath, "vtkexpat"); 1127 loadLibrary(vtkLibPath, "vtkDICOMParser"); 1128 loadLibrary(vtkLibPath, "vtkjpeg"); 1129 loadLibrary(vtkLibPath, "vtkjsoncpp"); 1130 loadLibrary(vtkLibPath, "vtkzlib"); 1131 loadLibrary(vtkLibPath, "vtkoggtheora", false); 1132 loadLibrary(vtkLibPath, "vtkverdict"); 1133 loadLibrary(vtkLibPath, "vtkpng"); 1134 1135 loadLibrary(vtkLibPath, "vtkgl2ps", false); // 1136 1137 loadLibrary(vtkLibPath, "vtktiff"); 1138 loadLibrary(vtkLibPath, "vtklibxml2"); 1139 loadLibrary(vtkLibPath, "vtkproj4"); 1140 loadLibrary(vtkLibPath, "vtksys"); 1141 loadLibrary(vtkLibPath, "vtkfreetype"); 1142 loadLibrary(vtkLibPath, "vtkmetaio"); 1143 loadLibrary(vtkLibPath, "vtkftgl", false); 1144 1145 loadLibrary(vtkLibPath, "vtkftgl2", false); // 1146 1147 loadLibrary(vtkLibPath, "vtkglew", false); 1148 loadLibrary(vtkLibPath, "vtkCommonCore"); 1149 loadLibrary(vtkLibPath, "vtkWrappingJava"); 1150 loadLibrary(vtkLibPath, "vtkCommonSystem"); 1151 loadLibrary(vtkLibPath, "vtkCommonMath"); 1152 loadLibrary(vtkLibPath, "vtkCommonMisc"); 1153 loadLibrary(vtkLibPath, "vtkCommonTransforms"); 1154 if (SystemUtil.isMac()) 1155 { 1156 loadLibrary(vtkLibPath, "vtkhdf5.8.0.2", false); 1157 loadLibrary(vtkLibPath, "vtkhdf5_hl.8.0.2", false); 1158 } 1159 else 1160 { 1161 loadLibrary(vtkLibPath, "vtkhdf5", false); 1162 loadLibrary(vtkLibPath, "vtkhdf5_hl", false); 1163 } 1164 loadLibrary(vtkLibPath, "vtkNetCDF"); 1165 loadLibrary(vtkLibPath, "vtkNetCDF_cxx"); 1166 loadLibrary(vtkLibPath, "vtkCommonDataModel"); 1167 loadLibrary(vtkLibPath, "vtkCommonColor"); 1168 loadLibrary(vtkLibPath, "vtkCommonComputationalGeometry"); 1169 loadLibrary(vtkLibPath, "vtkCommonExecutionModel"); 1170 loadLibrary(vtkLibPath, "vtkexoIIc"); 1171 loadLibrary(vtkLibPath, "vtkFiltersVerdict"); 1172 loadLibrary(vtkLibPath, "vtkFiltersProgrammable"); 1173 loadLibrary(vtkLibPath, "vtkImagingMath"); 1174 loadLibrary(vtkLibPath, "vtkIOCore"); 1175 loadLibrary(vtkLibPath, "vtkIOEnSight"); 1176 loadLibrary(vtkLibPath, "vtkIOVideo"); 1177 loadLibrary(vtkLibPath, "vtkIOLegacy"); 1178 loadLibrary(vtkLibPath, "vtkIONetCDF"); 1179 loadLibrary(vtkLibPath, "vtkIOXMLParser"); 1180 loadLibrary(vtkLibPath, "vtkIOXML"); 1181 loadLibrary(vtkLibPath, "vtkIOImage"); 1182 loadLibrary(vtkLibPath, "vtksqlite", false); 1183 loadLibrary(vtkLibPath, "vtkIOSQL"); 1184 loadLibrary(vtkLibPath, "vtkIOMovie"); 1185 loadLibrary(vtkLibPath, "vtkParallelCore"); 1186 loadLibrary(vtkLibPath, "vtkImagingCore"); 1187 loadLibrary(vtkLibPath, "vtkFiltersCore"); 1188 loadLibrary(vtkLibPath, "vtkImagingColor"); 1189 loadLibrary(vtkLibPath, "vtkImagingFourier"); 1190 loadLibrary(vtkLibPath, "vtkImagingSources"); 1191 loadLibrary(vtkLibPath, "vtkImagingHybrid"); 1192 loadLibrary(vtkLibPath, "vtkImagingStatistics"); 1193 loadLibrary(vtkLibPath, "vtkIOGeometry"); 1194 loadLibrary(vtkLibPath, "vtkIOPLY"); 1195 loadLibrary(vtkLibPath, "vtkFiltersSelection"); 1196 loadLibrary(vtkLibPath, "vtkImagingGeneral"); 1197 loadLibrary(vtkLibPath, "vtkImagingStencil"); 1198 loadLibrary(vtkLibPath, "vtkImagingMorphological"); 1199 loadLibrary(vtkLibPath, "vtkFiltersGeometry"); 1200 loadLibrary(vtkLibPath, "vtkFiltersStatistics"); 1201 loadLibrary(vtkLibPath, "vtkFiltersImaging"); 1202 loadLibrary(vtkLibPath, "vtkIOLSDyna"); 1203 loadLibrary(vtkLibPath, "vtkFiltersGeneral"); 1204 loadLibrary(vtkLibPath, "vtkFiltersHyperTree"); 1205 loadLibrary(vtkLibPath, "vtkFiltersSMP"); 1206 loadLibrary(vtkLibPath, "vtkFiltersTexture"); 1207 loadLibrary(vtkLibPath, "vtkFiltersAMR"); 1208 loadLibrary(vtkLibPath, "vtkFiltersExtraction"); 1209 loadLibrary(vtkLibPath, "vtkFiltersSources"); 1210 loadLibrary(vtkLibPath, "vtkIOExodus"); 1211 loadLibrary(vtkLibPath, "vtkFiltersGeneric"); 1212 loadLibrary(vtkLibPath, "vtkFiltersModeling"); 1213 loadLibrary(vtkLibPath, "vtkIOAMR"); 1214 loadLibrary(vtkLibPath, "vtkFiltersFlowPaths"); 1215 loadLibrary(vtkLibPath, "vtkInfovisCore"); 1216 loadLibrary(vtkLibPath, "vtkIOInfovis"); 1217 loadLibrary(vtkLibPath, "vtkInfovisLayout"); 1218 loadLibrary(vtkLibPath, "vtkRenderingCore"); 1219 loadLibrary(vtkLibPath, "vtkRenderingLOD"); 1220 loadLibrary(vtkLibPath, "vtkRenderingImage"); 1221 loadLibrary(vtkLibPath, "vtkRenderingFreeType"); 1222 loadLibrary(vtkLibPath, "vtkDomainsChemistry"); 1223 1224 loadLibrary(vtkLibPath, "vtkDomainsChemistryOpenGL2", false); 1225 1226 loadLibrary(vtkLibPath, "vtkInteractionStyle"); 1227 loadLibrary(vtkLibPath, "vtkIOImport"); 1228 loadLibrary(vtkLibPath, "vtkRenderingAnnotation"); 1229 loadLibrary(vtkLibPath, "vtkRenderingLabel"); 1230 loadLibrary(vtkLibPath, "vtkFiltersHybrid"); 1231 loadLibrary(vtkLibPath, "vtkFiltersParallel"); 1232 loadLibrary(vtkLibPath, "vtkFiltersParallelImaging"); 1233 loadLibrary(vtkLibPath, "vtkIOMINC"); 1234 loadLibrary(vtkLibPath, "vtkIOParallel"); 1235 loadLibrary(vtkLibPath, "vtkRenderingVolume"); 1236 loadLibrary(vtkLibPath, "vtkRenderingVolumeAMR", false); 1237 loadLibrary(vtkLibPath, "vtkInteractionWidgets"); 1238 loadLibrary(vtkLibPath, "vtkInteractionImage"); 1239 loadLibrary(vtkLibPath, "vtkViewsCore"); 1240 1241 loadLibrary(vtkLibPath, "vtkRenderingOpenGL", false); // 1242 1243 loadLibrary(vtkLibPath, "vtkRenderingOpenGL2", false); 1244 1245 loadLibrary(vtkLibPath, "vtkRenderingLIC", false); // 1246 loadLibrary(vtkLibPath, "vtkRenderingVolumeOpenGL", false); // 1247 1248 loadLibrary(vtkLibPath, "vtkRenderingVolumeOpenGL2", false); 1249 1250 loadLibrary(vtkLibPath, "vtkRenderingContext2D"); 1251 loadLibrary(vtkLibPath, "vtkRenderingContextOpenGL", false); // 1252 1253 loadLibrary(vtkLibPath, "vtkRenderingContextOpenGL2", false); 1254 1255 loadLibrary(vtkLibPath, "vtkRenderingGL2PS", false); // 1256 1257 loadLibrary(vtkLibPath, "vtkViewsContext2D"); 1258 loadLibrary(vtkLibPath, "vtkGeovisCore"); 1259 loadLibrary(vtkLibPath, "vtkIOExport"); 1260 loadLibrary(vtkLibPath, "vtkChartsCore"); 1261 loadLibrary(vtkLibPath, "vtkViewsInfovis"); 1262 loadLibrary(vtkLibPath, "vtkViewsGeovis", false); 1263 1264 // JAVA wrapper 1265 loadLibrary(vtkLibPath, "vtkCommonCoreJava"); 1266 loadLibrary(vtkLibPath, "vtkCommonSystemJava"); 1267 loadLibrary(vtkLibPath, "vtkCommonMathJava"); 1268 loadLibrary(vtkLibPath, "vtkCommonMiscJava"); 1269 loadLibrary(vtkLibPath, "vtkCommonTransformsJava"); 1270 loadLibrary(vtkLibPath, "vtkCommonDataModelJava"); 1271 loadLibrary(vtkLibPath, "vtkCommonColorJava"); 1272 loadLibrary(vtkLibPath, "vtkCommonComputationalGeometryJava"); 1273 loadLibrary(vtkLibPath, "vtkCommonExecutionModelJava"); 1274 loadLibrary(vtkLibPath, "vtkFiltersVerdictJava"); 1275 loadLibrary(vtkLibPath, "vtkFiltersProgrammableJava"); 1276 loadLibrary(vtkLibPath, "vtkImagingMathJava"); 1277 loadLibrary(vtkLibPath, "vtkIOCoreJava"); 1278 loadLibrary(vtkLibPath, "vtkIOEnSightJava"); 1279 loadLibrary(vtkLibPath, "vtkIOVideoJava"); 1280 loadLibrary(vtkLibPath, "vtkIOLegacyJava"); 1281 loadLibrary(vtkLibPath, "vtkIONetCDFJava"); 1282 loadLibrary(vtkLibPath, "vtkIOXMLParserJava"); 1283 loadLibrary(vtkLibPath, "vtkIOXMLJava"); 1284 loadLibrary(vtkLibPath, "vtkIOImageJava"); 1285 loadLibrary(vtkLibPath, "vtkIOSQLJava"); 1286 loadLibrary(vtkLibPath, "vtkIOMovieJava"); 1287 loadLibrary(vtkLibPath, "vtkParallelCoreJava"); 1288 loadLibrary(vtkLibPath, "vtkImagingCoreJava"); 1289 loadLibrary(vtkLibPath, "vtkFiltersCoreJava"); 1290 loadLibrary(vtkLibPath, "vtkImagingColorJava"); 1291 loadLibrary(vtkLibPath, "vtkImagingFourierJava"); 1292 loadLibrary(vtkLibPath, "vtkImagingSourcesJava"); 1293 loadLibrary(vtkLibPath, "vtkImagingHybridJava"); 1294 loadLibrary(vtkLibPath, "vtkImagingStatisticsJava"); 1295 loadLibrary(vtkLibPath, "vtkIOGeometryJava"); 1296 loadLibrary(vtkLibPath, "vtkIOPLYJava"); 1297 loadLibrary(vtkLibPath, "vtkFiltersSelectionJava"); 1298 loadLibrary(vtkLibPath, "vtkImagingGeneralJava"); 1299 loadLibrary(vtkLibPath, "vtkImagingStencilJava"); 1300 loadLibrary(vtkLibPath, "vtkImagingMorphologicalJava"); 1301 loadLibrary(vtkLibPath, "vtkFiltersGeometryJava"); 1302 loadLibrary(vtkLibPath, "vtkFiltersStatisticsJava"); 1303 loadLibrary(vtkLibPath, "vtkFiltersImagingJava"); 1304 loadLibrary(vtkLibPath, "vtkIOLSDynaJava"); 1305 loadLibrary(vtkLibPath, "vtkFiltersGeneralJava"); 1306 loadLibrary(vtkLibPath, "vtkFiltersHyperTreeJava"); 1307 loadLibrary(vtkLibPath, "vtkFiltersSMPJava"); 1308 loadLibrary(vtkLibPath, "vtkFiltersTextureJava"); 1309 loadLibrary(vtkLibPath, "vtkFiltersAMRJava"); 1310 loadLibrary(vtkLibPath, "vtkFiltersExtractionJava"); 1311 loadLibrary(vtkLibPath, "vtkFiltersSourcesJava"); 1312 loadLibrary(vtkLibPath, "vtkIOExodusJava"); 1313 loadLibrary(vtkLibPath, "vtkFiltersGenericJava"); 1314 loadLibrary(vtkLibPath, "vtkFiltersModelingJava"); 1315 loadLibrary(vtkLibPath, "vtkIOAMRJava"); 1316 loadLibrary(vtkLibPath, "vtkFiltersFlowPathsJava"); 1317 loadLibrary(vtkLibPath, "vtkInfovisCoreJava"); 1318 loadLibrary(vtkLibPath, "vtkIOInfovisJava"); 1319 loadLibrary(vtkLibPath, "vtkInfovisLayoutJava"); 1320 loadLibrary(vtkLibPath, "vtkRenderingCoreJava"); 1321 loadLibrary(vtkLibPath, "vtkRenderingLODJava"); 1322 loadLibrary(vtkLibPath, "vtkRenderingImageJava"); 1323 loadLibrary(vtkLibPath, "vtkRenderingFreeTypeJava"); 1324 loadLibrary(vtkLibPath, "vtkDomainsChemistryJava"); 1325 1326 loadLibrary(vtkLibPath, "vtkDomainsChemistryOpenGL2Java", false); 1327 1328 loadLibrary(vtkLibPath, "vtkInteractionStyleJava"); 1329 loadLibrary(vtkLibPath, "vtkIOImportJava"); 1330 loadLibrary(vtkLibPath, "vtkRenderingAnnotationJava"); 1331 loadLibrary(vtkLibPath, "vtkRenderingLabelJava"); 1332 loadLibrary(vtkLibPath, "vtkFiltersHybridJava"); 1333 loadLibrary(vtkLibPath, "vtkFiltersParallelJava"); 1334 loadLibrary(vtkLibPath, "vtkFiltersParallelImagingJava"); 1335 loadLibrary(vtkLibPath, "vtkIOMINCJava"); 1336 loadLibrary(vtkLibPath, "vtkIOParallelJava"); 1337 loadLibrary(vtkLibPath, "vtkRenderingVolumeJava"); 1338 loadLibrary(vtkLibPath, "vtkRenderingVolumeAMRJava", false); 1339 loadLibrary(vtkLibPath, "vtkInteractionWidgetsJava"); 1340 loadLibrary(vtkLibPath, "vtkInteractionImageJava"); 1341 loadLibrary(vtkLibPath, "vtkViewsCoreJava"); 1342 loadLibrary(vtkLibPath, "vtkRenderingOpenGLJava", false); // 1343 1344 loadLibrary(vtkLibPath, "vtkRenderingOpenGL2Java", false); 1345 1346 loadLibrary(vtkLibPath, "vtkRenderingLICJava", false); // 1347 loadLibrary(vtkLibPath, "vtkRenderingVolumeOpenGLJava", false); // 1348 1349 loadLibrary(vtkLibPath, "vtkRenderingVolumeOpenGL2Java", false); 1350 1351 loadLibrary(vtkLibPath, "vtkRenderingContext2DJava"); 1352 1353 loadLibrary(vtkLibPath, "vtkRenderingContextOpenGLJava", false); // 1354 1355 loadLibrary(vtkLibPath, "vtkRenderingContextOpenGL2Java", false); 1356 1357 loadLibrary(vtkLibPath, "vtkRenderingGL2PSJava", false); // 1358 1359 loadLibrary(vtkLibPath, "vtkViewsContext2DJava"); 1360 loadLibrary(vtkLibPath, "vtkGeovisCoreJava"); 1361 loadLibrary(vtkLibPath, "vtkIOExportJava"); 1362 loadLibrary(vtkLibPath, "vtkChartsCoreJava"); 1363 loadLibrary(vtkLibPath, "vtkViewsInfovisJava"); 1364 loadLibrary(vtkLibPath, "vtkViewsGeovisJava", false); 1365 1366 // VTK library successfully loaded 1367 vtkLibraryLoaded = true; 1368 } 1369 1370 // redirect vtk error log to file 1371 vtkNativeLibrary.DisableOutputWindow(new File("vtk.log")); 1372 } 1373 catch (Throwable e1) 1374 { 1375 IcyExceptionHandler.showErrorMessage(e1, false, false); 1376 1377 // // try to load the VTK way 1378 // try 1379 // { 1380 // System.out.print("Try to load VTK library using VTK method... "); 1381 // 1382 // vtkLibraryLoaded = vtkNativeLibrary.LoadAllNativeLibraries(); 1383 // 1384 // if (vtkLibraryLoaded) 1385 // System.out.println("success !"); 1386 // else 1387 // System.out.println("failed !"); 1388 // 1389 // // redirect vtk error log to file 1390 // vtkNativeLibrary.DisableOutputWindow(new File("vtk.log")); 1391 // } 1392 // catch (Throwable e2) 1393 // { 1394 // IcyExceptionHandler.showErrorMessage(e2, false, false); 1395 // } 1396 } 1397 1398 if (vtkLibraryLoaded) 1399 { 1400 final String vv = new vtkVersion().GetVTKVersion(); 1401 1402 System.out.println("VTK " + vv + " library successfully loaded..."); 1403 1404 // final vtkJavaGarbageCollector vtkJavaGarbageCollector = 1405 // vtkObjectBase.JAVA_OBJECT_MANAGER 1406 // .getAutoGarbageCollector(); 1407 // 1408 // set auto garbage collection for VTK (every 20 seconds should be enough) 1409 // probably not a good idea... 1410 // vtkJavaGarbageCollector.SetScheduleTime(5, TimeUnit.SECONDS); 1411 // vtkJavaGarbageCollector.SetAutoGarbageCollection(true); 1412 } 1413 else 1414 { 1415 System.out.println("Cannot load VTK library..."); 1416 1417 if (SystemUtil.isMac()) 1418 { 1419 final String osVer = SystemUtil.getOSVersion(); 1420 1421 if (osVer.startsWith("10.6") || osVer.startsWith("10.5")) 1422 System.out.println( 1423 "VTK 6.3 is not supported on OSX " + osVer + ", version 10.7 or above is required."); 1424 } 1425 } 1426 } 1427 1428 private static void loadItkLibrary(String osDir) 1429 { 1430 final String itkLibDir = osDir + FileUtil.separator + "itk"; 1431 1432 try 1433 { 1434 loadLibrary(itkLibDir, "SimpleITKJava", true); 1435 1436 System.out.println("SimpleITK library successfully loaded..."); 1437 itkLibraryLoaded = true; 1438 } 1439 catch (Throwable e) 1440 { 1441 System.out.println("Cannot load SimpleITK library..."); 1442 } 1443 } 1444 1445 private static void loadLibrary(String dir, String name, boolean mandatory, boolean showLog) 1446 { 1447 if (mandatory) 1448 SystemUtil.loadLibrary(dir, name); 1449 else 1450 { 1451 try 1452 { 1453 SystemUtil.loadLibrary(dir, name); 1454 } 1455 catch (Throwable e) 1456 { 1457 if (showLog) 1458 System.out.println("cannot load " + name + ", skipping..."); 1459 } 1460 } 1461 } 1462 1463 private static void loadLibrary(String dir, String name, boolean mandatory) 1464 { 1465 loadLibrary(dir, name, mandatory, false); 1466 } 1467 1468 private static void loadLibrary(String dir, String name) 1469 { 1470 loadLibrary(dir, name, true, false); 1471 } 1472 1473 static void nativeLibrariesShutdown() 1474 { 1475 // build the native local library path 1476 final String path = LIB_PATH + FileUtil.separator + SystemUtil.getOSArchIdString(); 1477 // get file list (we don't want hidden files if any) 1478 File[] libraryFiles = FileUtil.getFiles(new File(path), null, true, false, false); 1479 1480 // remove previous copied files 1481 for (File libraryFile : libraryFiles) 1482 { 1483 // get file in root directory 1484 final File file = new File(libraryFile.getName()); 1485 // invoke delete on exit if the file exists 1486 if (file.exists()) 1487 file.deleteOnExit(); 1488 } 1489 1490 // get file list from temporary native library path 1491 libraryFiles = FileUtil.getFiles(new File(SystemUtil.getTempLibraryDirectory()), null, true, false, false); 1492 1493 // remove previous copied files 1494 for (File libraryFile : libraryFiles) 1495 { 1496 // delete file 1497 if (!FileUtil.delete(libraryFile, false)) 1498 libraryFile.deleteOnExit(); 1499 } 1500 } 1501}