FileDocCategorySizeDatePackage
HttpView.javaAPI DocJ2ME MIDP 2.027217Thu Nov 07 12:02:16 GMT 2002example.http

HttpView

public class HttpView extends MIDlet implements CommandListener, Runnable
An example MIDlet to fetch a page using an HttpConnection. Refer to the startApp, pauseApp, and destroyApp methods so see how it handles each requested transition.

Fields Summary
Command
exitCommand
user interface command for indicating Exit request.
Command
reloadCommand
user interface comand for indicating a page reload request.
Command
headCommand
user interface command to request an HTTP HEAD transaction.
Command
postCommand
user interface command to request an HTTP POST transaction.
Command
getCommand
user interfrace command to request an HTTP GET transaction.
Command
aboutCommand
user interface command to request copyright information.
Command
cancelCommand
user interface command to cancel the current screen.
Command
backCommand
user interface command to return back to previous screen.
Command
headersCommand
user interface command to request current HTTP headers.
Command
requestsCommand
user interface command to display current HTTP request headers.
Command
errorsCommand
user interface command to display errors from current request.
Command
newURLCommand
user interface command to enter a new URL
Command
removeURLCommand
user inetrface command to remove the current URL
Command
okCommand
user interface command to confirm current screen.
Command
helpCommand
user interface command to display help message.
List
urlList
user interface component containing a list of URLs
Vector
urls
array of current URLs
Alert
alert
user interface alert component.
TextBox
content
user interface text box for the contents of the fetched URL.
Display
display
current display.
Thread
thread
instance of a thread for asynchronous networking and user interface.
String
url
current requested url.
Command
requestCommand
current HTTP request type - GET, HEAD, or POST
Form
progressForm
user interface form to hold progress results.
Gauge
progressGauge
user interface progress indicator.
Form
headerForm
user interface screen for HTTP headers
Form
requestForm
form to display request including parsing
Form
errorsForm
form to display exceptions
TextBox
urlbox
data entry text box for inputting URLs
Constructors Summary
public HttpView()
initialize the MIDlet with the current display object.


             
      
        display = Display.getDisplay(this);
        setupList();
        alert = new Alert("Warning");
        alert.setTimeout(2000);

        headerForm = new Form("Headers");
        headerForm.addCommand(backCommand);
        headerForm.addCommand(requestsCommand);
        headerForm.setCommandListener(this);

        requestForm = new Form("Request headers");
        requestForm.addCommand(backCommand);
        requestForm.addCommand(errorsCommand);
        requestForm.setCommandListener(this);

        progressForm = new Form("Progress");
        progressForm.addCommand(cancelCommand);
        progressForm.setCommandListener(this);

        progressGauge = new javax.microedition.lcdui.Gauge(url, false, 9, 0);
        progressForm.append(progressGauge);

        errorsForm = new Form("Errors");
        errorsForm.addCommand(backCommand);
        errorsForm.addCommand(headersCommand);
        errorsForm.setCommandListener(this);
        
        urlbox = new TextBox("Enter Url", "http://", 400, TextField.URL);
        urlbox.addCommand(okCommand);
        urlbox.setCommandListener(this);
    
Methods Summary
voidcleanUp(HttpConnection conn, java.io.InputStream input, java.io.OutputStream output)
Clean up all objects used by the HttpConnection. We must close the InputStream, OutputStream objects, as well as the HttpConnection object, to reclaim system resources. Otherwise, we may not be able to make new connections on some platforms.

param
conn the HttpConnection
param
input the InputStream of the HttpConnection, may be null if it's not yet opened.
param
output the OutputStream the HttpConnection, may be null if it's not yet opened.

        Thread mythread = Thread.currentThread();

        try {
            if (input != null) {
                input.close();
            }
        } catch (IOException e) {
            if (mythread == thread) {
  		genErrorsForm("InputStream close error", e);
 	    }
        }
        try {
            if (output != null) {
                output.close();
            }
        } catch (IOException e) {
            if (mythread == thread) {
  		genErrorsForm("OutStream close error", e);
 	    }
        }
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (IOException e) {
            if (mythread == thread) {
 		genErrorsForm("HttpConnection close error", e);
 	    }
        }
    
voidclearForm(Form form)
Clear out all items in a Form.

param
form the Form to clear.

        int s = form.size();
        for (int i = s-1; i >= 0; i--) {
            form.delete(i);
        }
    
