package tk.eclipse.plugin.jspeditor.compiler;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This compiler converts the JSP source code to the Java code
* to make code completion in the scriptlet / expression.
* <p>
* <strong>Note:</strong> <code>compile()</code> is not thread safe.
*
* @author Naoki Takezoe
* @since 2.0.3
*/
public class JSPCompiler {
private static final int NONE = 0;
private static final int LT = 1;
private static final int PARCENT = 2;
private static final int SCRIPT = 3;
private static final int END = 4;
private static final Pattern IMPORT_PATTERN
= Pattern.compile("<%@\\s*page.+?import\\s*=\\s*\"(.+?)\"");
private static final Pattern USEBEAN_PATTERN
= Pattern.compile("<jsp:useBean.+?>", Pattern.DOTALL);
/**
* Do compile. This method is not thread safe.
*
* @param source the raw JSP source code
* @return the compile result
*/
public static CompileResult compile(String source){
StringBuffer header = new StringBuffer();
Matcher matcher = IMPORT_PATTERN.matcher(source);
while(matcher.find()){
String[] imports = matcher.group(1).split(",");
for(int i=0;i<imports.length;i++){
String trimedImport = imports[i].trim();
if(trimedImport.length()!=0){
header.append("import ").append(trimedImport).append(";\n");
}
}
}
header.append("public class _xxx {\n");
header.append("public static void doService() throws Exception {\n");
// implicit objects
header.append("javax.servlet.http.HttpServletRequest request = null;\n");
header.append("javax.servlet.http.HttpServletResponse response = null;\n");
header.append("javax.servlet.http.HttpServletSession session = null;\n");
header.append("javax.servlet.jsp.JspWriter out = null;\n");
header.append("javax.servlet.ServletContext application = null;\n");
header.append("javax.servlet.ServletConfig config = null;\n");
header.append("javax.servlet.jsp.HttpJspPage page = null;\n");
header.append("javax.servlet.jsp.PageContext pageContext = null;\n");
header.append("java.lang.Exception exception = null;\n");
// jsp:useBean
matcher = USEBEAN_PATTERN.matcher(source);
while(matcher.find()){
String useBean = matcher.group();
String id = getAttibuteValue(useBean, "id");
String type = getAttibuteValue(useBean, "class");
if(id!=null && type!=null){
header.append(type + " " + id + " = null;\n");
}
}
StringBuffer sb = new StringBuffer();
int flag = NONE;
for(int i=0;i<source.length();i++){
char c = source.charAt(i);
if(flag==NONE && c=='<'){
flag = LT;
sb.append(' ');
} else if(flag==LT){
if(c=='%'){
flag = PARCENT;
} else {
flag = NONE;
}
sb.append(' ');
} else if(flag==PARCENT){
if(c=='@'){
flag = NONE;
sb.append(' ');
} else if(c=='='){
flag = SCRIPT;
sb.append(' ');
} else {
flag = SCRIPT;
sb.append(c);
}
} else if(flag==SCRIPT){
if(c=='%'){
flag = END;
} else {
sb.append(c);
}
} else if(flag==END){
if(c=='>'){
flag = NONE;
sb.append(" ");
} else {
flag = SCRIPT;
sb.append('%');
sb.append(c);
}
} else if(c=='\n' || c=='\r' || c=='\t'){
sb.append(c);
} else {
sb.append(' ');
}
}
return new CompileResult(header.toString(), sb.toString(), "}}");
}
private static String getAttibuteValue(String source, String name){
Pattern pattern = Pattern.compile(
"\\s+" + name + "\\s*?=\\s*?\"(.+?)\"", Pattern.DOTALL);
Matcher matcher = pattern.matcher(source);
if(matcher.find()){
return matcher.group(1);
}
return null;
}
}