Current MS Students/Sarang Nazari/CS 590

From CSWiki

Jump to: navigation, search

Contents

[edit] Week 3 July 7

Building MIDlets

MIDP (Mobile Information Device Profile) applications are piquantly called MIDlets, a continuation of the naming theme begun by applets and servlets. Writing MIDlets is relatively easy for a moderately experienced Java programmer. After all, the programming language is still Java. Furthermore, many of the fundamental APIs from java.lang and java.io are basically the same in the MIDP as they are in J2SE.

MIDlets are developed on regular desktop computers, although the MIDlet itself is designed to run on a small device. To develop MIDlets, you'll need some kind of development kit, either from Sun Microsystems or another vendor.

A good tool is Sun's J2ME Wireless Toolkit. The J2ME Wireless Toolkit includes a GUI tool that automates some of the tedious details of building and packaging MIDlets, providing a simple path from source code to running MIDlets.

You write and complile a MIDlet using J2SE on your desktop computer. The MIDlet itself will run on a mobile phone, pager, or other mobile information device that supports MIDP.

The J2ME Wireless Toolkit takes care of the details as long as you put the source code in the right directory.

  1. Start the toolkit, called KToolbar
  2. Choose New Project from the toolbar to create a new project
  3. J2ME Wireless Toolkit will ask you for the name of the project and the MIDlet class name.
  4. Click the Create Project button and then the OK button to dismiss the project settings window

Sun's J2ME Wireless Toolkit emulators

The J2ME Wireless Toolkit includes several different emulators that you can use to test your applications. When you click the Run button in the J2ME Wireless Toolkit, your application is launched in the currently selected emulator. The Wireless Toolkit devices

The J2ME Wireless Toolkit 2.2 contains four main device emulators:

   * DefaultColorPhone is a device with a 240-by-320-pixel color screen.
   * DefaultGrayPhone has a 108-by-208-pixel grayscale screen.
   * MediaControlSkin is similar to the default phone emulator and has a color screen of 108-by-208 pixels, 
      but its buttons are labeled with controls like a music player: a square for stop, a triangle for play, 
      volume control buttons, etc.
   * QwertyDevice is a smartphone with a 636-by-235 color screen and a miniature QWERTY keyboard.

[edit] Week 4 July 14

A MIDLet is a MID Profile application. The application must extend this class to allow the application management software to control the MIDlet and to be able to retrieve properties from the application descriptor and notify and request state changes. The methods of this class allow the application management software to create, start, pause, and destroy a MIDlet. A MIDlet is a set of classes designed to be run and controlled by the application management software via this interface. The states allow the application management software to manage the activities of multiple MIDlets within a runtime environment. It can select which MIDlets are active at a given time by starting and pausing them individually. The application management software maintains the state of the MIDlet and invokes methods on the MIDlet to change states. The MIDlet implements these methods to update its internal activities and resource usage as directed by the application management software. The MIDlet can initiate some state changes itself and notifies the application management software of those state changes by invoking the appropriate methods.

public abstract class MIDlet {
 
  // Fields
  private MIDletProxy state;
 
  // Constructors
  protected MIDlet() { }
 
  // Methods
  protected abstract void startApp() throws MIDletStateChangeException;
  protected abstract void pauseApp();
  protected abstract void destroyApp(boolean _boolean) throws MIDletStateChangeException;
  public final void notifyDestroyed() { }
  public final void notifyPaused() { }
  public final String getAppProperty(String key) { return null;}
  public final void resumeRequest() { }
}

The default data controller handles most simple work that a data controller needs to do. It listens for SHObjects and fires a ParameterEvent with the name and value. It also handles state change events that target the data view.

package javax.microedition.lcdui;
 
public abstract interface CommandListener {
 
  // Methods
  void commandAction(Command command, Displayable displayable);
}
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
 