public voidcommandAction(Command c, Displayable s)
Respond to commands, including exit

param
c user interface command requested
param
s screen object initiating the request

        try {
            if (c == exitCommand) {
                destroyApp(false);
                notifyDestroyed();
            } else if (c == headCommand ||
		       c == getCommand ||
		       c == postCommand ||
		       c == List.SELECT_COMMAND) {
                if (c == List.SELECT_COMMAND)
		    c = getCommand;
                requestCommand = c;

                // Display the progress screen and
                // start the thread to read the url
                int i = urlList.getSelectedIndex();

                url = (String)urls.elementAt(i);
                genProgressForm("Progress", url);
                display.setCurrent(progressForm);
                thread = new Thread(this);
                thread.start();
            } else if (c == headersCommand) {
                display.setCurrent(headerForm);
            } else if (c == requestsCommand) {
                display.setCurrent(requestForm);
            } else if (c == errorsCommand) {
                display.setCurrent(errorsForm);
            } else if (c == backCommand) {
                if (s == headerForm || s == requestForm || s == errorsForm) {
                    display.setCurrent(content);
                } else {
                    // Display the list of urls.
                    display.setCurrent(urlList);
                }
            } else if (c == cancelCommand) {
                // Signal thread to stop and put an alert.
                thread = null;
                alert.setString("Loading cancelled.");
                display.setCurrent(alert, urlList);
            } else if (c == aboutCommand) {
                About.showAbout(display);
            } else if (c == newURLCommand) {
                display.setCurrent(urlbox);
            } else if (c == removeURLCommand) {
                int i = urlList.getSelectedIndex();
                urlList.delete(i);
                urls.removeElementAt(i);
            } else if (c == okCommand && s == urlbox) {
                String newurl = urlbox.getString();
                urlList.append(newurl, null);
                urls.addElement(newurl);
                display.setCurrent(urlList);
            } else if (c == helpCommand) {
                String helpString = 
                    "Use Head, Get or Post to download a URL.\n\n" +
                    "Use 'New URL' to enter a new URL.";
                Alert alert = new Alert(null, helpString, null, null);
                alert.setTimeout(Alert.FOREVER);
                display.setCurrent(alert); 
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    
public voiddestroyApp(boolean unconditional)
Destroy must cleanup everything. The thread is signaled to stop and no result is produced.

param
unconditional true if a forced shutdown was requested

        thread = null;
    
voidgenErrorsForm(java.lang.String s, java.lang.Throwable ex)
Set the Alert to the exception message and display it.

param
s the Exception title string
param
ex the Exception

        clearForm(errorsForm);
        if (s != null) {
            errorsForm.setTitle(s);
        } else {
            errorsForm.setTitle("Exception");
        }

        if (ex != null) {
            ex.printStackTrace();  // debug
            errorsForm.append(ex.getClass().getName());
            errorsForm.append("\n");
            String m = ex.getMessage();
            if (m != null) {
                errorsForm.append(m);
            }
        } else {
            errorsForm.append("None");
        }
    
voidgenHeaderForm(HttpConnection c)
Generate and fill in the Form with the header fields.

param
c the open connection with the result headers.

        clearForm(headerForm);
        headerForm.append(new StringItem("response message: ",
                                         c.getResponseMessage()));
        headerForm.append(new StringItem("response code: ",
                                         c.getResponseCode() + ""));
        for (int i = 0; ; i++) {
            String key = c.getHeaderFieldKey(i);
            if (key == null)
		break;
            String value = c.getHeaderField(i);
            StringItem item = new StringItem(key + ": ", value);
            headerForm.append(item);
        }
    
voidgenProgressForm(java.lang.String name, java.lang.String url)
Generate the options form with URL title and progress gauge.

param
name the title of the URL to be loaded.
param
url label for the progress gauge

        progressGauge.setValue(0);
        progressGauge.setLabel(url);
        progressForm.setTitle(name);
    
voidgenRequestForm(HttpConnection c)
Generate the form with the request attributes and values.

param
c the open connection with the request headers.

        clearForm(requestForm);

        requestForm.append(new StringItem("URL: ", 
                                          c.getURL()));
        requestForm.append(new StringItem("Method: ",
                                          c.getRequestMethod()));
        requestForm.append(new StringItem("Protocol: ",
                                          c.getProtocol()));
	requestForm.append(new StringItem("Host: ",
                                          c.getHost()));
	requestForm.append(new StringItem("File: ",
                                          c.getFile()));
	requestForm.append(new StringItem("Ref: ",
                                          c.getRef()));
	requestForm.append(new StringItem("Query: ",
                                          c.getQuery()));
	requestForm.append(new StringItem("Port: ",
                                          Integer.toString(c.getPort())));
        requestForm.append(new StringItem("User-Agent: ",
			   c.getRequestProperty("User-Agent")));
        requestForm.append(new StringItem("Content-Language: ",
			   c.getRequestProperty("Content-Language")));
    
HttpConnectionhandleRedirects(HttpConnection c)
Check for redirect response codes and handle the redirect by getting the new location and opening a new connection to it. The original connection is closed. The process repeats until there are no more redirects.

param
c the initial HttpConnection
return
the final HttpConnection

        while (true) {
            int code = c.getResponseCode();
            switch (code) {
            case HttpConnection.HTTP_TEMP_REDIRECT:
            case HttpConnection.HTTP_MOVED_TEMP:
            case HttpConnection.HTTP_MOVED_PERM:
                String loc = c.getHeaderField("location");
                c.close();
		// DEBUG: System.out.println("Redirecting to " + loc);
                showAlert("Redirecting to " + loc, null);
                progressGauge.setLabel(loc);

                c = (HttpConnection)Connector.open(loc);
                // TBD: Copy request properties
                continue;
            default:
                return c;
            }
        }
    
public voidpauseApp()
Pause signals the thread to stop by clearing the thread field. If stopped before done with the iterations it will be restarted from scratch later.

    
public voidrun()
Fetch the specified url in a separate thread and update the progress bar as it goes. If the user cancels the fetch, the thread be changed from this thread. If this happens no further updates should be made to the displayable forms. Those shared objects may be re-used by the next fetch.

        long start = 0, end = 0;
        int bytecode_count_start = 0, bytecode_count_end = 0;

        Thread mythread = Thread.currentThread();
	String method = HttpConnection.GET;
	if (requestCommand == headCommand) {
	    method = HttpConnection.HEAD;
	} else if (requestCommand == postCommand) {
	    method = HttpConnection.POST;
	}

        if (content == null) {
            content = new TextBox("Content", "", 4096, 0);
            content.addCommand(backCommand);
            content.addCommand(headersCommand);
            content.setCommandListener(this);
        }

        // Clear the buffers and forms so then can be displayed
        // even if an exception terminates reading early.
	content.setTitle("Body len = 0");
	content.setString("");
	genErrorsForm("Errors", null);
	clearForm(requestForm);
	clearForm(headerForm);
	progressGauge.setValue(1);

	HttpConnection conn = null;
	InputStream input = null;
        OutputStream output = null;
        StringBuffer b;
        String string = null;

	try {
	    long len = 0;

	    conn = (HttpConnection)Connector.open(url);
	    conn.setRequestMethod(method);
            setConfig(conn);
	    if (mythread != thread) {
		return;
	    }
	    progressGauge.setValue(2);

            for (int hops = 0; hops < 2; hops++) {
                // Send data to the server (if necessary). Then, see if
                // we're redirected. If so, hop to the new URL
                // specified by the server.
                //
                // You can choose how many hops to make by changing the
                // exit condition of this loop.
                //
                // To see an example of this, try the link
                // "http://www.sun.com/products" link, which will 
                // redirect you to a link with a session ID.

                if (method == HttpConnection.POST) {
                    output = conn.openOutputStream();
                    if (mythread != thread) {
                        return;
                    }
                    output.write("hello midlet world".getBytes());
                    output.close();
                    output = null;
                }
                HttpConnection newConn = handleRedirects(conn);
                if (conn != newConn) {
                    conn = newConn;
                } else {
                    break;
                }
            }
	    genRequestForm(conn);
            

	    input = conn.openInputStream();
	    if (mythread != thread) {
		return;
	    }
	    content.setTitle(conn.getResponseMessage() +
			     " (" + conn.getResponseCode() + ")");
	    genHeaderForm(conn);
	    progressGauge.setValue(5);
	    if (mythread != thread) {
		return;
	    }

            // Download the content of the URL. We limit our download
            // to 4096 bytes (content.getMaxSize()), as most small
            // devices may not be able to handler larger size.
            //
            // A "real program", of course, needs to handle large
            // downloads intelligently. If possible, it should work
            // with the server to limit downloads to small sizes. If
            // this is not possible, it should download only part of
            // the data and allow the user to specify which part to
            // download.

            len = conn.getLength();
            b = new StringBuffer(len >= 0 ? (int)len : 1000);
            int max = content.getMaxSize();
            if (len != -1) {
		// Read content-Length bytes, or until max is reached.
                int ch = 0;
		for (int i = 0; i < len; i++) {
		    if ((ch = input.read()) != -1) {
			if (ch <= ' ") {
                            ch = ' ";
                        }
                        b.append((char) ch);
                        if (b.length() >= max) {
                            break;
                        }
		    }
		}
	    } else {
		// Read til the connection is closed, or til max is reached.
		// (Typical HTTP/1.0 script generated output)
                int ch = 0;
                len = 0;
		while ((ch = input.read()) != -1) {
		    if (ch <= ' ") {
                        ch = ' ";
                    }
		    b.append((char)ch);
                    if (b.length() >= max) {
                        break;
                    }
		}
	    }

            string = b.toString();
                        
            if (mythread != thread) {
		return;
	    }

	    progressGauge.setValue(8);

            content.setTitle("Body len = " + b.length());
            
            if (b.length() > 0) {
                content.setString(string);
            } else {
                content.setString("no data");
            }

	    display.setCurrent(content);
	    progressGauge.setValue(9);
	} catch (OutOfMemoryError mem) {
            // Mmm, we still run out of memory, even after setting
            // max download to 4096 bytes. Tell user about the error.
            //
            // A "real program" should decide on the max download
            // size depending on available heap space, or perhaps
            // allow the user to set the max size

            b = null;
            content = null; // free memory to print error
	    // DEBUG:            System.out.println("Out of Memory");
            mem.printStackTrace();

            if (mythread != thread) {
                genErrorsForm("Memory", mem);
                display.setCurrent(errorsForm);
            }
        } catch (Exception ex) {
            ex.printStackTrace();

	    genErrorsForm("Errors", ex);
	    display.setCurrent(errorsForm);
	} finally {
            cleanUp(conn, input, output);

	    if (mythread == thread) {
                progressGauge.setValue(10);
            }
	}
    
voidsetConfig(HttpConnection c)
Add request properties for the configuration, profiles, and locale of this system.

param
c current HttpConnection to receive user agent header

        String conf = System.getProperty("microedition.configuration");
        String prof = System.getProperty("microedition.profiles");
	int space = prof.indexOf(' ");
	if (space != -1) {
	    prof = prof.substring(0, space - 1);
	}

        String platform = System.getProperty("microedition.platform");
        String locale = System.getProperty("microedition.locale");
        String ua = "Profile/" + prof +
                " Configuration/" + conf +
	    " Platform/" + platform;

	// DEBUG:        System.out.println("User-Agent: " + ua);
        c.setRequestProperty("User-Agent", ua);
        
        if (locale != null) {
	    // DEBUG:       System.out.println("Content-Language: " + locale);
            c.setRequestProperty("Content-Language", locale);
        }
    
voidsetupList()
Check the attributes in the descriptor that identify url's and titles and initialize the lists of urls and urlList.

The attributes are named "ViewTitle-n" and "ViewURL-n". The value "n" must start at "1" and increment by 1.

        urls = new Vector();
        urlList = new List("URLs", List.IMPLICIT);
        urlList.addCommand(headCommand);
        urlList.addCommand(getCommand);
        urlList.addCommand(postCommand);
        urlList.addCommand(exitCommand);
        urlList.addCommand(newURLCommand);
        urlList.addCommand(removeURLCommand);
        urlList.addCommand(helpCommand);
        urlList.setCommandListener(this);

        for (int n = 1; n < 100; n++) {
            String nthURL = "ViewURL-"+ n;
            String url = getAppProperty(nthURL);
            if (url == null || url.length() == 0) {
		break;
            }

            String nthTitle = "ViewTitle-" + n;
            String title = getAppProperty(nthTitle);
            if (title == null || title.length() == 0) {
		title = url;
            }

            urls.addElement(url);
            urlList.append(title, null);
        }
        urls.addElement("http://jse.east/Telco/HttpTest.txt");
        // urls.addElement(
        //         "http://dhcp-70-219:8080/examples/servlet/httpdbexport");
        // urls.addElement(
        //       "http://jse.east.sun.com/~kfinn/proxy.jar");
        // urls.addElement(
        //       "http://dhcp-70-219:8080/examples/servlet/HelloWorldKerry");
        urlList.append("Test URL", null);
    
voidshowAlert(java.lang.String s, Screen next)
Set the alert string and display it.

param
s the error message
param
next the screen to be shown after the Alert.

        alert.setString(s);
        if (next == null) {
            display.setCurrent(alert);
        } else {
            display.setCurrent(alert, next);
        }
    
public voidstartApp()
Start creates the thread to do the timing. It should return immediately to keep the dispatcher from hanging.

	/* Bytes read from the URL update connection. */
	int count;
	/* Check for inbound async connection for sample Finger port. */
	String[] connections = PushRegistry.listConnections(true);

	/* HttpView was started to handle inbound request. */
	String pushProperty = getAppProperty("MIDlet-Push-1");

	if (connections != null && connections.length > 0) {
	    String newurl = "Pushed URL Placeholder";

	    /* DEBUG: Test basic get registry information interfaces. */
	    try {
		String midlet = PushRegistry.getMIDlet(connections[0]);
		String filter = PushRegistry.getFilter(connections[0]);

	    } catch (Exception e) {
		e.printStackTrace();
	    }
		    
	    /* Check for socket or datagram connection. */
	    if (connections[0].startsWith("socket://")) {
		try {
		    /* Simple test assumes a server socket connection. */
		    ServerSocketConnection scn = (ServerSocketConnection)
			Connector.open(connections[0]);
		    SocketConnection sc = (SocketConnection)
			scn.acceptAndOpen();
		    
		    /* Read one line of text as a new URL to add to the list. */
		    DataInputStream dis = sc.openDataInputStream();
		    byte[] buf = new byte[256];
		    int endofline = 0;
		    count =	dis.read(buf);
		    for (int i = 0; i < count; i++) {
			if (buf[i] == '\n") {
			    endofline = i;
			    break;
			}
		    }
		    newurl = new String(buf, 0, endofline);

		    dis.close();

		    sc.close();
		    scn.close();
		} catch (IOException e) {
		    e.printStackTrace();
		}
		
		/* 
		 * After successfully receiving a socket posted URL
		 * register a datgram connection, too.
		 */
		try {
		    PushRegistry.registerConnection("datagram://:40080",
						    "example.http.HttpView",
						    "129.148.*.*");
		} catch (ClassNotFoundException e) {
		    e.printStackTrace();
		} catch (IllegalArgumentException e) {
		    e.printStackTrace();
		} catch (ConnectionNotFoundException e) {
		    e.printStackTrace();
		} catch (IOException e) {
		    e.printStackTrace();
		}
		
	    } else if (connections[0].startsWith("datagram://")) {
		/* Must be a datagram connection. */
		try {
		    UDPDatagramConnection udc = (UDPDatagramConnection)
			Connector.open(connections[0]);
		    Datagram dg = udc.newDatagram(256);

		    udc.receive(dg);
		    udc.close();
		    
		    byte[] buf = dg.getData();

		    int endofline = 0;
		    count =	buf.length;
		    for (int i = 0; i < count; i++) {
			if (buf[i] == '\n") {
			    endofline = i;
			    break;
			}
		    }
		    newurl = new String(buf, 0, endofline);
		    

		    /* Unregister the datagram connection. */
		    PushRegistry.unregisterConnection("datagram://:40080");
		    
		} catch (SecurityException e) {
		    e.printStackTrace();
		} catch (IOException e) {
		    e.printStackTrace();
		}
	    } else {
		// NYI - unknown connection type
	    }
	    urlList.append(newurl, null);
	    urls.addElement(newurl);
	} else {
	    connections = PushRegistry.listConnections(false);
	    
	    /*
	     * If the MIDlet was started manually, set an alarm
	     * to restart automatically int one minute.
	     */
	    try {
		Date alarm = new Date();
		PushRegistry.registerAlarm("example.http.HttpView", 
					   alarm.getTime() + 60000);
	    } catch (ClassNotFoundException e) {
		e.printStackTrace();
	    } catch (ConnectionNotFoundException e) {
		e.printStackTrace();
	    }
	}	
	if (urlList.size() > 0) {
            display.setCurrent(urlList);
        } else {
            alert.setString("No url's configured.");
            display.setCurrent(alert, urlList);
        }