Fibonacci Thread


import java.net.*;
import java.io.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import org.apache.xerces.parsers.*;
import java.util.*;
import java.math.*;


public class FibonacciGenerator implements Runnable {

  Socket client;

  public FibonacciGenerator(Socket client) {
    this.client = client; 
  }

  public void run() {
    
    try {
      InputStream in = client.getInputStream();
      Writer out = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
      
      // We don't really care about the HTTP header so read and discard it.
      // Blank line ends the headers. BufferedReader would be easier
      // but I don't want to commit to an encoding just yet.
      // Furthermore it's buggy. 
      boolean done = false;
      while (!done) {
        int c = in.read(); 
        switch (c) {
          case '\r':
            c = in.read();
            if (c == '\r') {
              done = true;
            }
            else if (c == '\n') {
              int c1 = in.read();
              int c2 = in.read();
              if (c1 == '\r' && c2 == '\n') done = true;
            }            
            continue;
          case '\n':
            c = in.read();
            if (c == '\n') done = true;
            continue;
          case -1:  
            fault("Unexpected End of Stream", 2);
            return;
          default:
            continue;
        }
      }
      
      
      InputSource source = new InputSource(in);
      DOMParser parser = new DOMParser();
      parser.parse(source); 
      Document document = parser.getDocument();
      
      // Example invocation 
      /*
      <?xml version="1.0"?>
      <methodCall>
        <methodName>getFibonacci</methodName>
        <params>
          <param>
            <value><i4>4</i4></value>
          </param>
        </params>
      </methodCall>

      */
      
      Element methodCall = document.getDocumentElement();
      if (!methodCall.getTagName().equals("methodCall")) {
        fault("Root element must be methodCall", 1); 
        return;
      }
      
      NodeList methodNames = methodCall.getElementsByTagName("methodName");
      if (methodNames.getLength() != 1) {
        fault("There must be exactly one method name element", 1);
        return; 
      }
      
      Node methodName = methodNames.item(0).getFirstChild();
      if (methodName == null || methodName.getNodeType() != Node.TEXT_NODE ) {
        fault("No method name", 1);
        return;
      } 
      
      Text methodNameText = (Text) methodName;
      if (!methodNameText.getData().trim().equals("Fibonacci")) {
        fault("Unrecognized method name: " + methodNameText.getData(), 1); 
        return;
      }
      
      NodeList paramsList = methodCall.getElementsByTagName("params");
      if (paramsList.getLength() != 1) {
        fault("There must be exactly one params element", 1); 
        return;
      }
            
      Element params = (Element) paramsList.item(0);
      NodeList paramList = params.getElementsByTagName("param");
      if (paramList.getLength() != 1) {
        fault("There must be exactly one param element", 1);
        return; 
      }
      
      Element param = (Element) paramList.item(0);
      NodeList valueList = param.getElementsByTagName("value");
      if (valueList.getLength() != 1) {
        fault("There must be exactly one value element", 1); 
        return;
      }
      
      Element value = (Element) valueList.item(0);
      NodeList intList = value.getChildNodes();
      if (intList.getLength() != 1) {
        fault("There must be exactly one int or i4 element", 1);
        return; 
      }
      
      String intString = intList.item(0).getFirstChild().getNodeValue();
      System.out.println("Int string: " + intString);
      int index = 0;
      try {
        index = Integer.parseInt(intString); 
      }      
      catch(NumberFormatException e) {
        fault("Contents of " + intList.item(0).getNodeName() + " are not an integer.", 1);
        return;
      }
      
      // finally we're ready to calculate the Fibonacci number
      BigInteger fibonacci = calculateFibonacci(index);
      
      // now write out the result

      
      String result ="<?xml version=\"1.0\"?>\r\n"
       + "<methodResponse>\r\n"
       + "  <params>\r\n"
       + "    <param>\r\n"
       + "      <value><string>" + fibonacci + "</string></value>"
       + "    </param>\r\n"
       + "  </params>\r\n"
       + "</methodResponse>\r\n";
       
      out.write("HTTP/1.1 200 OK\r\n");
      out.write("Connection: close\r\n");
      out.write("Content-Type: text/xml\r\n");
      out.write("Content-length: " + result.length() + "\r\n");
      out.write("Date: " + (new Date()).toString() + "\r\n");
      out.write("\r\n");
      out.write(result);
      out.flush();
      client.close();
      
    }
    catch (SAXException e) {
      System.err.println(e); 
    }  
    catch (IOException e) {
      System.err.println(e); 
    }  
    
  }

  private void fault(String errorMessage, int code)
   throws IOException {
    
    
    System.out.println("Fault: " + errorMessage);
    
    String response = "<?xml version=\"1.0\"?>\r\n"
     + "<methodResponse>\r\n" 
     + "  <fault>\r\n"
     + "    <value>\r\n"
     + "      <struct>\r\n"
     + "        <member>\r\n"
     + "          <name>faultCode</name>\r\n"
     + "          <value><int>" + code + "</int></value>\r\n"
     + "        </member>\r\n"
     + "        <member>\r\n"
     + "          <name>faultString</name>\r\n"
     + "          <value><string>" + errorMessage + "</string></value>\r\n"
     + "        </member>\r\n"
     + "      </struct>\r\n"
     + "    </value>\r\n"
     + "  </fault>\r\n"
     + "</methodResponse>\r\n";
                      
    String header = "HTTP/1.1 200 OK\r\n"      
     + "Connection: close\r\n"
     + "Content-Length: " + response.length() + "\r\n"
     + "Content-Type: text/xml\r\n"
     + "Date: " + new Date() + "\r\n";

    System.out.println(header);
    System.out.println();
    System.out.flush();

    Writer out = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
     
    System.out.println(response);
    out.write(header);
    out.write("\r\n");
    out.write(response);
    out.flush();
    client.close();
      
  } 
  
  private static Vector cache = new Vector();

  public static BigInteger calculateFibonacci(int index) {
    
    if (index < 0) {
      throw new IllegalArgumentException("Index must be non-negative"); 
    }
    
    BigInteger low  = BigInteger.ZERO;
    BigInteger high = BigInteger.ONE;      
      
    for (int i = 0; i <= index; i++) {
      BigInteger temp = high;
      high = high.add(low);
      low = temp;
    }  
    return low;  
    
  }
  

}

Previous | Next | Top | Cafe con Leche

Copyright 2000 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified March 4, 2000