/** * Bandscope Receiver Applet 1.0.0 [SCAN DATA LOADER] * @author Robert J Morton YE572246C * @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[]; // gigantic byte array to hold 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) 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 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; // input stream for downloading index or current HTML file private InputStream I; // date object for the file-modified date of the scan data file private Date D; // Reference to instance of the ... private bs hf; // main bandscope applet private msgpanel mp; // message panel object private bands bd; // band-selector object private scope sc; // scope graph object private freqfigs ff; // frequency-figures object private update updt; // update button and selector class instance private ar86000 rx; // receiver object loader(bs hf,msgpanel mp,scope sc,freqfigs ff, // CONSTRUCTOR update updt,String cb,bands bd) { // Reference to instances of the ... this.hf = hf; // message panel object this.mp = mp; // message panel object this.sc = sc; // scope graph object this.ff = ff; // frefigs object this.updt = updt; // update button and selector class instance this.bd = bd; // band-selector class this.cb = cb; //code-base URL of the main applet } 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 server via HTTP boolean scanDataLoaded() { if(RL > 0) { // if reload not yet expired RL--; // decrement the reload delay timer return true; // and exit } switch(lp) { // THE 2 DOWNLOADING PHASES: case 1: fileConnect(); // connect to bandscope data file on server break; case 2: fileLoad(); // manage the downloading of its content } if(lp == 3) return true; // completion state return false; // error state } private void fileConnect() { // CONNECT TO BANDSCOPE DATA FILE ON SERVER fn = "bs"; // default name for the bandscope data file if((sBT > 0) && (sB > 0)) { // If a specific band has been selected, String s = ""; // pad the band number out to two digits if(sB < 10) s = "0"; // with a leading zero if required, fn = bandType[sBT - 1] // then form the complete file name for + s + sB; // the band's data file } fn += ".dat"; // add the "data" filename extension mp.showMsg("Connecting to server...", false); try { // capture any exceptions locally if(hf.JarredSearch) { // if loading from the applet's ".jar" file // create a stream to load the file from the applet's ".jar" I = getClass().getResourceAsStream(fn); LM = "Scanned: 1970-01-01-00:00 GMT"; lm = 0; // convert to whole seconds L = 1000; // cannot find the current file length easily } else { // ELSE CREATE A STREAM TO LOAD THE FILE FROM THE SERVER: URL url = new URL(cb + fn); // form URL of bandscope data file, URLConnection u = url.openConnection(); // open a connection to it I = u.getInputStream(); // make input stream through which to access it /* Form a readable date of when file was last updated in milliseconds since 1970-01-01-00:00 GMT and convert it to whole seconds. */ LM = "Scanned: " + new Date(lm = u.getLastModified()); lm /= 1000; L = u.getContentLength(); // length of the remote file (bytes) } B = new byte[L]; // create the gigantic buffer for the data l = 0; // number of bytes so far successfully downloaded lp = 2; // advance to the file loading phase } /* If any error occurs during this "try", set unrecoverable error status and then show type of error and where it occurred. */ catch(Exception e) { lp = 0; mp.showMsg("fileConnect() " + e, true); } } // DOWNLOAD THE BANDSCOPE DATA private void fileLoad() { mp.showMsg("Loading " + bd.getBandName() + " scan data.", false); try { int k; // to hold each grabbed byte in turn /* While the entire file has not yet been downloaded and read() hasn't hit the current end of input stream, add its new byte to the big byte array B[]. */ if(hf.JarredSearch) { // if loading bandscope data from jar file while((k = I.read()) != -1) B[l++] = (byte)k; if(l < 200) L = 100; } else // else [if pulling it from the server] while(l < L && (k = I.read()) != -1) B[l++] = (byte)k; if(hf.JarredSearch // If the whole file has now been downloaded, || l >= L) { I.close(); // close the input stream rx.computePlots(); // make graph plots from the downloaded data lp = 3; // set loader to isuccessful completion state computeAge(); // compute the age of current scan data invokeEDT(); // schedule tasks for Event-Despatching Thread mp.showMsg(LM, false); // show date & time when file was last updated } } /* If any error occurs during this "try", set the loader to its error state and then show the type of error and where it occurred. */ catch(Exception e) { lp = 0; mp.showMsg("fileLoad() " + e + " " + L + " " + l, true); } } // DISPLAY THE AGE OF THE FILE ON THE AGE LABEL private void computeAge() { /* The age of the scan data file just loaded is the current system time converted to seconds, minus the time (in seconds) at which the file was last updated. */ long age = System.currentTimeMillis() / 1000 - lm; // From the above numeric age, form the appropriate age message. 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"; } // CALLED BY THE LOADER TO SET VALUES WITHIN SWING WIDGETS void invokeEDT() { try { // update the age label via the event-despatching thread SwingUtilities.invokeLater( new Runnable() { public void run() { threadSafe(); } } ); } catch (Exception e) { } } /* DONE ON THE EVENT-DESPATCHING THREAD: display the scope panel and the frequency figures, then update the text of the age label at bottom right of applet. */ void threadSafe() { sc.atualizar(); ff.atualizar(); updt.setAgeLabel(Age + " old"); } // Return the length of array B[] containing the received scan data file int getL() {return L;} /* Return the loader phase (to check that the scan data is not currently in the process of being loaded). */ int getLP() {return lp;} // get the ith byte from the downloaded scan data file int getB(int i) {return (int)B[i];} }