[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index] [Home]

Implementation sketch...


Hi again.

OK, here's the code I've been putting together.  It reads an ordinary
JSP 1.0 source file from stdin, converts it to a valid XML document, and
then invokes the openxml parser on it.  After that, it walks the DOM
tree and spits out a semblance of java code to stdout.

The JSP to XML step requires gnu.regexp 1.0.8 right now. A real
implementation would do this as a well-oiled state machine.  The XML to
Document step requires OpenXML, just like the current gnujsp snapshot.

You need to put "jsp.dtd" (from src/org/gjt/jsp/) in your working
directory or the openxml parser will complain.  (Can anyone explain how
the DOCTYPE directive would best work to find a DTD file that's in the
Java classpath?)

Also, if anyone knows how to turn off the annoying debug from the
openxml parser, be my guest.

command line:
% java XML2Java < file.jsp

Next steps:
- replace crappy regular expression with state machine preparser
- move into org.gjt.jsp package and integrate
- really implement code generation

Wes

import gnu.regexp.*;
import java.io.*;
import org.openxml.parser.*;
import org.w3c.dom.*;

public class XML2Java {
    private static int indent;

    public static void indent() {
	for (int i = 0; i < indent; i++) {
	    System.out.print(' ');
	}
    }


    public static void quoteString(String in, PrintStream out) {
	char c;
	for (int i = 0; i < in.length(); i++) {
	    switch (c = in.charAt(i)) {
	    case '\n':
		out.print("\\n");
		break;
	    case '\r':
		out.print("\\r");
		break;
	    case '\t':
		out.print("\\t");
		break;
	    case '\\':
		out.print("\\\\");
		break;
	    case '"':
		out.print("\\\"");
		break;
	    default:
		out.print(c);
	    }
	}
    }

    public static void walk(Node e) {
	if (e == null) {
	    return;
	}

	if (e instanceof CharacterData) {
	    indent();
	    System.out.print("out.print(\"");
	    quoteString(((CharacterData) e).getData(),System.out);
	    System.out.println("\");");
	} else if (e instanceof Element) {
	    indent();
	    String tagName = ((Element) e).getTagName();
	    if (tagName.equals("jsp:scriptlet")) {
		if (e.hasChildNodes()) {
		   CharacterData c = (CharacterData) e.getFirstChild();
		   System.out.println(c.getData());
		}
	    } else if (tagName.equals("jsp:expression")) {
		if (e.hasChildNodes()) {
		   CharacterData c = (CharacterData) e.getFirstChild();
		   System.out.println("out.print( ( " + c.getData() + ").toString() );");
		}
	    } else {
		System.out.println("// " + ((Element) e).getTagName());
		if (e.hasChildNodes()) {
		    indent += 2;
		    walk(e.getFirstChild());
		    indent -= 2;
		}
	    }
	}

	// Walk siblings
	System.out.println();
	walk(e.getNextSibling());
    }

    public static void main(String[] argv) throws Exception {
	// Read from STDIN, create Document
	
	XMLParser parser = new XMLParser(new StringReader(JSPToXML(System.in)),null);
	Document doc = parser.parseDocument();

	System.out.println("public class xxx extends Servlet {");
	System.out.println("  public void _jspService(...) {");
	indent = 2;
	walk(doc.getDocumentElement());
	System.out.println("  }\n}");
    }

    // JSP --> XML methods

    public static String cdataWrap(String in) {
	return("<![CDATA[" + in + "]]>");
    }
    
    public static String JSPToXML(InputStream in) throws Exception {
	StringBuffer output = new StringBuffer();
	output.append("<!DOCTYPE jsp:body SYSTEM \"file:jsp.dtd\">\n");
	output.append("<jsp:root>");
	
	RE bloat = new RE("(<jsp:(\\w+)(.*?)(?:/>|>(.*?)</jsp:\\1>))" + 
			  "|<%(=|@\\s+)?(.*?)%>",RE.REG_DOT_NEWLINE);
	
	REMatchEnumeration en = bloat.getMatchEnumeration(in);
	StringBuffer b = new StringBuffer();
	while (en.hasMoreMatches(b)) {
	    REMatch m = en.nextMatch();
	    output.append(cdataWrap(b.toString()));
	    b = new StringBuffer();
	    if (!m.toString(1).equals("")) output.append(m);
	    else {
		if (m.toString(5).startsWith("@")) {
		    output.append("<jsp:directive." + m.toString(6) + " />");
		} else if (m.toString(5).equals("=")) {
		    output.append("<jsp:expression>" + cdataWrap(m.toString(6)) + "</jsp:expression>");
		} else if (m.toString(5).equals("!")) {
		    output.append("<jsp:declaration>" + cdataWrap(m.toString(6)) + "</jsp:declaration>");
		} else output.append("<jsp:scriptlet>" + cdataWrap(m.toString(6)) + "</jsp:scriptlet>");
	    }
	}
	output.append(cdataWrap(b.toString()));
	output.append("</jsp:root>");

	return output.toString();
    }
}