001 /* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2013 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 029 package edu.wisc.ssec.mcidasv; 030 031 import java.awt.event.ActionEvent; 032 import java.io.BufferedReader; 033 import java.io.BufferedWriter; 034 import java.io.FileReader; 035 import java.io.FileWriter; 036 import java.util.Hashtable; 037 import java.util.Map; 038 import java.util.Properties; 039 040 import javax.swing.JEditorPane; 041 import javax.swing.JLabel; 042 import javax.swing.JOptionPane; 043 import javax.swing.JPanel; 044 import javax.swing.event.HyperlinkEvent; 045 import javax.swing.event.HyperlinkListener; 046 047 import ucar.unidata.idv.IdvObjectStore; 048 import ucar.unidata.idv.IntegratedDataViewer; 049 import ucar.unidata.util.IOUtil; 050 import ucar.unidata.util.Misc; 051 import ucar.unidata.util.StringUtil; 052 import edu.wisc.ssec.mcidasv.startupmanager.StartupManager; 053 import edu.wisc.ssec.mcidasv.util.SystemState; 054 055 public class StateManager extends ucar.unidata.idv.StateManager implements Constants, HyperlinkListener { 056 057 /** Lazily-loaded VisAD build date. */ 058 private String visadDate; 059 060 /** Lazily-loaded VisAD SVN revision number. */ 061 private String visadVersion; 062 063 private String version; 064 private String versionAbout; 065 066 public StateManager(IntegratedDataViewer idv) { 067 super(idv); 068 } 069 070 /** 071 * Override to set the right user directory 072 */ 073 protected IdvObjectStore doMakeObjectStore() { 074 IdvObjectStore store = new IdvObjectStore(getIdv(), 075 getStoreSystemName(), getStoreName(), 076 getIdv().getEncoderForRead(), 077 StartupManager.getInstance().getPlatform().getUserDirectory()); 078 initObjectStore(store); 079 return store; 080 } 081 082 /** 083 * Handle a change to a link 084 * 085 * @param e the link's event 086 */ 087 public void hyperlinkUpdate(HyperlinkEvent e) { 088 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { 089 if (e.getURL() == null) { 090 click(e.getDescription()); 091 } else { 092 click(e.getURL().toString()); 093 } 094 } 095 } 096 097 /** 098 * Handle a click on a link 099 * 100 * @param url the link definition 101 */ 102 public void click(String url) { 103 getIdv().actionPerformed(new ActionEvent(this, 0, url)); 104 } 105 106 public String getOSName() { 107 String os = System.getProperty("os.name"); 108 os = os.replaceAll(" ", "_"); 109 return os; 110 } 111 112 public String getMcIdasVersionAbout() { 113 getMcIdasVersion(); 114 115 versionAbout = IOUtil.readContents((String) getProperty(Constants.PROP_ABOUTTEXT), ""); 116 versionAbout = StringUtil.replace(versionAbout, MACRO_VERSION, version); 117 Properties props = Misc.readProperties( 118 (String) getProperty(Constants.PROP_VERSIONFILE), 119 null, 120 getClass() 121 ); 122 123 String value = getIdvVersion(); 124 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_IDV_VERSION, value); 125 value = props.getProperty(PROP_COPYRIGHT_YEAR, ""); 126 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_COPYRIGHT_YEAR, value); 127 value = props.getProperty(PROP_BUILD_DATE, "Unknown"); 128 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_BUILDDATE, value); 129 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_VISAD_VERSION, getVisadVersion()); 130 131 return versionAbout; 132 } 133 134 public String getMcIdasVersion() { 135 if (version != null) { 136 return version; 137 } 138 139 Properties props = new Properties(); 140 props = Misc.readProperties((String) getProperty(Constants.PROP_VERSIONFILE), null, getClass()); 141 String maj = props.getProperty(PROP_VERSION_MAJOR, "0"); 142 String min = props.getProperty(PROP_VERSION_MINOR, "0"); 143 String rel = props.getProperty(PROP_VERSION_RELEASE, ""); 144 145 version = maj.concat(".").concat(min).concat(rel); 146 147 return version; 148 } 149 150 /** 151 * Returns the current Jython version. 152 * 153 * @return Jython's version information. 154 */ 155 @Override public String getJythonVersion() { 156 return org.python.Version.PY_VERSION; 157 } 158 159 /** 160 * Get a property 161 * 162 * @param name name of the property 163 * 164 * @return the property or null 165 */ 166 @Override public Object getProperty(final String name) { 167 Object value = null; 168 if (McIDASV.isMac()) { 169 value = getProperties().get("mac."+name); 170 } 171 if (value == null) { 172 value = getProperties().get(name); 173 } 174 if (value == null) { 175 String fixedName = StateManager.fixIds(name); 176 if (!name.equals(fixedName)) { 177 return getProperties().get(fixedName); 178 } 179 } 180 return value; 181 } 182 183 /** 184 * Returns information about the current version of McIDAS-V and the IDV, 185 * along with their respective build dates. 186 * 187 * @return Hashtable containing versioning information. 188 */ 189 public Hashtable<String, String> getVersionInfo() { 190 Properties props = new Properties(); 191 props = Misc.readProperties((String) getProperty(Constants.PROP_VERSIONFILE), null, getClass()); 192 193 String mcvBuild = props.getProperty(PROP_BUILD_DATE, "Unknown"); 194 195 Hashtable<String, String> table = new Hashtable<String, String>(); 196 table.put("mcv.version.general", getMcIdasVersion()); 197 table.put("mcv.version.build", mcvBuild); 198 table.put("idv.version.general", getVersion()); 199 table.put("idv.version.build", getBuildDate()); 200 table.put("visad.version.general", getVisadVersion()); 201 table.put("visad.version.build", getVisadDate()); 202 return table; 203 } 204 205 /** 206 * Return the timestamp from visad.jar was created. 207 * 208 * @return {@code String} representation of the creation timestamp. Likely to change formatting over time. 209 */ 210 public String getVisadDate() { 211 if (visadDate == null) { 212 Map<String, String> props = SystemState.queryVisadBuildProperties(); 213 visadDate = props.get(Constants.PROP_VISAD_DATE); 214 visadVersion = props.get(Constants.PROP_VISAD_REVISION); 215 } 216 return visadDate; 217 } 218 219 /** 220 * Return the {@literal "version"} of VisAD. 221 * 222 * @return Currently returns whatever the SVN revision number was when 223 * visad.jar was built. 224 */ 225 public String getVisadVersion() { 226 if (visadVersion== null) { 227 Map<String, String> props = SystemState.queryVisadBuildProperties(); 228 visadDate = props.get(Constants.PROP_VISAD_DATE); 229 visadVersion = props.get(Constants.PROP_VISAD_REVISION); 230 } 231 return visadVersion; 232 } 233 234 public String getIdvVersion() { 235 return getVersion(); 236 } 237 238 /** 239 * Overridden to set default of McIDAS-V 240 */ 241 public String getStoreSystemName() { 242 return StartupManager.getInstance().getPlatform().getUserDirectory(); 243 } 244 245 /** 246 * Overridden to get dir of the unnecessary second level directory. 247 * 248 * @see ucar.unidata.idv.StateManager#getStoreName() 249 */ 250 public String getStoreName() { 251 return ""; 252 } 253 254 /** 255 * Connect to McIDAS website and look for latest stable version 256 */ 257 public String getMcIdasVersionStable() { 258 String offscreen = "0"; 259 if (super.getIdv().getArgsManager().getIsOffScreen()) { 260 offscreen = "1"; 261 } 262 263 String version = ""; 264 try { 265 version = IOUtil.readContents(Constants.HOMEPAGE_URL+"/"+Constants.VERSION_HANDLER_URL+"?v="+getMcIdasVersion()+"&os="+getOSName()+"&off="+offscreen, ""); 266 } catch (Exception e) {} 267 return version.trim(); 268 } 269 270 /** 271 * Connect to McIDAS website and look for latest prerelease version 272 */ 273 public String getMcIdasVersionPrerelease() { 274 String version = ""; 275 try { 276 String htmlList = IOUtil.readContents(Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL, ""); 277 String lines[] = htmlList.split("\n"); 278 for (int i=0; i<lines.length; i++) { 279 String line = lines[i].trim(); 280 if (line.matches(".*McIDAS-V_\\d+\\.\\d+.*")) { 281 line = line.substring(line.indexOf("McIDAS-V_")+9); 282 String aVersion = line.substring(0, line.indexOf("_")); 283 if (version == "") { 284 version = aVersion; 285 } 286 else { 287 int comp = compareVersions(version, aVersion); 288 if (comp > 0) { 289 version = aVersion; 290 } 291 } 292 } 293 } 294 } catch (Exception e) {} 295 return version.trim(); 296 } 297 298 /** 299 * Connect to McIDAS website and look for latest notice 300 */ 301 public String getNoticeLatest() { 302 String notice = ""; 303 try { 304 notice = IOUtil.readContents(Constants.HOMEPAGE_URL+"/"+Constants.NOTICE_URL+"?requesting="+getMcIdasVersion()+"&os="+getOSName(), ""); 305 } catch (Exception e) {} 306 if (notice.indexOf("<notice>")<0) notice=""; 307 notice = notice.replaceAll("<[/?]notice>",""); 308 return notice.trim(); 309 } 310 311 /** 312 * Compare version strings 313 * 0: equal 314 * <0: this version is greater 315 * >0: that version is greater 316 */ 317 private int compareVersions(String thisVersion, String thatVersion) { 318 int thisInt = versionToInteger(thisVersion); 319 int thatInt = versionToInteger(thatVersion); 320 return (thatInt - thisInt); 321 } 322 323 /** 324 * Turn version strings of the form #.#(a#) 325 * where # is one or two digits, a is one of alpha or beta, and () is optional 326 * Into an integer... (empty) > beta > alpha 327 */ 328 private int versionToInteger(String version) { 329 int value = 0; 330 int p; 331 String part; 332 Character one = null; 333 334 try { 335 336 // Major version 337 p = version.indexOf('.'); 338 if (p > 0) { 339 part = version.substring(0,p); 340 value += Integer.parseInt(part) * 1000000; 341 version = version.substring(p+1); 342 } 343 344 // Minor version 345 int minor = 0; 346 int i=0; 347 for (i=0; i<2 && i<version.length(); i++) { 348 one = version.charAt(i); 349 if (Character.isDigit(one)) { 350 if (i>0) minor *= 10; 351 minor += Character.digit(one, 10) * 10000; 352 } 353 else { 354 break; 355 } 356 } 357 value += minor; 358 if (one!=null) version = version.substring(i); 359 360 // Alpha/beta/update/release status 361 if (version.length() == 0) value += 300; 362 else if (version.charAt(0) == 'b') value += 200; 363 else if (version.charAt(0) == 'a') value += 100; 364 else if (version.charAt(0) == 'u') value += 400; 365 else if (version.charAt(0) == 'r') value += 400; 366 for (i=0; i<version.length(); i++) { 367 one = version.charAt(i); 368 if (Character.isDigit(one)) break; 369 } 370 if (one!=null) version = version.substring(i); 371 372 // Alpha/beta version 373 if (version.length() > 0) 374 value += Integer.parseInt(version); 375 376 } catch (Exception e) {} 377 378 return value; 379 } 380 381 public boolean getIsPrerelease() { 382 boolean isPrerelease = false; 383 String version = getMcIdasVersion(); 384 if (version.indexOf("a") >= 0 || version.indexOf("b") >= 0) { 385 isPrerelease = true; 386 } 387 return isPrerelease; 388 } 389 390 public void checkForNewerVersion(boolean notifyDialog) { 391 checkForNewerVersionStable(notifyDialog); 392 if (getStore().get(Constants.PREF_PRERELEASE_CHECK, getIsPrerelease())) { 393 checkForNewerVersionPrerelease(notifyDialog); 394 } 395 } 396 397 public void checkForNewerVersionStable(boolean notifyDialog) { 398 399 /** Get the stable version from the website (for statistics recording) */ 400 String thatVersion = getMcIdasVersionStable(); 401 402 /** Shortcut the rest of the process if we are processing offscreen */ 403 if (super.getIdv().getArgsManager().getIsOffScreen()) { 404 return; 405 } 406 407 String thisVersion = getMcIdasVersion(); 408 String titleText = "Version Check"; 409 410 if (thisVersion.equals("") || thatVersion.equals("")) { 411 if (notifyDialog) { 412 JOptionPane.showMessageDialog(null, "Version check failed", titleText, 413 JOptionPane.WARNING_MESSAGE); 414 } 415 } 416 else if (compareVersions(thisVersion, thatVersion) > 0) { 417 String labelText = "<html>Version <b>" + thatVersion + "</b> is available<br><br>"; 418 labelText += "Visit <a href=\"" + Constants.HOMEPAGE_URL + "\">"; 419 labelText += Constants.HOMEPAGE_URL + "</a> to download</html>"; 420 421 JPanel backgroundColorGetterPanel = new JPanel(); 422 JEditorPane messageText = new JEditorPane("text/html", labelText); 423 messageText.setBackground(backgroundColorGetterPanel.getBackground()); 424 messageText.setEditable(false); 425 messageText.addHyperlinkListener(this); 426 427 // JLabel message = new JLabel(labelText, JLabel.CENTER); 428 JOptionPane.showMessageDialog(null, messageText, titleText, 429 JOptionPane.INFORMATION_MESSAGE); 430 } 431 else { 432 if (notifyDialog) { 433 String labelText = "<html>This version (<b>" + thisVersion + "</b>) is up to date</html>"; 434 JLabel message = new JLabel(labelText, JLabel.CENTER); 435 JOptionPane.showMessageDialog(null, message, titleText, 436 JOptionPane.INFORMATION_MESSAGE); 437 } 438 } 439 440 } 441 442 public void checkForNewerVersionPrerelease(boolean notifyDialog) { 443 444 /** Shortcut the rest of the process if we are processing offscreen */ 445 if (super.getIdv().getArgsManager().getIsOffScreen()) { 446 return; 447 } 448 449 String thisVersion = getMcIdasVersion(); 450 String thatVersion = getMcIdasVersionPrerelease(); 451 String titleText = "Prerelease Check"; 452 453 if (thisVersion.equals("") || thatVersion.equals("")) { 454 if (notifyDialog) { 455 JOptionPane.showMessageDialog(null, "No prerelease version available", titleText, 456 JOptionPane.WARNING_MESSAGE); 457 } 458 } 459 else if (compareVersions(thisVersion, thatVersion) > 0) { 460 String labelText = "<html>Prerelease <b>" + thatVersion + "</b> is available<br><br>"; 461 labelText += "Visit <a href=\"" + Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL + "\">"; 462 labelText += Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL + "</a> to download</html>"; 463 464 JPanel backgroundColorGetterPanel = new JPanel(); 465 JEditorPane messageText = new JEditorPane("text/html", labelText); 466 messageText.setBackground(backgroundColorGetterPanel.getBackground()); 467 messageText.setEditable(false); 468 messageText.addHyperlinkListener(this); 469 470 // JLabel message = new JLabel(labelText, JLabel.CENTER); 471 JOptionPane.showMessageDialog(null, messageText, titleText, 472 JOptionPane.INFORMATION_MESSAGE); 473 } 474 else { 475 if (notifyDialog) { 476 String labelText = "<html>This version (<b>" + thisVersion + "</b>) is up to date</html>"; 477 JLabel message = new JLabel(labelText, JLabel.CENTER); 478 JOptionPane.showMessageDialog(null, message, titleText, 479 JOptionPane.INFORMATION_MESSAGE); 480 } 481 } 482 483 } 484 485 public void checkForNotice(boolean notifyDialog) { 486 487 /** Shortcut this whole process if we are processing offscreen */ 488 if (super.getIdv().getArgsManager().getIsOffScreen()) 489 return; 490 491 String thisNotice = getNoticeCached().trim(); 492 String thatNotice = getNoticeLatest().trim(); 493 String titleText = "New Notice"; 494 String labelText = thatNotice; 495 496 if (thatNotice.equals("")) { 497 setNoticeCached(thatNotice); 498 if (notifyDialog) { 499 titleText = "No Notice"; 500 JLabel message = new JLabel("There is no current notice", JLabel.CENTER); 501 JOptionPane.showMessageDialog(null, message, titleText, 502 JOptionPane.INFORMATION_MESSAGE); 503 } 504 return; 505 } 506 else if (!thisNotice.equals(thatNotice)) { 507 setNoticeCached(thatNotice); 508 509 JPanel backgroundColorGetterPanel = new JPanel(); 510 JEditorPane messageText = new JEditorPane("text/html", labelText); 511 messageText.setBackground(backgroundColorGetterPanel.getBackground()); 512 messageText.setEditable(false); 513 messageText.addHyperlinkListener(this); 514 515 // JLabel message = new JLabel(labelText, JLabel.CENTER); 516 JOptionPane.showMessageDialog(null, messageText, titleText, 517 JOptionPane.INFORMATION_MESSAGE); 518 } 519 else { 520 if (notifyDialog) { 521 titleText = "Previous Notice"; 522 JLabel message = new JLabel(labelText, JLabel.CENTER); 523 JOptionPane.showMessageDialog(null, message, titleText, 524 JOptionPane.INFORMATION_MESSAGE); 525 } 526 } 527 528 } 529 530 private String getNoticePath() { 531 return StartupManager.getInstance().getPlatform().getUserFile("notice.txt"); 532 } 533 534 private String getNoticeCached() { 535 String notice = ""; 536 try{ 537 FileReader fstream = new FileReader(getNoticePath()); 538 BufferedReader in = new BufferedReader(fstream); 539 String line; 540 while ((line = in.readLine()) != null) { 541 notice += line + '\n'; 542 } 543 in.close(); 544 } catch (Exception e){ 545 System.err.println("Error: " + e.getMessage()); 546 } 547 return notice; 548 } 549 550 private void setNoticeCached(String notice) { 551 try{ 552 FileWriter fstream = new FileWriter(getNoticePath()); 553 BufferedWriter out = new BufferedWriter(fstream); 554 out.write(notice); 555 out.close(); 556 } catch (Exception e){ 557 System.err.println("Error: " + e.getMessage()); 558 } 559 } 560 561 }