Name:

SE550 midterm exam: Autumn 2003-2004

Answer all questions.

Time allowed: 2 hours

Total number of points: 100

Email Lookup server

Some questions will refer to an Email Lookup server. It is defined here.

public class EmailLookupServer implements Runnable {

    public static void main (final String[] args) throws IOException {        
        final ServerSocket sSocket = new ServerSocket (2000);
        while (true) {
            final Socket socket = sSocket.accept ();
            final EmailLookupServer server = new EmailLookupServer (socket);
            server.start ();
        }
    }

    final static HashMap emails = new HashMap ();
    final static HashMap names = new HashMap ();

    final Socket socket;
    final PrintWriter out;
    final BufferedReader in;
    final Thread thread;

    EmailLookupServer (final Socket socket) throws IOException {
        this.socket = socket;
        this.out = new PrintWriter (socket.getOutputStream (), true);
        this.in = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
        this.thread = new Thread (this);
    }

    public void start () { thread.start (); }

    public void run () {
        try {
            String line = in.readLine (); 
            while (line != null && !line.equals ("QUIT")) {
                if (line.startsWith ("GET EMAIL ")) { getEmail (line.substring (10)); } 
                else if (line.startsWith ("GET NAME ")) { getName (line.substring (9)); } 
                else if (line.equals ("NEW")) { newNameEmail (); } 
                else { error (); }
                line = in.readLine ();
            }
        } catch (final IOException ex) {
        } finally {
            try { out.close (); in.close (); socket.close (); } 
            catch (final IOException ex) { }
        }
    }

Email Lookup server continued

    void getEmail (String name) throws IOException {
        String result = (String)(emails.get (name));
        if (result == null) { out.println ("NO SUCH NAME"); }
        else { out.println ("EMAIL: " + result); }
    }

    void getName (String email) throws IOException {
        String result = (String)(names.get (email));
        if (result == null) { out.println ("NO SUCH EMAIL"); }
        else { out.println ("NAME: " + result); }
    }

    void newNameEmail () throws IOException {
        String name = in.readLine ();
        String email = in.readLine ();
        if (name == null || email == null) { error (); return; }
        else if (emails.containsKey (name)) { out.println ("OLD NAME"); }
        else if (names.containsKey (email)) { out.println ("OLD EMAIL"); }
        else { emails.put (name, email); names.put (email, name); out.println ("OK"); }
    }

    void error () throws IOException { out.println ("ERROR"); }

}

Email Lookup client

Some questions will refer to an Email Lookup client. It is defined here.

public class EmailLookupClient {

    public static void main (final String[] args) {

        try {
            final Socket socket = new Socket (args[0], 2000);
            final PrintWriter out = new PrintWriter (socket.getOutputStream (), true);
            final BufferedReader in = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
            for (int i=1; i<args.length; i++) {
                out.println ("GET EMAIL " + args[i]);
                String line = in.readLine ();
                if (line == null) { System.err.println ("Protocol error"); }
                else if (line.startsWith ("EMAIL: ")) { System.out.println ("Email for " + args[i] + " is " + line.substring (7)); }
                else if (line.equals ("NO SUCH NAME")) { System.out.println ("Unknown name " + args[i]); }
                else { System.err.println ("Protocol error"); }
            }
            out.println ("QUIT");
            out.close ();
            in.close ();
            socket.close ();
        } catch (final IOException ex) {
            System.err.println ("Network error: " + ex);
            System.exit (1);
        }
    }

}

Email Lookup Response parser

options { static=false; }
PARSER_BEGIN (EmailLookupResponseParser)
public class EmailLookupResponseParser {
    public void handleEmailResponse (String email) { /* code for a EMAIL response */ }
    public void handleErrorResponse () { /* code for an ERROR response */ }
    public void handleNameResponse (String name) { /* code for a NAME response */ }
    public void handleOKResponse () { /* code for an OK response */ }
    public void handleOldEmailResponse () { /* code for an OLD EMAIL response */ }
    public void handleOldNameResponse () { /* code for an OLD NAME response */ }
}
PARSER_END (EmailLookupResponseParser)

TOKEN : {
  <OLD: "OLD">
| <ERROR: "ERROR">
| <OK: "OK">
| <EMAIL: "EMAIL">
| <NAME: "NAME">
| <COLON: ":">
| <CRLF: "\n" | "\r" | "\n\r">
| <SPACE: " ">
| <STRING: ( ~["\n","\r"] )+>
}

Email Lookup Response parser continued

void response () : {} {
    nameResponse () | emailResponse () | okResponse () | 
    errorResponse () | oldResponse ()
}

void nameResponse () : {
    String name;
}{
    <NAME> <COLON> name = string () <CRLF>
    { handleNameResponse (name); }
}

