views:

314

answers:

4

After several hours of working on porting this program over, it appears to finally be in a working state. However, I was wondering if anyone knew of a better way or more complete way of porting Java servlets over into Python. The beginning of the Python script contains a lot of support code to make it easier to port the program line-by-line directly into Python. Does anyone know of a better way to go about this?


Java

// --------------------------------------------------------
// File: Hello.java
// Description: A simple "Hello World" servlet
// --------------------------------------------------------

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import sun.servlet.http.HttpServer;

public class Hello extends HttpServlet {

  int count;

  public void service(HttpServletRequest request, 
         HttpServletResponse response) throws ServletException, IOException {

    // setup response

    response.setContentType("text/html");
    PrintWriter out = response.getWriter();

    // send response

    out.println("<html><body>");
    out.println("<h5>Stephen Paul Chappell (SPC)</h5>");
    out.println("<h5>:) (ZTD) Zero The Dragon :(</h5>");
    String name = request.getParameter("NAME");
    if (name != null && !name.equals("")) {
      out.println("<h2>Hello, " + name + "</h2>");
    } else {
      out.println();
      if (name != null && name.equals("")) {
        out.println("  <h2>You didn't enter your name. Please enter your name. </h2>");
      } else {
        out.println("  <h2>What's your name? </h2>");
      }
      out.println("  <hr>");
      out.println("  <form action=\"http://127.0.0.1:8080/servlet/Hello\"&gt;");
      out.println();
      out.println("    Enter your name: <input type=\"text\" name=\"NAME\" value=\"Fred\"><br>");
      out.println("    <input type=\"submit\" value=\"Click for greeting\">");
      out.println();
      out.println("  </form>");
    }
    String color = request.getParameter("FAVCOLOR");
    if (color != null) {
      out.println("<h2>Why, " + color + " is my favorite color too!</h2>");
    }

    count++;
    out.println("This page has been hit " + count + " time(s).");

    out.print("</body></html>");
  }

  // start web server
  public static void main(String[] args) throws Exception {
    HttpServer.main(args);
  }
}

Python

import urllib.parse
import http.server
import cgitb
import sys
import io

################################################################################

class HttpServlet(http.server.BaseHTTPRequestHandler):

    __debug = False

    @staticmethod
    def debug(value):
        HttpServlet.__debug = value

    def do_GET(self):
        if self.path == '/favicon.ico':
            self.send_error(404)
            return
        request = HttpServletRequest(self.path)
        response = HttpServletResponse()
        try:
            self.service(request, response)
        except Exception:
            if HttpServlet.__debug:
                self.send_response(500)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                klass, value, trace = sys.exc_info()
                html = cgitb.html((klass, value, trace.tb_next))
                self.wfile.write(html.encode())
            else:
                self.send_error(500)
        else:
            self.send_response(200)
            self.send_header('Content-type', response._type)
            self.end_headers()
            self.wfile.write(response._value)

    def service(self, request, response):
        raise NotImplementedError()

################################################################################

class HttpServletRequest:

    def __init__(self, path):
        query = urllib.parse.urlparse(path).query
        self.__dict = urllib.parse.parse_qs(query, True)

    def getParameter(self, name):
        return self.__dict.get(name, [None])[0]

################################################################################

class HttpServletResponse:

    def __init__(self):
        self.__content_type = 'text/plain'
        self.__print_writer = PrintWriter()

    def setContentType(self, content_type):
        self.__content_type = content_type

    def getWriter(self):
        return self.__print_writer

    @property
    def _type(self):
        return self.__content_type

    @property
    def _value(self):
        return self.__print_writer.getvalue().encode()

################################################################################

class PrintWriter(io.StringIO):

    print = io.StringIO.write

    def println(self, string):
        self.write(string + '\r\n')

################################################################################

class HttpServer(http.server.HTTPServer):

    @staticmethod
    def main(RequestHandlerClass, port=80):
        server = HttpServer(('', port), RequestHandlerClass)
        socket = server.socket.getsockname()
        print('Serving HTTP on', socket[0], 'port', socket[1], '...')
        try:
            server.serve_forever()
        except KeyboardInterrupt:
            print('Keyboard interrupt received: EXITING')
            server.server_close()

################################################################################
################################################################################

## ---------------------------------------------------------
## File: Hello.py
## Description: A simple "Hello World" servlet
## ---------------------------------------------------------

