[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();
}
}