001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2018 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see http://www.gnu.org/licenses. 027 */ 028 029package edu.wisc.ssec.mcidasv; 030 031 032import java.io.BufferedReader; 033import java.io.BufferedWriter; 034import java.io.File; 035import java.io.FileReader; 036import java.io.FileWriter; 037 038import java.util.Hashtable; 039import java.util.Map; 040import java.util.Properties; 041 042import java.awt.event.ActionEvent; 043 044import javax.swing.JEditorPane; 045import javax.swing.JLabel; 046import javax.swing.JOptionPane; 047import javax.swing.JPanel; 048import javax.swing.event.HyperlinkEvent; 049import javax.swing.event.HyperlinkListener; 050 051import ucar.unidata.idv.IdvObjectStore; 052import ucar.unidata.idv.IntegratedDataViewer; 053import ucar.unidata.util.FileManager; 054import ucar.unidata.util.IOUtil; 055import ucar.unidata.util.LogUtil; 056import ucar.unidata.util.Misc; 057import ucar.unidata.util.StringUtil; 058 059import org.slf4j.Logger; 060import org.slf4j.LoggerFactory; 061 062import edu.wisc.ssec.mcidasv.startupmanager.StartupManager; 063import edu.wisc.ssec.mcidasv.util.SystemState; 064 065/** 066 * This class is used to initialize McIDAS-V. 067 * 068 * <p>The initialization process includes creating an 069 * {@literal "object store"} (for preferences), user-modifiable settings, 070 * and so on.</p> 071 * 072 * <p>McIDAS-V uses this class to perform pretty much all version-check 073 * operations.</p> 074 */ 075public class StateManager extends ucar.unidata.idv.StateManager 076 implements Constants, HyperlinkListener 077{ 078 /** Logging object. */ 079 private static final Logger logger = 080 LoggerFactory.getLogger(StateManager.class); 081 082 /** Error message shown when given userpath cannot be used. */ 083 public static final String USERPATH_IS_BAD_MESSAGE = 084 "<html>McIDAS-V is unable to create or write to the local user's " + 085 "directory.<br>Please select a directory.</html>"; 086 087 /** Message shown when asking the user to select a userpath. */ 088 public static final String USERPATH_PICK = 089 "Please select a directory to use as the McIDAS-V user path."; 090 091 /** 092 * Lazily-loaded VisAD build date. Value may be {@code null}. 093 * 094 * @see #getVisadDate() 095 */ 096 private String visadDate; 097 098 /** 099 * Lazily-loaded VisAD revision number. Value may be {@code null}. 100 * 101 * @see #getVisadVersion() 102 */ 103 private String visadVersion; 104 105 /** 106 * Lazily-loaded {@code ncIdv.jar} build timestamp. Value may be 107 * {@code null}. 108 * 109 * @see #getNetcdfDate() 110 */ 111 private String netcdfDate; 112 113 /** 114 * Lazily-loaded {@code ncIdv.jar} version. Value may be {@code null}. 115 * 116 * @see #getNetcdfVersion() 117 */ 118 private String netcdfVersion; 119 120 /** 121 * Lazily-loaded {@code mcidasv.jar} version. Value may be {@code null}. 122 * 123 * @see #getMcIdasVersion() 124 */ 125 private String version; 126 127 public StateManager(IntegratedDataViewer idv) { 128 super(idv); 129 } 130 131 /** 132 * Override to set the right user directory. 133 * 134 * @return Newly created object store. 135 */ 136 @Override protected IdvObjectStore doMakeObjectStore() { 137 IdvObjectStore store = new IdvObjectStore(getIdv(), 138 getStoreSystemName(), getStoreName(), 139 getIdv().getEncoderForRead(), 140 StartupManager.getInstance().getPlatform().getUserDirectory()); 141 initObjectStore(store); 142 return store; 143 } 144 145 /** 146 * Initialize the given object store. This mostly initializes the user's 147 * {@literal "userpath"} directory when it is first created. 148 * 149 * @param store Object store to initialize. Cannot be {@code null}. 150 */ 151 @Override protected void initObjectStore(IdvObjectStore store) { 152 while (!store.userDirectoryOk()) { 153 LogUtil.userMessage(USERPATH_IS_BAD_MESSAGE); 154 File dir = FileManager.getDirectory(null, USERPATH_PICK); 155 if (dir != null) { 156 store.setOverrideDirectory(dir); 157 } else { 158 // TODO(jon): figure out why we aren't using regular exit stuff 159 System.exit(0); 160 } 161 } 162 163 if (store.getMadeUserDirectory()) { 164 initNewUserDirectory(store.getUserDirectory()); 165 } 166 initUserDirectory(store.getUserDirectory()); 167 } 168 169 /** 170 * Initialize the McIDAS-V user directory (if it is not already 171 * initalized). 172 * 173 * <p>Here, initialization means {@literal "the user directory exists, 174 * and contains a barebones version of mcidasv.rbi"}.</p> 175 * 176 * @param directory McIDAS-V user directory. Cannot be {@code null}. 177 */ 178 @Override protected void initUserDirectory(File directory) { 179 File idvRbi = new File(IOUtil.joinDir(directory, "idv.rbi")); 180 if (idvRbi.exists()) { 181 if (!idvRbi.delete()) { 182 logger.warn("Could not delete '"+idvRbi+'\''); 183 } 184 } 185 File rbiFile = new File(IOUtil.joinDir(directory, "mcidasv.rbi")); 186 if (!rbiFile.exists()) { 187 String defaultRbi = 188 IOUtil.readContents( 189 "/edu/wisc/ssec/mcidasv/resources/userrbi.rbi", 190 (String)null); 191 if (defaultRbi != null) { 192 try { 193 IOUtil.writeFile(rbiFile, defaultRbi); 194 } catch (Exception exc) { 195 logException("Writing default rbi", exc); 196 } 197 } 198 } 199 } 200 201 /** 202 * Handle a change to a link. 203 * 204 * @param e Link event. Cannot be {@code null}. 205 */ 206 @Override public void hyperlinkUpdate(HyperlinkEvent e) { 207 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { 208 if (e.getURL() == null) { 209 click(e.getDescription()); 210 } else { 211 click(e.getURL().toString()); 212 } 213 } 214 } 215 216 /** 217 * Handle a click on a link. 218 * 219 * @param url Link to visit. 220 */ 221 public void click(String url) { 222 getIdv().actionPerformed(new ActionEvent(this, 0, url)); 223 } 224 225 /** 226 * Get the name of the current operating system (via 227 * {@literal "os.name"} system property). 228 * 229 * <p>Note: all space characters will be replaced with underscores.</p> 230 * 231 * @return Operating system name. 232 */ 233 public String getOSName() { 234 String os = System.getProperty("os.name"); 235 os = os.replaceAll(" ", "_"); 236 return os; 237 } 238 239 public String getMcIdasVersionAbout() { 240 if (version == null) { 241 getMcIdasVersion(); 242 } 243 244 String aboutText = (String)getProperty(Constants.PROP_ABOUTTEXT); 245 String versionAbout = IOUtil.readContents(aboutText, ""); 246 versionAbout = StringUtil.replace(versionAbout, MACRO_VERSION, version); 247 Properties props = Misc.readProperties( 248 (String) getProperty(Constants.PROP_VERSIONFILE), 249 null, 250 getClass() 251 ); 252 253 String value = getIdvVersion(); 254 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_IDV_VERSION, value); 255 value = props.getProperty(PROP_COPYRIGHT_YEAR, ""); 256 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_COPYRIGHT_YEAR, value); 257 value = props.getProperty(PROP_BUILD_DATE, "Unknown"); 258 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_BUILDDATE, value); 259 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_VISAD_VERSION, getVisadVersion()); 260 261 return versionAbout; 262 } 263 264 public String getMcIdasVersion() { 265 if (version != null) { 266 return version; 267 } 268 269 Properties props = new Properties(); 270 props = Misc.readProperties((String) getProperty(Constants.PROP_VERSIONFILE), null, getClass()); 271 String maj = props.getProperty(PROP_VERSION_MAJOR, "0"); 272 String min = props.getProperty(PROP_VERSION_MINOR, "0"); 273 String rel = props.getProperty(PROP_VERSION_RELEASE, ""); 274 275 version = maj.concat(".").concat(min).concat(rel); 276 277 return version; 278 } 279 280 /** 281 * Returns the current Jython version. 282 * 283 * @return Jython's version information. 284 */ 285 @Override public String getJythonVersion() { 286 return org.python.Version.PY_VERSION; 287 } 288 289 /** 290 * Get a property. 291 * 292 * @param name Name of the property. Cannot be {@code null}. 293 * 294 * @return Value associated with {@code name} or {@code null}. 295 */ 296 @Override public Object getProperty(final String name) { 297 Object value = null; 298 if (McIDASV.isMac()) { 299 value = getProperties().get("mac."+name); 300 } 301 if (value == null) { 302 value = getProperties().get(name); 303 } 304 if (value == null) { 305 String fixedName = StateManager.fixIds(name); 306 if (!name.equals(fixedName)) { 307 return getProperties().get(fixedName); 308 } 309 } 310 return value; 311 } 312 313 /** 314 * Find the value associated with the given ID by checking the 315 * {@literal "properties"}, and if nothing was found, check the preferences. 316 * 317 * @param name Property or preference ID. Cannot be {@code null}. 318 * 319 * @return Either the value associated with {@code name} or {@code null}. 320 */ 321 public Object getPropertyOrPreference(String name) { 322 Object o = getProperty(name); 323 if (o == null) { 324 o = getPreference(name); 325 } 326 return o; 327 } 328 329 /** 330 * Find the {@link String} value associated with the given ID by checking 331 * the {@literal "properties"}, and if nothing was found, check the 332 * preferences. 333 * 334 * @param name Property or preference ID. Cannot be {@code null}. 335 * @param dflt Value to return if there is no property or preference 336 * associated with {@code name} 337 * 338 * @return Either the value associated with {@code name} or {@code dflt}. 339 */ 340 public String getPropertyOrPreference(String name, String dflt) { 341 String value = dflt; 342 Object o = getPropertyOrPreference(name); 343 if (o != null) { 344 value = o.toString(); 345 } 346 return value; 347 } 348 349 /** 350 * Find the {@link Integer} value associated with the given ID by checking 351 * the {@literal "properties"}, and if nothing was found, check the 352 * preferences. 353 * 354 * @param name Property or preference ID. Cannot be {@code null}. 355 * @param dflt Value to return if there is no property or preference 356 * associated with {@code name} 357 * 358 * @return Either the value associated with {@code name} or {@code dflt}. 359 */ 360 public int getPropertyOrPreference(String name, int dflt) { 361 int value = dflt; 362 Object o = getPropertyOrPreference(name); 363 if (o != null) { 364 value = Integer.valueOf(o.toString()); 365 } 366 return value; 367 } 368 369 /** 370 * Find the {@link Double} value associated with the given ID by checking 371 * the {@literal "properties"}, and if nothing was found, check the 372 * preferences. 373 * 374 * @param name Property or preference ID. Cannot be {@code null}. 375 * @param dflt Value to return if there is no property or preference 376 * associated with {@code name} 377 * 378 * @return Either the value associated with {@code name} or {@code dflt}. 379 */ 380 public double getPropertyOrPreference(String name, double dflt) { 381 double value = dflt; 382 Object o = getPropertyOrPreference(name); 383 if (o != null) { 384 value = Double.valueOf(o.toString()); 385 } 386 return value; 387 } 388 389 /** 390 * Find the {@link Boolean} value associated with the given ID by checking 391 * the {@literal "properties"}, and if nothing was found, check the 392 * preferences. 393 * 394 * @param name Property or preference ID. Cannot be {@code null}. 395 * @param dflt Value to return if there is no property or preference 396 * associated with {@code name} 397 * 398 * @return Either the value associated with {@code name} or {@code dflt}. 399 */ 400 public boolean getPropertyOrPreference(String name, boolean dflt) { 401 boolean value = dflt; 402 Object o = getPropertyOrPreference(name); 403 if (o != null) { 404 value = Boolean.valueOf(o.toString()); 405 } 406 return value; 407 } 408 409 /** 410 * Returns information about the current version of McIDAS-V and the IDV, 411 * along with their respective build dates. 412 * 413 * @return {@code Hashtable} containing versioning information. 414 */ 415 public Hashtable<String, String> getVersionInfo() { 416 String versionFile = (String)getProperty(Constants.PROP_VERSIONFILE); 417 Properties props = 418 Misc.readProperties(versionFile, null, getClass()); 419 420 String mcvBuild = props.getProperty(PROP_BUILD_DATE, "Unknown"); 421 422 Hashtable<String, String> table = new Hashtable<>(); 423 table.put("mcv.version.general", getMcIdasVersion()); 424 table.put("mcv.version.build", mcvBuild); 425 table.put("idv.version.general", getVersion()); 426 table.put("idv.version.build", getBuildDate()); 427 table.put("visad.version.general", getVisadVersion()); 428 table.put("visad.version.build", getVisadDate()); 429 table.put("netcdf.version.general", getNetcdfVersion()); 430 table.put("netcdf.version.build", getNetcdfDate()); 431 return table; 432 } 433 434 /** 435 * Return the timestamp from when {@code ncIdv.jar} was created. 436 * 437 * @return {@code String} representation of the creation timestamp. 438 */ 439 public String getNetcdfDate() { 440 if (netcdfDate == null) { 441 Map<String, String> props = SystemState.queryNcidvBuildProperties(); 442 netcdfDate = props.get("buildDate"); 443 netcdfVersion = props.get("version"); 444 } 445 return netcdfDate; 446 } 447 448 /** 449 * Return the version information within {@code ncIdv.jar}. 450 * 451 * @return Version of {@code ncIdv.jar} shipped by McIDAS-V. 452 */ 453 public String getNetcdfVersion() { 454 if (netcdfVersion == null) { 455 Map<String, String> props = SystemState.queryNcidvBuildProperties(); 456 netcdfDate = props.get("buildDate"); 457 netcdfVersion = props.get("version"); 458 } 459 return netcdfVersion; 460 } 461 462 /** 463 * Return the timestamp from when visad.jar was created. 464 * 465 * @return {@code String} representation of the creation timestamp. 466 * Likely to change formatting over time. 467 */ 468 public String getVisadDate() { 469 if (visadDate == null) { 470 Map<String, String> props = SystemState.queryVisadBuildProperties(); 471 visadDate = props.get(Constants.PROP_VISAD_DATE); 472 visadVersion = props.get(Constants.PROP_VISAD_REVISION); 473 } 474 return visadDate; 475 } 476 477 /** 478 * Return the {@literal "version"} of VisAD. 479 * 480 * @return Currently returns whatever the SVN revision number was when 481 * visad.jar was built. 482 */ 483 public String getVisadVersion() { 484 if (visadVersion == null) { 485 Map<String, String> props = SystemState.queryVisadBuildProperties(); 486 visadDate = props.get(Constants.PROP_VISAD_DATE); 487 visadVersion = props.get(Constants.PROP_VISAD_REVISION); 488 } 489 return visadVersion; 490 } 491 492 public String getIdvVersion() { 493 return getVersion(); 494 } 495 496 /** 497 * Overridden to set default of McIDAS-V 498 */ 499 @Override public String getStoreSystemName() { 500 return StartupManager.getInstance().getPlatform().getUserDirectory(); 501 } 502 503 /** 504 * Overridden to get dir of the unnecessary second level directory. 505 */ 506 @Override public String getStoreName() { 507 return ""; 508 } 509 510 /** 511 * Connect to McIDAS-V website and look for latest stable version. 512 * 513 * @return Latest stable version. 514 */ 515 public String getMcIdasVersionStable() { 516 String offscreen = "0"; 517 if (getIdv().getArgsManager().getIsOffScreen()) { 518 offscreen = "1"; 519 } 520 521 String version = ""; 522 try { 523 version = IOUtil.readContents(Constants.HOMEPAGE_URL+"/"+Constants.VERSION_HANDLER_URL+"?v="+getMcIdasVersion()+"&os="+getOSName()+"&off="+offscreen, ""); 524 } catch (Exception e) { 525 logger.warn("Could not get latest McV stable version", e); 526 } 527 return version.trim(); 528 } 529 530 /** 531 * Connect to McIDAS-V website and look for latest pre-release version. 532 * 533 * @return Latest pre-release version. 534 */ 535 public String getMcIdasVersionPrerelease() { 536 String version = ""; 537 try { 538 String htmlList = IOUtil.readContents(Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL, ""); 539 String lines[] = htmlList.split("\n"); 540 for (int i=0; i<lines.length; i++) { 541 String line = lines[i].trim(); 542 if (line.matches(".*McIDAS-V_\\d+\\.\\d+.*")) { 543 line = line.substring(line.indexOf("McIDAS-V_")+9); 544 String aVersion = line.substring(0, line.indexOf("_")); 545 if (version.isEmpty()) { 546 version = aVersion; 547 } else { 548 int comp = compareVersions(version, aVersion); 549 if (comp > 0) { 550 version = aVersion; 551 } 552 } 553 } 554 } 555 } catch (Exception e) { 556 logger.warn("Could not get latest McV pre-release version", e); 557 } 558 return version.trim(); 559 } 560 561 /** 562 * Connect to McIDAS website and look for latest notice. 563 * 564 * @return Contents of notice. String may be empty. 565 */ 566 public String getNoticeLatest() { 567 String notice = ""; 568 try { 569 notice = IOUtil.readContents(Constants.HOMEPAGE_URL+"/"+Constants.NOTICE_URL+"?requesting="+getMcIdasVersion()+"&os="+getOSName(), ""); 570 } catch (Exception e) { 571 logger.warn("Could not get latest notice", e); 572 } 573 if (!notice.contains("<notice>")) { 574 notice = ""; 575 } 576 notice = notice.replaceAll("<[/?]notice>",""); 577 return notice.trim(); 578 } 579 580 /** 581 * Compare version strings. 582 * 583 * <p>The logic is as follows. 584 * <pre> 585 * 0: thisVersion and thatVersion are equal. 586 * <0: thisVersion is greater. 587 * >0: thatVersion is greater. 588 * </pre> 589 * 590 * @param thisVersion First version string to compare. 591 * @param thatVersion Second version string to compare. 592 * 593 * @return Value indicating which of {@code thisVersion} and 594 * {@code thatVersion} is {@literal "greater"}. 595 */ 596 public static int compareVersions(String thisVersion, String thatVersion) { 597 int thisInt = versionToInteger(thisVersion); 598 int thatInt = versionToInteger(thatVersion); 599 return thatInt - thisInt; 600 } 601 602 /** 603 * Turn version strings of the form {@code #.#(a#)}, where # is one or two 604 * digits, a is one of alpha or beta, and () is optional, into an integer 605 * value... (empty) > beta > alpha. 606 * 607 * @param version String representation of version number. 608 * 609 * @return Integer representation of {@code version}. 610 */ 611 public static int versionToInteger(String version) { 612 int value = 0; 613 int p; 614 String part; 615 Character one = null; 616 617 try { 618 // Major version 619 p = version.indexOf('.'); 620 if (p > 0) { 621 part = version.substring(0,p); 622 value += Integer.parseInt(part) * 1000000; 623 version = version.substring(p+1); 624 } 625 626 // Minor version 627 int minor = 0; 628 int i = 0; 629 for (i = 0; i < 2 && i < version.length(); i++) { 630 one = version.charAt(i); 631 if (Character.isDigit(one)) { 632 if (i > 0) { 633 minor *= 10; 634 } 635 minor += Character.digit(one, 10) * 10000; 636 } else { 637 break; 638 } 639 } 640 value += minor; 641 if (one != null) { 642 version = version.substring(i); 643 } 644 645 // Alpha/beta/update/release status 646 if (version.length() == 0) { 647 value += 300; 648 } else if (version.charAt(0) == 'b') { 649 value += 200; 650 } else if (version.charAt(0) == 'a') { 651 value += 100; 652 } else if (version.charAt(0) == 'u') { 653 value += 400; 654 } else if (version.charAt(0) == 'r') { 655 value += 400; 656 } 657 for (i = 0; i < version.length(); i++) { 658 one = version.charAt(i); 659 if (Character.isDigit(one)) { 660 break; 661 } 662 } 663 if (one != null) { 664 version = version.substring(i); 665 } 666 667 // Alpha/beta version 668 if (version.length() > 0) { 669 value += Integer.parseInt(version); 670 } 671 } catch (Exception e) { 672 673 } 674 return value; 675 } 676 677 public boolean getIsPrerelease() { 678 boolean isPrerelease = false; 679 String version = getMcIdasVersion(); 680 if (version.contains("a") || version.contains("b")) { 681 isPrerelease = true; 682 } 683 return isPrerelease; 684 } 685 686 public void checkForNewerVersion(boolean notifyDialog) { 687 checkForNewerVersionStable(notifyDialog); 688 if (getStore().get(Constants.PREF_PRERELEASE_CHECK, getIsPrerelease())) { 689 checkForNewerVersionPrerelease(notifyDialog); 690 } 691 } 692 693 public void checkForNewerVersionStable(boolean notifyDialog) { 694 695 // get the stable version from the website (for statistics recording) 696 String thatVersion = getMcIdasVersionStable(); 697 698 // shortcut the rest of the process if we are processing offscreen 699 if (getIdv().getArgsManager().getIsOffScreen()) { 700 return; 701 } 702 703 String thisVersion = getMcIdasVersion(); 704 String titleText = "Version Check"; 705 706 if (thisVersion.isEmpty() || thatVersion.isEmpty()) { 707 if (notifyDialog) { 708 JOptionPane.showMessageDialog(null, 709 "Version check failed", 710 titleText, 711 JOptionPane.WARNING_MESSAGE); 712 } 713 } else if (compareVersions(thisVersion, thatVersion) > 0) { 714 String labelText = "<html>Version <b>" + thatVersion + "</b> is available<br><br>"; 715 labelText += "Visit <a href=\"" + Constants.HOMEPAGE_URL + "\">"; 716 labelText += Constants.HOMEPAGE_URL + "</a> to download</html>"; 717 718 JPanel backgroundColorGetterPanel = new JPanel(); 719 JEditorPane messageText = new JEditorPane("text/html", labelText); 720 messageText.setBackground(backgroundColorGetterPanel.getBackground()); 721 messageText.setEditable(false); 722 messageText.addHyperlinkListener(this); 723 724 //JLabel message = new JLabel(labelText, JLabel.CENTER); 725 JOptionPane.showMessageDialog(null, 726 messageText, 727 titleText, 728 JOptionPane.INFORMATION_MESSAGE); 729 } else { 730 if (notifyDialog) { 731 String labelText = "<html>This version (<b>" + thisVersion + "</b>) is up to date</html>"; 732 JLabel message = new JLabel(labelText, JLabel.CENTER); 733 JOptionPane.showMessageDialog(null, 734 message, 735 titleText, 736 JOptionPane.INFORMATION_MESSAGE); 737 } 738 } 739 } 740 741 public void checkForNewerVersionPrerelease(boolean notifyDialog) { 742 743 // shortcut the rest of the process if we are processing offscreen 744 if (getIdv().getArgsManager().getIsOffScreen()) { 745 return; 746 } 747 748 String thisVersion = getMcIdasVersion(); 749 String thatVersion = getMcIdasVersionPrerelease(); 750 String titleText = "Prerelease Check"; 751 752 if (thisVersion.isEmpty() || thatVersion.isEmpty()) { 753 if (notifyDialog) { 754 JOptionPane.showMessageDialog( 755 null, "No prerelease version available", titleText, 756 JOptionPane.WARNING_MESSAGE); 757 } 758 } else if (compareVersions(thisVersion, thatVersion) > 0) { 759 String labelText = "<html>Prerelease <b>" + thatVersion + "</b> is available<br><br>"; 760 labelText += "Visit <a href=\"" + Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL + "\">"; 761 labelText += Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL + "</a> to download</html>"; 762 763 JPanel backgroundColorGetterPanel = new JPanel(); 764 JEditorPane messageText = new JEditorPane("text/html", labelText); 765 messageText.setBackground(backgroundColorGetterPanel.getBackground()); 766 messageText.setEditable(false); 767 messageText.addHyperlinkListener(this); 768 769 // JLabel message = new JLabel(labelText, JLabel.CENTER); 770 JOptionPane.showMessageDialog(null, 771 messageText, 772 titleText, 773 JOptionPane.INFORMATION_MESSAGE); 774 } else { 775 if (notifyDialog) { 776 String labelText = "<html>This version (<b>" + thisVersion + "</b>) is up to date</html>"; 777 JLabel message = new JLabel(labelText, JLabel.CENTER); 778 JOptionPane.showMessageDialog(null, 779 message, 780 titleText, 781 JOptionPane.INFORMATION_MESSAGE); 782 } 783 } 784 } 785 786 public void checkForNotice(boolean notifyDialog) { 787 788 // Shortcut this whole process if we are processing offscreen 789 if (getIdv().getArgsManager().getIsOffScreen()) { 790 return; 791 } 792 793 String thisNotice = getNoticeCached().trim(); 794 String thatNotice = getNoticeLatest().trim(); 795 String titleText = "New Notice"; 796 String labelText = thatNotice; 797 798 if (thatNotice.isEmpty()) { 799 setNoticeCached(thatNotice); 800 if (notifyDialog) { 801 titleText = "No Notice"; 802 JLabel message = new JLabel("There is no current notice", JLabel.CENTER); 803 JOptionPane.showMessageDialog(null, message, titleText, 804 JOptionPane.INFORMATION_MESSAGE); 805 } 806 } else if (!thisNotice.equals(thatNotice)) { 807 setNoticeCached(thatNotice); 808 809 JPanel backgroundColorGetterPanel = new JPanel(); 810 JEditorPane messageText = new JEditorPane("text/html", labelText); 811 messageText.setBackground(backgroundColorGetterPanel.getBackground()); 812 messageText.setEditable(false); 813 messageText.addHyperlinkListener(this); 814 JOptionPane.showMessageDialog(null, messageText, titleText, 815 JOptionPane.INFORMATION_MESSAGE); 816 } else { 817 if (notifyDialog) { 818 titleText = "Previous Notice"; 819 JPanel bgPanel = new JPanel(); 820 JEditorPane messageText = 821 new JEditorPane("text/html", labelText); 822 messageText.setBackground(bgPanel.getBackground()); 823 messageText.setEditable(false); 824 messageText.addHyperlinkListener(this); 825 JOptionPane.showMessageDialog(null, messageText, titleText, 826 JOptionPane.INFORMATION_MESSAGE); 827 } 828 } 829 } 830 831 /** 832 * Debug a McIDAS-V {@literal "system notice"} before sending it to all 833 * users! 834 * 835 * @param noticeContents Contents of the notice. 836 * @param notifyDialog if {@code true}, show notice even if already seen. 837 * @param disableCache Whether or not {@code noticeContents} will be cached. 838 */ 839 public void debugNotice(String noticeContents, boolean notifyDialog, 840 boolean disableCache) 841 { 842 // Shortcut this whole process if we are processing offscreen 843 if (getIdv().getArgsManager().getIsOffScreen()) { 844 return; 845 } 846 847 String thisNotice; 848 thisNotice = disableCache ? "" : getNoticeCached().trim(); 849 String thatNotice = noticeContents.trim(); 850 String labelText = thatNotice; 851 852 if (thatNotice.isEmpty()) { 853 if (!disableCache) { 854 setNoticeCached(thatNotice); 855 } 856 if (notifyDialog) { 857 String titleText = "No Notice"; 858 JLabel message = 859 new JLabel("There is no current notice", JLabel.CENTER); 860 JOptionPane.showMessageDialog(null, message, titleText, 861 JOptionPane.INFORMATION_MESSAGE); 862 } 863 } else if (!thisNotice.equals(thatNotice)) { 864 if (!disableCache) { 865 setNoticeCached(thatNotice); 866 } 867 String titleText = "New Notice"; 868 JPanel backgroundColorGetterPanel = new JPanel(); 869 JEditorPane messageText = new JEditorPane("text/html", labelText); 870 messageText.setBackground(backgroundColorGetterPanel.getBackground()); 871 messageText.setEditable(false); 872 messageText.addHyperlinkListener(this); 873 JOptionPane.showMessageDialog(null, messageText, titleText, 874 JOptionPane.INFORMATION_MESSAGE); 875 } else { 876 if (notifyDialog) { 877 String titleText = "Previous Notice"; 878 JPanel bgPanel = new JPanel(); 879 JEditorPane messageText = 880 new JEditorPane("text/html", labelText); 881 messageText.setBackground(bgPanel.getBackground()); 882 messageText.setEditable(false); 883 messageText.addHyperlinkListener(this); 884 JOptionPane.showMessageDialog(null, messageText, titleText, 885 JOptionPane.INFORMATION_MESSAGE); 886 } 887 } 888 } 889 890 private String getNoticePath() { 891 return StartupManager.getInstance().getPlatform().getUserFile("notice.txt"); 892 } 893 894 private String getNoticeCached() { 895 StringBuilder notice = new StringBuilder(1024); 896 try{ 897 FileReader fstream = new FileReader(getNoticePath()); 898 BufferedReader in = new BufferedReader(fstream); 899 String line; 900 while ((line = in.readLine()) != null) { 901 notice.append(line).append('\n'); 902 } 903 in.close(); 904 } catch (Exception e) { 905 logger.warn("Could not get cached notice", e); 906 } 907 return notice.toString(); 908 } 909 910 private void setNoticeCached(String notice) { 911 try { 912 FileWriter fstream = new FileWriter(getNoticePath()); 913 BufferedWriter out = new BufferedWriter(fstream); 914 out.write(notice); 915 out.close(); 916 } catch (Exception e) { 917 logger.warn("Could not cache downloaded notice", e); 918 } 919 } 920}