001 /*
002 * $Id: StateManager.java,v 1.30 2012/04/30 15:57:35 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2012
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 *
012 * All Rights Reserved
013 *
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.
016 *
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 *
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
025 * GNU Lesser Public License for more details.
026 *
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program. If not, see http://www.gnu.org/licenses.
029 */
030
031 package edu.wisc.ssec.mcidasv;
032
033 import java.awt.event.ActionEvent;
034 import java.io.BufferedReader;
035 import java.io.BufferedWriter;
036 import java.io.FileReader;
037 import java.io.FileWriter;
038 import java.util.Hashtable;
039 import java.util.Properties;
040
041 import javax.swing.JEditorPane;
042 import javax.swing.JLabel;
043 import javax.swing.JOptionPane;
044 import javax.swing.JPanel;
045 import javax.swing.event.HyperlinkEvent;
046 import javax.swing.event.HyperlinkListener;
047
048 import ucar.unidata.idv.IdvObjectStore;
049 import ucar.unidata.idv.IntegratedDataViewer;
050 import ucar.unidata.util.IOUtil;
051 import ucar.unidata.util.Misc;
052 import ucar.unidata.util.StringUtil;
053 import edu.wisc.ssec.mcidasv.startupmanager.StartupManager;
054
055 public class StateManager extends ucar.unidata.idv.StateManager implements Constants, HyperlinkListener {
056
057 private String version;
058 private String versionAbout;
059
060 public StateManager(IntegratedDataViewer idv) {
061 super(idv);
062 }
063
064 /**
065 * Override to set the right user directory
066 */
067 protected IdvObjectStore doMakeObjectStore() {
068 IdvObjectStore store = new IdvObjectStore(getIdv(),
069 getStoreSystemName(), getStoreName(),
070 getIdv().getEncoderForRead(),
071 StartupManager.INSTANCE.getPlatform().getUserDirectory());
072 initObjectStore(store);
073 return store;
074 }
075
076 /**
077 * Handle a change to a link
078 *
079 * @param e the link's event
080 */
081 public void hyperlinkUpdate(HyperlinkEvent e) {
082 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
083 if (e.getURL() == null) {
084 click(e.getDescription());
085 } else {
086 click(e.getURL().toString());
087 }
088 }
089 }
090
091 /**
092 * Handle a click on a link
093 *
094 * @param url the link definition
095 */
096 public void click(String url) {
097 getIdv().actionPerformed(new ActionEvent(this, 0, url));
098 }
099
100 public String getOSName() {
101 String os = System.getProperty("os.name");
102 os = os.replaceAll(" ", "_");
103 return os;
104 }
105
106 public String getMcIdasVersionAbout() {
107 getMcIdasVersion();
108
109 versionAbout = IOUtil.readContents((String) getProperty(Constants.PROP_ABOUTTEXT), "");
110 versionAbout = StringUtil.replace(versionAbout, MACRO_VERSION, version);
111 Properties props = Misc.readProperties(
112 (String) getProperty(Constants.PROP_VERSIONFILE),
113 null,
114 getClass()
115 );
116
117 String value = getIdvVersion();
118 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_IDV_VERSION, value);
119 value = props.getProperty(PROP_COPYRIGHT_YEAR, "");
120 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_COPYRIGHT_YEAR, value);
121 value = props.getProperty(PROP_BUILD_DATE, "Unknown");
122 versionAbout = StringUtil.replace(versionAbout, Constants.MACRO_BUILDDATE, value);
123
124 return versionAbout;
125 }
126
127 public String getMcIdasVersion() {
128 if (version != null) {
129 return version;
130 }
131
132 Properties props = new Properties();
133 props = Misc.readProperties((String) getProperty(Constants.PROP_VERSIONFILE), null, getClass());
134 String maj = props.getProperty(PROP_VERSION_MAJOR, "0");
135 String min = props.getProperty(PROP_VERSION_MINOR, "0");
136 String rel = props.getProperty(PROP_VERSION_RELEASE, "");
137
138 version = maj.concat(".").concat(min).concat(rel);
139
140 return version;
141 }
142
143 /**
144 * Get a property
145 *
146 * @param name name of the property
147 *
148 * @return the property or null
149 */
150 @Override public Object getProperty(final String name) {
151 Object value = null;
152 if (McIDASV.isMac())
153 value = getProperties().get("mac."+name);
154
155 if (value == null)
156 value = getProperties().get(name);
157
158 if (value == null) {
159 String fixedName = StateManager.fixIds(name);
160 if (!name.equals(fixedName))
161 return getProperties().get(fixedName);
162 }
163 return value;
164 }
165
166 /**
167 * Returns information about the current version of McIDAS-V and the IDV,
168 * along with their respective build dates.
169 *
170 * @return Hashtable containing versioning information.
171 */
172 public Hashtable<String, String> getVersionInfo() {
173 Properties props = new Properties();
174 props = Misc.readProperties((String) getProperty(Constants.PROP_VERSIONFILE), null, getClass());
175
176 String mcvBuild = props.getProperty(PROP_BUILD_DATE, "Unknown");
177
178 Hashtable<String, String> table = new Hashtable<String, String>();
179 table.put("mcv.version.general", getMcIdasVersion());
180 table.put("mcv.version.build", mcvBuild);
181 table.put("idv.version.general", getVersion());
182 table.put("idv.version.build", getBuildDate());
183 return table;
184 }
185
186 public String getIdvVersion() {
187 return getVersion();
188 }
189
190 /**
191 * Overridden to set default of McIDAS-V
192 */
193 public String getStoreSystemName() {
194 return StartupManager.INSTANCE.getPlatform().getUserDirectory();
195 }
196
197 /**
198 * Overridden to get dir of the unnecessary second level directory.
199 *
200 * @see ucar.unidata.idv.StateManager#getStoreName()
201 */
202 public String getStoreName() {
203 return "";
204 }
205
206 /**
207 * Connect to McIDAS website and look for latest stable version
208 */
209 public String getMcIdasVersionStable() {
210 String version = "";
211 try {
212 version = IOUtil.readContents(Constants.HOMEPAGE_URL+'/'+Constants.VERSION_URL+"?requesting="+getMcIdasVersion()+"&os="+getOSName(), "");
213 } catch (Exception e) {}
214 return version.trim();
215 }
216
217 /**
218 * Connect to McIDAS website and look for latest prerelease version
219 */
220 public String getMcIdasVersionPrerelease() {
221 String version = "";
222 try {
223 String htmlList = IOUtil.readContents(Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL, "");
224 String lines[] = htmlList.split("\n");
225 for (int i=0; i<lines.length; i++) {
226 String line = lines[i].trim();
227 if (line.matches(".*McIDAS-V_\\d+\\.\\d+.*")) {
228 line = line.substring(line.indexOf("McIDAS-V_")+9);
229 String aVersion = line.substring(0, line.indexOf("_"));
230 if (version == "") {
231 version = aVersion;
232 }
233 else {
234 int comp = compareVersions(version, aVersion);
235 if (comp > 0) {
236 version = aVersion;
237 }
238 }
239 }
240 }
241 } catch (Exception e) {}
242 return version.trim();
243 }
244
245 /**
246 * Connect to McIDAS website and look for latest notice
247 */
248 public String getNoticeLatest() {
249 String notice = "";
250 try {
251 notice = IOUtil.readContents(Constants.HOMEPAGE_URL+"/"+Constants.NOTICE_URL+"?requesting="+getMcIdasVersion()+"&os="+getOSName(), "");
252 } catch (Exception e) {}
253 if (notice.indexOf("<notice>")<0) notice="";
254 notice = notice.replaceAll("<[/?]notice>","");
255 return notice.trim();
256 }
257
258 /**
259 * Compare version strings
260 * 0: equal
261 * <0: this version is greater
262 * >0: that version is greater
263 */
264 private int compareVersions(String thisVersion, String thatVersion) {
265 int thisInt = versionToInteger(thisVersion);
266 int thatInt = versionToInteger(thatVersion);
267 return (thatInt - thisInt);
268 }
269
270 /**
271 * Turn version strings of the form #.#(a#)
272 * where # is one or two digits, a is one of alpha or beta, and () is optional
273 * Into an integer... (empty) > beta > alpha
274 */
275 private int versionToInteger(String version) {
276 int value = 0;
277 int p;
278 String part;
279 Character one = null;
280
281 try {
282
283 // Major version
284 p = version.indexOf('.');
285 if (p > 0) {
286 part = version.substring(0,p);
287 value += Integer.parseInt(part) * 1000000;
288 version = version.substring(p+1);
289 }
290
291 // Minor version
292 int minor = 0;
293 int i=0;
294 for (i=0; i<2 && i<version.length(); i++) {
295 one = version.charAt(i);
296 if (Character.isDigit(one)) {
297 if (i>0) minor *= 10;
298 minor += Character.digit(one, 10) * 10000;
299 }
300 else {
301 break;
302 }
303 }
304 value += minor;
305 if (one!=null) version = version.substring(i);
306
307 // Alpha/beta/update/release status
308 if (version.length() == 0) value += 300;
309 else if (version.charAt(0) == 'b') value += 200;
310 else if (version.charAt(0) == 'a') value += 100;
311 else if (version.charAt(0) == 'u') value += 400;
312 else if (version.charAt(0) == 'r') value += 400;
313 for (i=0; i<version.length(); i++) {
314 one = version.charAt(i);
315 if (Character.isDigit(one)) break;
316 }
317 if (one!=null) version = version.substring(i);
318
319 // Alpha/beta version
320 if (version.length() > 0)
321 value += Integer.parseInt(version);
322
323 } catch (Exception e) {}
324
325 return value;
326 }
327
328 public boolean getIsPrerelease() {
329 boolean isPrerelease = false;
330 String version = getMcIdasVersion();
331 if (version.indexOf("a") >= 0 || version.indexOf("b") >= 0) {
332 isPrerelease = true;
333 }
334 return isPrerelease;
335 }
336
337 public void checkForNewerVersion(boolean notifyDialog) {
338 checkForNewerVersionStable(notifyDialog);
339 if (getStore().get(Constants.PREF_PRERELEASE_CHECK, getIsPrerelease())) {
340 checkForNewerVersionPrerelease(notifyDialog);
341 }
342 }
343
344 public void checkForNewerVersionStable(boolean notifyDialog) {
345
346 /** Shortcut this whole process if we are processing offscreen */
347 if (super.getIdv().getArgsManager().getIsOffScreen())
348 return;
349
350 String thisVersion = getMcIdasVersion();
351 String thatVersion = getMcIdasVersionStable();
352 String titleText = "Version Check";
353
354 if (thisVersion.equals("") || thatVersion.equals("")) {
355 if (notifyDialog) {
356 JOptionPane.showMessageDialog(null, "Version check failed", titleText,
357 JOptionPane.WARNING_MESSAGE);
358 }
359 }
360 else if (compareVersions(thisVersion, thatVersion) > 0) {
361 String labelText = "<html>Version <b>" + thatVersion + "</b> is available<br><br>";
362 labelText += "Visit <a href=\"" + Constants.HOMEPAGE_URL + "\">";
363 labelText += Constants.HOMEPAGE_URL + "</a> to download</html>";
364
365 JPanel backgroundColorGetterPanel = new JPanel();
366 JEditorPane messageText = new JEditorPane("text/html", labelText);
367 messageText.setBackground(backgroundColorGetterPanel.getBackground());
368 messageText.setEditable(false);
369 messageText.addHyperlinkListener(this);
370
371 // JLabel message = new JLabel(labelText, JLabel.CENTER);
372 JOptionPane.showMessageDialog(null, messageText, titleText,
373 JOptionPane.INFORMATION_MESSAGE);
374 }
375 else {
376 if (notifyDialog) {
377 String labelText = "<html>This version (<b>" + thisVersion + "</b>) is up to date</html>";
378 JLabel message = new JLabel(labelText, JLabel.CENTER);
379 JOptionPane.showMessageDialog(null, message, titleText,
380 JOptionPane.INFORMATION_MESSAGE);
381 }
382 }
383
384 }
385
386 public void checkForNewerVersionPrerelease(boolean notifyDialog) {
387
388 /** Shortcut this whole process if we are processing offscreen */
389 if (super.getIdv().getArgsManager().getIsOffScreen())
390 return;
391
392 String thisVersion = getMcIdasVersion();
393 String thatVersion = getMcIdasVersionPrerelease();
394 String titleText = "Prerelease Check";
395
396 if (thisVersion.equals("") || thatVersion.equals("")) {
397 if (notifyDialog) {
398 JOptionPane.showMessageDialog(null, "No prerelease version available", titleText,
399 JOptionPane.WARNING_MESSAGE);
400 }
401 }
402 else if (compareVersions(thisVersion, thatVersion) > 0) {
403 String labelText = "<html>Prerelease <b>" + thatVersion + "</b> is available<br><br>";
404 labelText += "Visit <a href=\"" + Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL + "\">";
405 labelText += Constants.HOMEPAGE_URL+'/'+Constants.PRERELEASE_URL + "</a> to download</html>";
406
407 JPanel backgroundColorGetterPanel = new JPanel();
408 JEditorPane messageText = new JEditorPane("text/html", labelText);
409 messageText.setBackground(backgroundColorGetterPanel.getBackground());
410 messageText.setEditable(false);
411 messageText.addHyperlinkListener(this);
412
413 // JLabel message = new JLabel(labelText, JLabel.CENTER);
414 JOptionPane.showMessageDialog(null, messageText, titleText,
415 JOptionPane.INFORMATION_MESSAGE);
416 }
417 else {
418 if (notifyDialog) {
419 String labelText = "<html>This version (<b>" + thisVersion + "</b>) is up to date</html>";
420 JLabel message = new JLabel(labelText, JLabel.CENTER);
421 JOptionPane.showMessageDialog(null, message, titleText,
422 JOptionPane.INFORMATION_MESSAGE);
423 }
424 }
425
426 }
427
428 public void checkForNotice(boolean notifyDialog) {
429
430 /** Shortcut this whole process if we are processing offscreen */
431 if (super.getIdv().getArgsManager().getIsOffScreen())
432 return;
433
434 String thisNotice = getNoticeCached().trim();
435 String thatNotice = getNoticeLatest().trim();
436 String titleText = "New Notice";
437 String labelText = thatNotice;
438
439 if (thatNotice.equals("")) {
440 setNoticeCached(thatNotice);
441 if (notifyDialog) {
442 titleText = "No Notice";
443 JLabel message = new JLabel("There is no current notice", JLabel.CENTER);
444 JOptionPane.showMessageDialog(null, message, titleText,
445 JOptionPane.INFORMATION_MESSAGE);
446 }
447 return;
448 }
449 else if (!thisNotice.equals(thatNotice)) {
450 setNoticeCached(thatNotice);
451
452 JPanel backgroundColorGetterPanel = new JPanel();
453 JEditorPane messageText = new JEditorPane("text/html", labelText);
454 messageText.setBackground(backgroundColorGetterPanel.getBackground());
455 messageText.setEditable(false);
456 messageText.addHyperlinkListener(this);
457
458 // JLabel message = new JLabel(labelText, JLabel.CENTER);
459 JOptionPane.showMessageDialog(null, messageText, titleText,
460 JOptionPane.INFORMATION_MESSAGE);
461 }
462 else {
463 if (notifyDialog) {
464 titleText = "Previous Notice";
465 JLabel message = new JLabel(labelText, JLabel.CENTER);
466 JOptionPane.showMessageDialog(null, message, titleText,
467 JOptionPane.INFORMATION_MESSAGE);
468 }
469 }
470
471 }
472
473 private String getNoticePath() {
474 return StartupManager.INSTANCE.getPlatform().getUserFile("notice.txt");
475 }
476
477 private String getNoticeCached() {
478 String notice = "";
479 try{
480 FileReader fstream = new FileReader(getNoticePath());
481 BufferedReader in = new BufferedReader(fstream);
482 String line;
483 while ((line = in.readLine()) != null) {
484 notice += line + '\n';
485 }
486 in.close();
487 } catch (Exception e){
488 System.err.println("Error: " + e.getMessage());
489 }
490 return notice;
491 }
492
493 private void setNoticeCached(String notice) {
494 try{
495 FileWriter fstream = new FileWriter(getNoticePath());
496 BufferedWriter out = new BufferedWriter(fstream);
497 out.write(notice);
498 out.close();
499 } catch (Exception e){
500 System.err.println("Error: " + e.getMessage());
501 }
502 }
503
504 }