public class Test extends MIDlet
   implements CommandListener{//, Runnable {
   private Display mDisplay;
 
 
   private Command mExitCommand, mSayCommand, mCancelCommand;
 
 
   private TextBox mSubmitBox;
   private Form mProgressForm;
   private StringItem mProgressString;
 
   public Test() {
      mExitCommand = new Command("Exit", Command.EXIT, 0);
      mSayCommand = new Command("Say Hello", Command.SCREEN, 0);
      mCancelCommand = new Command("Cancel", Command.CANCEL, 0);
      mSubmitBox = new TextBox("First MIDLET", "", 32, 0);
      mSubmitBox.addCommand(mExitCommand);
      mSubmitBox.addCommand(mSayCommand);
      mSubmitBox.setCommandListener(this);
      mProgressForm = new Form("Say hello progress");
      mProgressString = new StringItem(null, null);
      mProgressForm.append(mProgressString);
   }
 
 
   public void startApp() {
      mDisplay = Display.getDisplay(this);
      mDisplay.setCurrent(mSubmitBox);
   }
 
   public void pauseApp() {}
 
   public void destroyApp(boolean unconditional) {}
 
   public void commandAction(Command c, Displayable s) {
      if (c == mExitCommand) {
         destroyApp(false);
         notifyDestroyed();
      }
      else if (c == mSayCommand) {
         String word = mSubmitBox.getString();
         mSubmitBox.setString("Hello " +  word);
      }
   }
}

[edit] Week 5 July 21

MIDP GUI Programming

The MIDP UI consists of high-level and low-level APIs.

High-Level API

The high-level API is designed for applications whose client parts run on mobile information devices where portability is important. To achieve portability, the API employs a high-level abstraction and gives you little control over its look and feel. For example, you cannot define the visual appearance (shape, color, or font) of components. Interaction with components is encapsulated by the implementation and the application is not aware of such interactions.

When you use the high-level API, the underlying implementation does the necessary adaptation to the device's hardware and native user interface style. The high-level API is implemented by classes that inherit from the Screen class.

Low-Level API

The low-level API provides little abstraction. It is designed for applications that need precise placement and control of graphic elements and access to low-level input events. This API gives the application full control over what is being drawn on the display. The Canvas and Graphics classes implement the low-level API.

It is important to note that MIDlets that access the low-level API are not guaranteed to be portable because this API provides mechanisms to access details that are specific to a particular device.

The MIDP GUI Programming Model

The central abstraction of the MIDP UI is a screen, which is an object that encapsulates device-specific graphics rendering user input. Only one screen can be visible at a time, and the user can traverse only through the items on that screen.

The main reason for the screen-based design is that mobile information devices have different display and keypad solutions. If an application has to be aware of component layout, scrolling, and focus traversal it compromises portability.

There are three types of screens:

  • Screens that encapsulate a complex user interface component that involves a List or TextBox component. The structure of these screens is predefined, and the application cannot add other components to these screens.
  • Generic screens that use a Form component. The application can add text, images, and a simple set of related UI components to the form.
  • Screens used within the context of the low-level API, such as a subclass of the Canvas class.

The Display class is the display manager that is instantiated for each active MIDlet and provides methods to retrieve information about the device's display capabilities. A screen is made visible by calling the Display.setCurrent() method.

Example

This example demonstrates how to create various GUI components. The MIDlet for this example allows you to test lists, forms, choices, gauges, text fields, text boxes, for instance.

The GuiTests MIDlet has a few methods for testing various GUI components. The MIDlet makes use of the following classes, listed in alphabetical order, from the javax.microedition.lcdui package:

   * Alert
   * Command
   * DateField
   * Display
   * Displayable
   * Form
   * Gauge
   * List
   * TextBox
   * TextField
   * Ticker
   * CommandListener
