/** * Current Account Balances: Graphical Display Applet * @author Robert J Morton UK-YE572246C * @version 12 July 2000, 23 April 2012 * @copyright July 2000 Robert J Morton (all rights reserved) */ /* This applet requires specialised data files called savyyyy.dat (where yyyy is the year number) located in the same directory as savlim1.class and savlim2.class on the web server. It requires no server-side executables or scripts. The data files are generated from input text files by an off-line command-line java program called savlim0.class. This applet conforms to API 1.1 */ import java.applet.*; // all the gubbins to make the applet work import java.awt.*; // for graphics operations (GUI) import java.net.*; // for downloading data from the remote server import java.io.*; // for stream handling for the above import javax.swing.*; // swing GUI widgets library public class savlim1 extends JApplet implements Runnable { private boolean JarredSearch = true, ready = false; // to make sure init thread finishes before // starting data load private int L = 0, // length of the remote item being loaded l = 0, // number of bytes of the above successfully downloaded so far lp = 1; // indicates current download phases private byte B[]; // gigantic byte array to hold the downloaded data private String yearFile, // name of year data file cb; // code base URL - where this applet's class file came from private InputStream I; // input stream for downloading data files private Thread TH; // reference for Internet Data Transfer thread private graph gp; // instance reference of the accounts graph panel public void init() { // do Phase 1 of GUI build try { javax.swing.SwingUtilities.invokeAndWait( new Runnable() { public void run() { init1(); } } ); } catch(Exception e) { showStatus("couldn't create Swing GUI"); } // Get the URL (less file name) from where this applet came cb = getCodeBase().toString(); /* Workaround re Hotjava re Microsoft intranet machine names where getCodeBase() wrongly returns the document base (cira Nov 1999). */ if(!cb.endsWith("/")) { int x = cb.lastIndexOf('/'); if(x != -1) cb = cb.substring(0,x + 1); } TH = new Thread(this); // create a thread for downloading data loadData(2000); // display the data initially for the year 1991 // To signal that the thread has finished [for Netscape Navigator]. ready = true; } /* THE FIRST PHASE OF INITIALISATION: Since this involves the creation and set-up of Swing widgets, it must be done on the Event Dispatching thread. It is invoked from the applet's init() method above. */ private void init1() { // set the applet's background colour setBackground(new Color(238,238,238)); Container // Get the content pane reference cp = getContentPane(); // of the JApplet then set it to allow cp.setLayout(null); // control panels to be laid out manually. /* Create instances of each of the following panels, add it to the applet's pane then set its position and size upon the pane. */ // max/min balances, money scale, month scale and graphs panels maxmin mm = new maxmin(); cp.add(mm); mm.setBounds(10,0,350,50); pscale ps = new pscale(); cp.add(ps); ps.setBounds(10,56,45,212); mscale ms = new mscale(); cp.add(ms); ms.setBounds(49,268,370,30); gp = new graph(mm, ms); cp.add(gp); gp.setBounds(49,62,366,201); // year and inflation selector panels selyear sy = new selyear(this, ms, gp); cp.add(sy); sy.setBounds(425,40,100,240); selinfl si = new selinfl(gp); cp.add(si); si.setBounds(10,300,350,40); } public void start() { TH.start(); } // start the local run-thread public void run() { // MANAGE INTERNET DATA TRANSFERS ON SEPARATE THREAD while(TH != null) { //while this thread exists if(lp == 1) // if Phase 1: start/continue connecting fileConnect(); // to data resource on server. if(lp == 2) // if Phase 2: start/continue managing fileLoad(); // the downloading of its content /* Put the thread to sleep for 50 milliseconds. Catch but ingore any exceptions that may occur during sleep. */ try { TH.sleep(50); } catch (InterruptedException e) { } } } public void stop() { TH = null; } // Stop the local run-thread void fileConnect() { // CONNECT TO THE ACCOUNTS DATA FILE ON THE SERVER if(!ready) // to make sure init thread has return; // finished (re Navigator lockups) showStatus("Connecting to server..."); try { // try to connect to the server /* If loading from a ".jar" file, create a stream to load file from the applet's jar file and set its known length to 4096 [cannot find the current file length easily]. */ if(JarredSearch) { I = getClass().getResourceAsStream("sav" + yearFile + ".dat"); L = 4096; } /* Else we're loading directly from remote server, so create a stream to load file from remote server, form the URL of the account balance data from the code base of the applet (URL of its resident directory), plus its filename prefix, plus the year number e.g. 2001, plus the ".dat" filename extension. From this, create a URL connection and from this get the reference of its input stream and its content length. */ else { URL url = new URL(cb + "sav" + yearFile + ".dat"); URLConnection u = url.openConnection(); I = u.getInputStream(); L = u.getContentLength(); } l = 0; // number of bytes so far successfully downloaded B = new byte[L]; // create the gigantic buffer for the data /* Create a data input stream to read the byte barray as full 16-bit Unicode characters. */ DataInputStream D = new DataInputStream(new ByteArrayInputStream(B)); gp.setD(D); // pass reference to the graph panel lp = 2; // advance to the file loading phase } /* Catch any exceptions occurring during the process of establishing the connection and not the type of exception and where it occurred, then set the loader to its unrecoverable error state. */ catch(Exception e) { lp = 0; showStatus("fileConnect() " + e); } } void fileLoad() { // DOWNLOAD THE HITS DATA showStatus("Loading data..."); int k; // current byte being read() try { /* If loading from applet's own ".jar" file, then while we've not yet hit the 'end of file', add next byte into the giant byte array; */ if(JarredSearch) while((k = I.read()) != -1) B[l++] = (byte)k; /* else we're loading directly from remote server, so while prescribed content length of the resource has not yet been loaded AND we haven't hit the end of the stream, add next byte into the giant byte array. */ else while(l < L && (k = I.read()) != -1) B[l++] = (byte)k; /* if the whole of the index has now been down- loaded, display the load completion message... */ if(JarredSearch || l >= L) { showStatus("Graph data loaded."); I.close(); // close the URL Connection's input stream repaint(); // re-display the applet pane and its contents lp = 0; // set the loader to its normal termination state } } /* If loading process were halted by an error, set loader to its error state, note the type of exception and that it occurred during loading, the length of the resource and the number of bytes success- fully downloaded at the point where the error occurred. */ catch(Exception e) { lp = 0; showStatus("fileLoad() " + e + L + " " + l); } } /* Called by both 'this' and 'selyear': creates string version of the year number e.g. 2001 then initialise loading of the account data for the selected year. */ void loadData(int year) { yearFile = String.valueOf(year); lp = 1; } }