void emailResponse () : {
    String email;
}{
    <EMAIL> <COLON> email = string () <CRLF>
    { handleEmailResponse (email); }
}

void oldResponse () : {} {
    <OLD> (
      <NAME> <CRLF>
      { handleOldNameResponse (); }
    | <EMAIL> <CRLF> 
      { handleOldEmailResponse (); }
    )
}

void okResponse () : {} {
    <OK> <CRLF>
    { handleOKResponse (); }
}

void errorResponse () : {} {
    <ERROR> <CRLF>
    { handleErrorResponse (); }
}

String string () : {
    Token t;
}{
    t = <STRING>
    { return t.image; }
}

Question 1 (10 points)

Give a one- or two-sentence answer to each of the following:

a) What is a proxy?

b) Why does a programmer designing a distributed application need to be aware of proxies?

c) What is the difference between a proxy and a network address translator?

d) Why does a programmer designing a distributed application need to be aware of network address translation?

Question 2 (10 points)

Assume that on machine server the following command is run:

    java EmailLookupServer

and that on machine client the following command is run:

    java EmailLookupClient server Fred

What messages are sent between the client and the server (assuming no network problems)?

Question 2 continued

Question 3 (10 points)

If a client sends the following requests in order to the EmailLookupServer, what responses will be returned?

NEW
Fred
ff@foo.com





GET NAME ff@foo.com





GET EMAIL Fred





NEW
Wilma
wf@foo.com





GET EMAIL Wilma





NEW
Wilma
oops@foo.com





GET EMAIL: Wilma





QUIT

Question 4 (20 points)

The client code only allows users to look up email addresses and doesn't allow addresses to be added.

Write a client which allows users to add email addresses. This should send a NEW message, a GET NAME message (to make sure the address was added) and a QUIT message. It should print the messages "Name=name." and "Email=email." if the address was added succesfully. It should print "Oh dear..." if an error occurred.

public class CounterSetClient {

    public static void main (final String[] args) {

        try {
            final Socket socket = new Socket (args[0], 2000);
            final String name = args[1];
            final String email = args[2];
            final PrintWriter out = new PrintWriter (socket.getOutputStream (), true);
            final BufferedReader in = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
            do (name, email, in, out);
            out.close ();
            in.close ();
            socket.close ();
        } catch (final IOException ex) {
            System.err.println ("Network error: " + ex);
            System.exit (1);
        }
    }

    static void do (String name, String email, BufferedReader in, PrintWriter out) throws IOException {

        Your code starts here

Question 4 continued

Question 5 (20 points)

Give two grammars for the protocol which is used by the EmailLookup clients and server.

a) Your first grammar should define a nonterminal <request>, which defines the language of requests sent by the clients.

Question 5 continued

b) Your second grammar should define a nonterminal <response>, which defines the language of responses sent by the server.

Question 6 (20 points)

The JavaCC parser EmailResponseParser gives a parser for requests. Write a parser for requests.

options { static=false; }
PARSER_BEGIN (EmailLookupRequestParser)
public class EmailLookupRequestParser {
    public void handleGetEmailRequest (String name) { /* code for a GET EMAIL request */ }
    public void handleGetNameRequest (String email) { /* code for a GET NAME request */ }
    public void handleNewRequest (String name, String email) { /* code for a NEW request */ }
    public void handleQuitRequest () { /* code for a QUIT request */ }
}
PARSER_END (EmailLookupRequestParser)

TOKEN : {
  <QUIT: "QUIT">
| <NEW: "NEW">
| <GET: "GET">
| <EMAIL: "EMAIL">
| <NAME: "NAME">
| <CRLF: "\n" | "\r" | "\n\r">
| <SPACE: " ">
| <STRING: ( ~["\n","\r"] )+>
}

String string () : {
    Token t;
}{
    t = <STRING>
    { return t.image; }
}

// Some productions go here

Question 6 continued

Question 7 (10 points)

Consider the following class definition:

class User {
  String email;
  String name;
  User (String email, String name) {
    this.email = email; this.name = name;
  }
}

a) Write the Java code which could generate the following XML serialization:

  <Object class="User" id="handle1">
    <String value="ff@foo.com">
    <String value="Fred">
  </Object>

Question 7 continued

b) Write the XML which is sent when the following code is executed:

  User foo = new User ("ff@foo.com", "Fred");
  User bar = new User ("ff@foo.com", "Fred");
  xmlSerializer.writeObject (foo);
  xmlSerializer.writeObject (bar);
  foo = new User ("ff@blah.com", "Fred");
  bar.email = "ff@blah.com";
  xmlSerializer.writeObject (foo);
  xmlSerializer.writeObject (bar);

Worksheet

You can use this sheet as scrap paper.

Worksheet

You can use this sheet as scrap paper.