import javax.microedition.lcdui.*;
    import javax.microedition.midlet.*;
 
    public class GuiTests extends MIDlet 
    implements CommandListener {
        // display manager
        Display display;
        
        // a menu with items
        // main menu
        List menu;
 
        // list of choices
        List choose;
 
        // textbox
        TextBox input;
 
        // ticker
        Ticker ticker = new Ticker(
        "Test GUI Components");
 
        // alerts
        final Alert soundAlert = 
        new Alert("sound Alert");
 
        // date
        DateField date = new DateField("Today's date: ", DateField.DATE);
 
        // form
        Form form = new Form("Form for Stuff");
 
        // today's form
        Form today = new Form("Today's date");
            
        // gauge
        Gauge gauge = new Gauge("Progress Bar", false, 20, 9);
 
        // text field
        TextField textfield = new TextField(
        "TextField Label", "abc", 50, 0);
 
        // command
        static final Command backCommand =
         new Command("Back", Command.BACK, 0);
        static final Command mainMenuCommand =
        new Command("Main", Command.SCREEN, 1);
        static final Command exitCommand =
         new Command("Exit", Command.STOP, 2);
        String currentMenu;
 
        // constructor.
        public GuiTests() {
        }
 
        /**
         * Start the MIDlet by creating a list of
         * items and associating the
         * exit command with it.
         */
        public void startApp() throws 
        MIDletStateChangeException {
          display = Display.getDisplay(this);
          menu = new List(
          "Test Components", Choice.IMPLICIT);
          menu.append("Test TextBox", null);
          menu.append("Test List", null);
          menu.append("Test Alert", null);
          menu.append("Test Date", null);
          menu.append("Test Form", null);
          menu.addCommand(exitCommand);
          menu.setCommandListener(this);
          menu.setTicker(ticker);
          mainMenu();
          // form
          form.append(gauge);
          form.append(textfield);
          // today
          today.append(date);
        }
 
        public void pauseApp() {
          display = null;
          choose = null;
          menu = null;
          ticker = null;
          form = null;
          today = null;
          input = null;
          gauge = null;
          textfield = null;      
        }
 
        public void destroyApp(boolean unconditional) {
          notifyDestroyed();
        }
 
        // main menu
        void mainMenu() {
          display.setCurrent(menu);
          currentMenu = "Main";
        }
 
        /**
         * Test the TextBox component.
         */
        public void testTextBox() {
          input = new TextBox
          ("Enter Some Text:", "", 10, TextField.ANY);
          input.setTicker(new Ticker(
          "Testing TextBox"));
          input.addCommand(backCommand);
          input.setCommandListener(this);
          input.setString("");
          display.setCurrent(input);
          currentMenu = "input";
        }
       
        /**
         * Test the List component.
         */
        public void testList() {
            choose = new List("Choose Items",
            Choice.MULTIPLE);
            choose.setTicker(new Ticker(
            "Testing List"));
            choose.addCommand(backCommand);
            choose.setCommandListener(this);
            choose.append("Item 1", null);
            choose.append("Item 2", null);
            choose.append("Item 3", null);
            display.setCurrent(choose);
            currentMenu = "list"; 
       }
 
       /**
        * Test the Alert component.
        */
       public void testAlert() {
          soundAlert.setType(AlertType.ERROR);
          //soundAlert.setTimeout(20);
          soundAlert.setString("** ERROR **");
          display.setCurrent(soundAlert);
       }
 
       /**
        * Test the DateField component.
        */
       public void testDate() {
          java.util.Date now = new java.util.Date();
          date.setDate(now);
          today.addCommand(backCommand);
          today.setCommandListener(this);
          display.setCurrent(today);
          currentMenu = "date";
       }
 
       /**
        * Test the Form component.
        */
       public void testForm() {
          form.addCommand(backCommand);
          form.setCommandListener(this);
          display.setCurrent(form);
          currentMenu = "form";
       }
 
       /**
        * Handle events.
        */  
       public void commandAction(Command c,
       Displayable d) {
          String label = c.getLabel();
          if (label.equals("Exit")) {
             destroyApp(true);
          } else if (label.equals("Back")) {
              if(currentMenu.equals("list") 
              || currentMenu.equals("input") ||
                   currentMenu.equals("date")
                   || currentMenu.equals("form")) {
                // go back to menu
                mainMenu();
              } 
 
          } else {
             List down = (List)display.getCurrent();
             switch(down.getSelectedIndex()) {
               case 0: testTextBox();break;
               case 1: testList();break;
               case 2: testAlert();break;
               case 3: testDate();break;
               case 4: testForm();break;
             }
                
          }
      }
    }

[edit] Week 6 July 28

Secure JavaMail with JSSE


The Java Secure Socket Extension (JSSE) API provides SSL functionality that you can add to any JavaMail storage provider. Before we get started, you must download and install JavaMail, JSSE, and all the required packages as described in the JSSE and JavaMail documentation on Sun's Website (most required downloads are included in Java 2 Standard Edition 1.4), as well as JavaMail and JSSE providers of your choice.

Before the JSSE framework can recognize any JSSE providers, you must register them permanently in the <'java home'>\jre\lib\security\java.security properties file or register them dynamically by calling the Security.addProvider() method in your code:

 Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider());