class Hello(HttpServlet):

    count = 0

    def service(self, request, response):

        # Setup for a response.
        response.setContentType('text/html')
        out = response.getWriter()

        # Send an appropriate response.
        out.println('''\
<html>
    <head>
        <title>Java to Python servlet</title>
    </head>
    <body>
        <h5>Stephen Paul Chappell (SPC)</h5>
        <h5>:) (ZTD) Zero The Dragon :(</h5>''')
        name = request.getParameter('NAME')
        if name:
            out.println('''\
        <h2>Hello, {}!</h2>'''.format(name))
        else:
            if name == '':
                out.println('''\
        <h2>You did not enter your name.</h2>
        <h3>Please enter your name.</h3>''')
            else:
                out.println('''\
        <h2>What is your name?</h2>''')
            out.println('''\
        <form>
            <fieldset>
                <legend>About Yourself</legend>
                <label for='NAME'>Enter your name:</label>
                <input id='NAME' name='NAME' type='text' value='John Doe' />
                <br />
                <input type='submit' value='Click me!' />
            </fieldset>
        </form>''')
        color = request.getParameter('FAVCOLOR')
        if color:
            out.println('''\
        <h2>Why, {} is my favorite color too!</h2>'''.format(color))

        Hello.count += 1
        out.println('''\
        This page has been hit {} times.'''.format(Hello.count))

        out.print('''\
    </body>
</html>''')

# Start the web server.
def main():
    HttpServlet.debug(True)
    HttpServer.main(Hello)

################################################################################

if __name__ == '__main__':
    main()

In case anyone is wondering what the purpose of this project is, the original Java program was given as an introductory exercise in freshman-level computer-science course. Since then, it has been about six years since I have worked with Java and am going through the old programs, porting them over to Python for the challenge and learning experience. Porting the servlets are presenting extra difficulties.

+5  A: 

My best suggestion is to not write a line by line port. Python is not Java and you're hamstringing yourself if you're just writing Java style code in the Python language.

Here's a starter for recognizing some of the common differences/mistakes: http://dirtsimple.org/2004/12/python-is-not-java.html

If you're lucky enough to be working with a codebase that contains unit tests, a great way to go about this is to port your unit tests from Java to Python, and then write new python to match the unit tests. If that's not something that you have, then it's much more important to recognize what the software does in Java, and then write Python code that does the same thing. It will almost certainly not be in the same way, at least not at the line-by-line level.

Travis Bradshaw
For whatever reason, my college's filter is not letting me get to dirtsimple.org (uncategorized). I know Python much better than Java (haven't worked with Java for the past six years). That is why I am trying to figure out the best way of porting this old, introductory code to serlets (written for a class) over to Python. It is a challenging exercise that should help me and others to learn more.
Noctis Skytower
Considering the problems you're having with internet filtering, you should consider buying an inexpensive web hosting service that has shell access. Then you can SSH tunnel outside of your college's filter to access the sites that you need. It sucks that your college's filter is hampering your learning, you should definitely bypass it.
Travis Bradshaw
+2  A: 

Not a direct answer but, any good reason to not use something like Webware which offers, among other features (see the Overview):

  • Servlets. Similar to Java servlets, they provide a familiar basis for construction web applications.
Pascal Thivent
Yet another URL the filter is not allowing ... Be thankful for unrestricted internet access (if you have it).
Noctis Skytower
I trust that this is probably the library to use if it were immediately accessible. Thanks for your help! Maybe the admins on this network will approve the link ...
Noctis Skytower
+3  A: 

Isn't this a translation and not a port? :)

I just googled and found java2python as well as a similar SO question.

Anyway ...

Ideally, i think you should understand what you're translating so you can know what to translate and what you shouldn't need to translate. You need a reasonable understanding of both languages to know how constructs in Java relate to the similar in Python and how libraries play roles in the translations.

A direct translation between languages is often not a good approach. I mention this simply because the translated Python in your question isn't very Pythonic. And also because a fair amount of the Python is concerned with the HTTP Server aspects. That isn't the case with the Java code. So to produce a "fair" translation, i would have relied on a Python framework that does for Python what Servlet containers do for Java. Maybe Tornado/Django. My point being, a Java Servlet is wrapped up in a significant set of standards so it makes sense that the Python version follow a similar route, which, at a minimum, probably means WSGI.

nicerobot
+1  A: 

Creating a python webapp in this way is confusing and non pythonic. You might have better success rewriting your app in Django rather than porting it line by line from Java

jbwoot