/* * [AppToWatch.java] * * Summary: class to hold the table data about an Application. * * Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 3.8 2009-03-31 change order of fields in defaults.csv. */ package com.mindprod.vercheck; import com.mindprod.common18.BigDate; import javax.swing.Icon; import java.io.Serializable; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Date; import static com.mindprod.vercheck.AppState.*; import static java.lang.System.*; /** * class to hold the table data about an Application. * * @author Roedy Green, Canadian Mind Products * @version 3.8 2009-03-31 change order of fields in defaults.csv. * @since 2009 */ public class AppToWatch implements Serializable, Comparable { /** * Defining a layout version for a class. */ static final long serialVersionUID = 9L; /** * today, using tho local TimeZone to figure out when midnight is. */ static final BigDate localToday = BigDate.localToday(); /** * how many days we keep status before before we consider them stale, 0= always stale 1= yesterday is stale */ private static final int STALE_DAYS = 2; /** * mask for: Tuesday 2009-01-20 12:00 AM EST : Eastern Standard Time * define an elaborate date format */ private static final SimpleDateFormat SDF = new SimpleDateFormat( "EEEE yyyy-MM-dd hh:mm aa zz : zzzzzz" ); /** * date we last checked the statuses by probing websites, common to all apps. */ static BigDate datePartiallyChecked; /** * date/time timestamp internal data last changed, by probe or keying, common to all apps. */ static long modifiedTimestamp; /** * date/time we last checked the statuses by probing websites, UTC, common to all apps. */ static long timestampFullyChecked; /** * date/time we last checked the statuses by probing some websites, UTC, common to all apps. */ static long timestampPartiallyChecked; /** * where to get info on how to download. Not displayed in VerCheck. Exported. */ private final String downloadInstructionsURL; /** * has this appName changed recently, and other states */ private AppState state; /** * date this version was released, null if unknown */ private BigDate dateReleased; /** * name of the app */ private String appName; /** * what this app does, one-line description */ private String description; /** * String you will find in the web page if the version has not changed. */ private String marker; /** * current version of the appName */ private String version; /** * url of the web page to check for a version change. */ private URL versionURL; /** * does this site require Server Name Identification */ private boolean sni; /** * no-arg constructor */ public AppToWatch() { this.state = AppState.EMPTY; this.version = ""; this.description = ""; this.downloadInstructionsURL = ""; this.versionURL = null; this.marker = ""; this.dateReleased = null; } /** * constructor * * @param appName name of the appName * @param version version of the appName * @param description what the app is for * @param downloadInstructionsURL where to get info on downloading. * @param sni true if you need to enable Server Name Identification for this site. * @param versionURL url to check the appName * @param marker string expected to find at url if version has not changed. * @param dateReleased date this version was released */ public AppToWatch( final String appName, final String version, final String description, final String downloadInstructionsURL, final boolean sni, final String versionURL, final String marker, final BigDate dateReleased ) { this.state = AppState.UNTESTED; this.appName = appName; this.version = version; this.description = description; this.downloadInstructionsURL = downloadInstructionsURL; this.sni = sni; setVersionURL( versionURL ); this.marker = marker; this.dateReleased = dateReleased; } /** * get date/time last probed * * @return date/time */ static String getTimestampCheckedString() { // user default TZ return ( timestampPartiallyChecked == Long.MIN_VALUE ) ? "unknown" : SDF.format( new Date( timestampPartiallyChecked ) ); } /** * adjust state based on current date and dateReleased */ void normaliseState() { switch ( state ) { case EMPTY: case UNTESTED: case CHECKING: case RECENTLY_CHANGED: case NO_CONNECTION: case INVALID: return; case UNCHANGED_RELEASED_IN_LAST_WEEK: case UNCHANGED_RELEASED_IN_LAST_MONTH: case UNCHANGED_RELEASED_MORE_THAN_A_MONTH_AGO: case UNCHANGED_RELEASED_MORE_THAN_A_YEAR_AGO: if ( datePartiallyChecked == null || datePartiallyChecked.isNull() || localToday.getOrdinal() >= datePartiallyChecked.getOrdinal() + STALE_DAYS ) { state = UNTESTED; } else if ( dateReleased == null || dateReleased.isNull() ) { state = UNCHANGED_RELEASED_MORE_THAN_A_YEAR_AGO; } else { final int ageInDays = Math.max( 0, localToday.getOrdinal() - dateReleased.getOrdinal() ); if ( ageInDays <= 7 ) { state = UNCHANGED_RELEASED_IN_LAST_WEEK; } else if ( ageInDays <= 30 ) { state = UNCHANGED_RELEASED_IN_LAST_MONTH; } else if ( ageInDays <= 365 ) { state = UNCHANGED_RELEASED_MORE_THAN_A_MONTH_AGO; } else { state = UNCHANGED_RELEASED_MORE_THAN_A_YEAR_AGO; } } break; default: throw new IllegalArgumentException( "Program bug: illegal AppState" ); } } /** * set url to check the appName * * @param url url to check the appName */ private void setVersionURL( String url ) { try { this.versionURL = new URL( url ); } catch ( MalformedURLException e ) { err.println( "Malformed Url: " + url ); this.versionURL = null; } } public int compareTo( AppToWatch o ) { return this.appName.compareToIgnoreCase( o.appName ); } /** * get name of the appName * * @return name of the appName */ public String getAppName() { return appName; } /** * set name of the appName * * @param appName name of the appName */ public void setAppName( String appName ) { if ( appName.equals( this.appName ) ) { return; } this.appName = appName; setState( AppState.UNTESTED ); } public BigDate getDateReleased() { return dateReleased; } public void setDateReleased( BigDate dateReleased ) { if ( dateReleased != null ) { final int ordinalToday = localToday.getOrdinal(); final int ordinalReleased = dateReleased.getOrdinal(); if ( ordinalReleased > ordinalToday ) { Audio.FUTURE_DATE.play(); return; } } // catches null == null if ( dateReleased == this.dateReleased || dateReleased.equals( this.dateReleased ) ) { return; } this.dateReleased = dateReleased; setState( AppState.UNTESTED ); } /** * get description of what app is for * * @return description of this app, what it is for. */ public String getDescription() { return description; } /** * set the description of what app does * * @param description what the app does */ public void setDescription( String description ) { this.description = description; // does not affect state } /** * get URL where can find out about how to download, usually relative URL on mindprod.com, not * intended for general use. * Only used to generate HTML with link to where to download. Not used in Applet. Not client settable. * Defined only via defaults.csv. * * @return url for download info * @see #getVersionURL() */ public String getDownloadInstructionsURL() { return downloadInstructionsURL; } /** * get icon for the row, generated from state. * * @return icon to represent the row. */ public Icon getIcon() { return state.getIcon(); } /** * get marker string expected to find at url if version has not changed. * * @return marker string expected to find at url if version has not changed. */ public String getMarker() { return marker; } /** * set marker string expected to find at url if version has not changed. * * @param marker string expected to find at url if version has not changed. */ public void setMarker( String marker ) { if ( marker.equals( this.marker ) ) { return; } this.marker = marker; setState( AppState.UNTESTED ); } /** * get enum AppState of appName * * @return enum AppState of appName */ public AppState getState() { return state; } /** * set enum AppState of appName. Does not refresh table. * * @param state enum AppState of appName */ public void setState( AppState state ) { this.state = state; normaliseState(); } /** * get version of the appName * * @return version of the appName */ public String getVersion() { return version; } /** * set version of the appName * * @param version version of the appName */ public void setVersion( String version ) { if ( version.equals( this.version ) ) { return; } this.version = version; setState( AppState.UNTESTED ); } /** * get url to check the appName * * @return url to check the appName * @see #getDownloadInstructionsURL() */ public URL getVersionURL() { return versionURL; } /** * set url to check the appName * * @param versionURL url to check the appName */ public void setVersionURL( URL versionURL ) { if ( versionURL.equals( this.versionURL ) ) { return; } this.versionURL = versionURL; setState( AppState.UNTESTED ); } /** * is SNI Server Name Identification enabled for this site? * * @return true if yes. */ public boolean isSNIEnabled() { return this.sni; } /** * set SNI Server Name Identifacation needed for this site. * * @param sni true if sni enabled. */ public void setSNI( boolean sni ) { this.sni = sni; } }