Then you need to replace JavaMail's default socket factory with JSSE's SSL socket factory. This approach is similar to the one used in "Java Tip 96: Use HTTPS in Your Java Client Code"; however, in our case, we have no control over socket creation since sockets are created inside the JavaMail framework, not in the application code or storage provider. Fortunately, JavaMail accepts several undocumented properties, allowing you to set up a custom socket factory class and some other parameters. Those properties are:

mail.<protocol>.socketFactory.class
  mail.<protocol>.socketFactory.fallback 
  mail.<protocol>.socketFactory.port
  mail.<protocol>.timeout


Now you can use the following code to replace a socket factory:

final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
  Properties props = System.getProperties();
  // IMAP provider
  props.setProperty( "mail.imap.socketFactory.class", SSL_FACTORY);
  // POP3 provider
  props.setProperty( "mail.pop3.socketFactory.class", SSL_FACTORY);
  // NNTP provider (if any)
  // props.setProperty( "mail.nntp.socketFactory.class", SSL_FACTORY);


If you want JavaMail to use only secure connections, you configure the appropriate properties so JavaMail doesn't fall back to an unsecure connection when a secure one fails:

// IMAP provider
  props.setProperty( "mail.imap.socketFactory.fallback", "false");
  // POP3 provider
  props.setProperty( "mail.pop3.socketFactory.fallback", "false");
  // NNTP provider (if any)
  // props.setProperty( "mail.nntp.socketFactory.fallback", "false");


You then change the default port number to the corresponding port that your protocol's secure version uses; otherwise, you must use a fully qualified address (that includes a port number) in the URL passed to JavaMail (for example, imap://id:password@your.imap.server.com:993/folder/), or else you get an "unrecognized SSL handshake" exception. You specify these properties like so:

// IMAP provider
  props.setProperty( "mail.imap.port", "993");
  props.setProperty( "mail.imap.socketFactory.port", "993");
  // POP3 provider
  props.setProperty( "mail.pop3.port", "995");
  props.setProperty( "mail.pop3.socketFactory.port", "995");
  // NNTP provider (if any)
  // props.setProperty( "mail.pop3.port", "563");
  // props.setProperty( "mail.pop3.socketFactory.port", "563");


After setting up all the properties, you can open a secure JavaMail session:

 Session session = Session.getInstance(props);


Certificates

Unfortunately, you may realize that the code above throws an SSLException "untrusted server cert chain" if the mail server certificate is not installed locally. In that case, you should obtain a correct, valid certificate for the server and use the keytool utility to add it to a local key storage at <javahome>\jre\lib\security\cacerts.

Alternatively, you can replace the default TrustManager. However, since you can't control socket creation and you want your TrustManager to work, you must use your own socket factory with SSLSocketFactory, which creates secure sockets.

