/** * Bandscope Receiver Applet 1.0.0 [SCAN DATA LOADER] * @author Robert J Morton * @version 13 March 2002, 20 March 2012 * @copyright Robert J Morton (all rights reserved) */ import java.net.*; // for downloading data from the remote server import java.io.*; // for stream handling for the above import java.util.Date; // for bandscope data file date formatting import javax.swing.*; class loader { private static final String bandType[]= { // first 3 letters of bandscope data file names "brd", // broadcast band "ham", // amateur band "air", // aeronautical band "mar" // marine band }; private byte B[]; // large byte array to hold the downloaded signal data private int L = 0, // length of the remote item being loaded l = 0, // number of bytes of the above successfully downloaded lp = 3, // current loader phase (3 = loaded) ls = 0, // load switch sBT = 0, // currently selected band type sB = 0, // currently selected band RL = 0; // reload counter private long t, // current system time lm = 0; /* when current data file was last modified (seconds since 1970-01-01-00:00Z) */ private String LM = "", // date when data file last modified fn = "bs", // default name for the bandscope data file Age = "", // to preserve the part of the age string that changes cb; // code-base URL of the main applet boolean RELOAD = false; private InputStream I; // for downloading index or current HTML file private bs hf; // instance reference of the main bandscope applet private msgpanel mp; // reference to the message panel object private bands bd; // reference to the band-selector object private scope sc; // reference to the scope graph object private freqfigs ff; // reference to the frequency-figures object private ar86000 rx; // reference to the receiver object // reference to current instance of update button and selector class private update updt; // date object for the file-modified date of the receiver's scan data file private Date D; loader(bs hf, msgpanel mp, scope sc, freqfigs ff, update updt, int ls, String cb, bands bd) { this.hf = hf; // reference to the message panel object this.mp = mp; // reference to the message panel object this.sc = sc; // reference to the scope graph object this.ff = ff; // reference to the frefigs object this.updt = updt; // ref to update button and selector class instance this.cb = cb; // code-base URL of the main applet this.bd = bd; // instance reference for the band-selector class this.ls = ls; // load switch } void setAR86000(ar86000 rx) {this.rx = rx;} // called initially from the main applet and thereafter from "bands" void load(int sBT,int sB) { // trigger a reload of the data this.sBT = sBT; // currently selected band type this.sB = sB; // currently selected band lp = 1; // initiate the loading process } void reload() {lp=1; RL=7;} // trigger a reload of the data void post() {} // POST a "RESCAN" command to RX via HTTP boolean scanDataLoaded() { if(RL > 0) {RL--; return true;} // reload delay timer switch(lp) { // THE 2 DOWNLOADING PHASES case 1: fileConnect(); break; // connect to bandscope data file on server case 2: fileLoad(); // manage the downloading of its content } if(lp == 3) return true; return false; } private void fileConnect() { // CONNECT TO THE BANDSCOPE DATA FILE fn = "bs"; // default name for bandscope data file if((sBT > 0) && (sB > 0)) { // if a specific band has been selected String s = ""; // pad band number out to two digits if(sB < 10) s = "0"; // with a leading zero if required fn = bandType[sBT-1]+s+sB; // form the complete file name } fn += ".dat"; // add the "data" filename extension mp.showMsg("Connecting to server...", false); lm = 0; // time since file last modifies milliseconds since 01JAN1970 try { // set to capture any exceptions locally switch(ls) { case 0: L = (int)(new File(fn)).length(); I = new FileInputStream(fn); break; case 1: // Create an input stream to load ile from jar file L = 1000; // cannot find current file length easily I = getClass().getResourceAsStream(fn); break; case 2: // Create an input stream to load ile from server URLConnection u = new URL(cb + fn).openConnection(); L = u.getContentLength(); I = u.getInputStream(); lm = u.getLastModified(); // date last modified } /* Form a readable date when file was last updated (in milli- seconds since 1970-01-01-00:00 GMT) in ugly American date format. */ LM = "Scanned: " + new Date(lm); lm /= 1000; // convert to whole seconds B = new byte[L]; // create the large buffer for the data l = 0; // number of bytes so far successfully downloaded lp = 2; // advance to the file loading phase } catch(Exception e) { // if any error occurs during this "try" lp = 0; // set unrecoverable error status and then mp.showMsg( "fileConnect() " // show where error occurred + e,true // and what type of error it was ); } } private void fileLoad() { // DOWNLOAD THE BANDSCOPE DATA mp.showMsg("Loading " + bd.getBandName() + " scan data.", false); try { int k; // to hold each grabbed byte in turn if(ls == 1) { // L is unknown for jar files /* While the entire file has not yet been down- loaded, add each new byte to the big byte array. */ while((k = I.read()) != -1) B[l++] = (byte)k; if(l < 200) L = 100; } else // L is known for local files and server connections while(l < L && (k = I.read()) != -1) B[l++] = (byte)k; I.close(); // close the URL Connection's input stream rx.computePlots(); // make graph plots from downloaded bandscope data lp = 3; // indicate file loading completed successfully computeAge(); // compute age of current scan data invokeEDT(); // update Swing widgets via Event-Despatching Thread mp.showMsg(LM,false); // show date and time when file was last updated } catch(Exception e) { // if any error occurs during this "try" lp = 0; // set error condition and then mp.showMsg( "fileLoad() " // show where it error occurred + e // show type of error that occurred + " " + L + " " + l,true ); } } private void computeAge() { // DISPLAY AGE OF THE FILE ON AGE LABEL /* The age of the scan data file just loaded is the current system time (converted to seconds), minus the system time (in seconds) at which the file was last updated (modified): */ long age = System.currentTimeMillis() / 1000 - lm; if(age > 2592000) Age = "Over a month"; else if(age > 604800) Age = "Over a week"; else if(age > 86400) Age = "Over a day"; else if (age > 3600) Age = "Over an hour"; else if(age > 60) Age = "" + age / 60 + " min"; else Age = "" + age + " sec"; } void invokeEDT() { // CALLED BY LOADER TO SET VALUES WITHIN SWING WIDGETS try { SwingUtilities.invokeLater( new Runnable() { public void run() {threadSafe();} } ); } catch(Exception e){} } // Update the age label via the event-despatching thread. void threadSafe() { sc.atualizar(); // display the scope panel ff.atualizar(); // display the frequency figures // Update the text of the age label at bottom right of app's panel updt.setAgeLabel(Age + " old"); } // Length of array B[] containing the received scan data file int getL(){return L;} // Loader phase (to check that scan data is not currently being loaded). int getLP() {return lp;} // Get the ith byte from the lownloaded scan data file int getB(int i) {return (int)B[i];} }