Our simple example TrustManager implementation, DummyTrustManager.java, accepts all certificates without validation, even if the certificate name differs from the server name. This could be a security issue you may want to address in your application. For example, you can show a nice GUI dialog asking if the user trusts the certificate, and then store the certificate locally (you've probably seen these dialogs in Netscape Navigator or MS Internet Explorer).

Here is the code:

import com.sun.net.ssl.X509TrustManager;
  import java.security.cert.X509Certificate;
  public class DummyTrustManager implements X509TrustManager {
    public boolean isClientTrusted( X509Certificate[] cert) {
      return true;
    }
    public boolean isServerTrusted( X509Certificate[] cert) {
      return true;
    }
    public X509Certificate[] getAcceptedIssuers() {
      return new X509Certificate[ 0];
    }
  }

You also need to implement a custom SSLSocketFactory, like DummySSLSocketFactor.java. We will use the Proxy pattern to change the TrustManager of a standard SSLSocketFactory:

import com.sun.net.ssl.*;
  import java.io.IOException;
  import java.net.InetAddress;
  import java.net.Socket;
  import javax.net.SocketFactory;
  import javax.net.ssl.SSLSocketFactory;
  public class DummySSLSocketFactory extends SSLSocketFactory {
    private SSLSocketFactory factory;
    public DummySSLSocketFactory() {
      System.out.println( "DummySocketFactory instantiated");
      try {
        SSLContext sslcontext = SSLContext.getInstance( "TLS");
        sslcontext.init( null, // No KeyManager required
            new TrustManager[] { new DummyTrustManager()},
            new java.security.SecureRandom());
        factory = ( SSLSocketFactory) sslcontext.getSocketFactory();
      } catch( Exception ex) {
        ex.printStackTrace();
      }
    }
    public static SocketFactory getDefault() {
      return new DummySSLSocketFactory();
    }
    public Socket createSocket( Socket socket, String s, int i, boolean 
flag)
        throws IOException {
      return factory.createSocket( socket, s, i, flag);
    }
    public Socket createSocket( InetAddress inaddr, int i,
        InetAddress inaddr1, int j) throws IOException {
      return factory.createSocket( inaddr, i, inaddr1, j);
    }
    public Socket createSocket( InetAddress inaddr, int i) throws 
IOException {
      return factory.createSocket( inaddr, i);
    }
    public Socket createSocket( String s, int i, InetAddress inaddr, int j)
        throws IOException {
      return factory.createSocket( s, i, inaddr, j);
    }
    public Socket createSocket( String s, int i) throws IOException {
      return factory.createSocket( s, i);
    }
    public String[] getDefaultCipherSuites() {
      return factory.getSupportedCipherSuites();
    }
    public String[] getSupportedCipherSuites() {
      return factory.getSupportedCipherSuites();
    }
  }


Finally you should install the SocketFactory provider like this:

Security.setProperty( "ssl.SocketFactory.provider", "DummySSLSocketFactory");


You should execute this code before creating any JavaMail sessions. Also, don't forget to make the DummySSLSocketFactory class visible to your code.

[edit] Week 7 Aug 4

During last week, I talked to Dr. Guo. I explained him what I have in mind and luckily he likes my idea. Then I started working on high level architecture of the project. I came out with a general architecture design. I also Prospectus description in my 590 wiki page

[edit] Week 8 Aug 11

JavaMail

In JavaMail you'll find APIs and provider implementations allowing you to develop fully functional email client applications. "Email client applications" invokes thoughts of Microsoft Outlook; you could write your own Outlook replacement. But an email client need not reside on a client machine at all. Indeed, it could be a servlet or an EJB running on a remote server, providing end-user access to email via a Web browser. Think of Hotmail (yes, you could write your own version of Hotmail too). Or you could avoid a user interface altogether.


Setup

If you use Java 2 Platform, Enterprise Edition (J2EE) 1.3, you're in luck: it includes JavaMail, so no additional setup is required. If, however, you're running Java 2 Platform, Standard Edition (J2SE) 1.1.7 and upwards, and you want email capability for your applications, download and install the following:

  • JavaMail
  • JavaBeans Activation Framework

To install, simply unzip the downloaded files and add the contained jar files to your classpath.


Receive email via POP3

This example shows how to receive an email message via POP3.

mport javax.mail.*;
import javax.mail.internet.*;
import java.util.*;
import java.io.*;
/**
  * A simple email receiver class.
  */
public class SimpleReceiver
{
  /**
    * Main method to receive messages from the mail server specified
    * as command line arguments.
    */
  public static void main(String args[])
  {
    try
    {
      String popServer=args[0];
      String popUser=args[1];
      String popPassword=args[2];
      receive(popServer, popUser, popPassword);
    }
    catch (Exception ex)
    {
    }
    System.exit(0);
  }
/**
    * "receive" method to fetch messages and process them.
    */
  public static void receive(String popServer, String popUser
   , String popPassword)
  {
    Store store=null;
    Folder folder=null;
    try
    {
      // -- Get hold of the default session --
      Properties props = System.getProperties();
      Session session = Session.getDefaultInstance(props, null);
      // -- Get hold of a POP3 message store, and connect to it --
      store = session.getStore("pop3");
      store.connect(popServer, popUser, popPassword);
      
      // -- Try to get hold of the default folder --
      folder = store.getDefaultFolder();
      if (folder == null) throw new Exception("No default folder");
      // -- ...and its INBOX --
      folder = folder.getFolder("INBOX");
      if (folder == null) throw new Exception("No POP3 INBOX");
      // -- Open the folder for read only --
      folder.open(Folder.READ_ONLY);
      // -- Get the message wrappers and process them --
      Message[] msgs = folder.getMessages();
      for (int msgNum = 0; msgNum < msgs.length; msgNum++)
      {
        printMessage(msgs[msgNum]);
      }
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
    finally
    {
      // -- Close down nicely --
      try
      {
        if (folder!=null) folder.close(false);
        if (store!=null) store.close();
      }
      catch (Exception ex2) {ex2.printStackTrace();}
    }
  }
Personal tools