From 9b2fc0e5a9b501ffba64c313b1cca46347a6258e Mon Sep 17 00:00:00 2001 From: Alexandre Chatiron Date: Fri, 19 Sep 2014 16:59:11 +0800 Subject: [PATCH] Methods should be protected so that they can be used/overidden from outside default package * Add specific method to allow to override the compiler options --- .../src/play/templates/BaseTemplate.java | 2 +- .../src/play/templates/GroovyTemplate.java | 98 ++++++++++++++----- .../templates/GroovyTemplateCompiler.java | 20 ++-- .../src/play/templates/TemplateCompiler.java | 52 +++++----- 4 files changed, 113 insertions(+), 59 deletions(-) diff --git a/framework/src/play/templates/BaseTemplate.java b/framework/src/play/templates/BaseTemplate.java index bff367aa68..3978368bf4 100644 --- a/framework/src/play/templates/BaseTemplate.java +++ b/framework/src/play/templates/BaseTemplate.java @@ -93,7 +93,7 @@ void throwException(Throwable e) { throw new RuntimeException(e); } - abstract Throwable cleanStackTrace(Throwable e); + protected abstract Throwable cleanStackTrace(Throwable e); public static ThreadLocal layout = new ThreadLocal(); public static ThreadLocal> layoutData = new ThreadLocal>(); public static ThreadLocal currentTemplate = new ThreadLocal(); diff --git a/framework/src/play/templates/GroovyTemplate.java b/framework/src/play/templates/GroovyTemplate.java index b5b28976e0..2e80d28469 100644 --- a/framework/src/play/templates/GroovyTemplate.java +++ b/framework/src/play/templates/GroovyTemplate.java @@ -2,6 +2,7 @@ import com.jamonapi.Monitor; import com.jamonapi.MonitorFactory; + import groovy.lang.Binding; import groovy.lang.Closure; import groovy.lang.GroovyClassLoader; @@ -9,6 +10,7 @@ import groovy.lang.GroovyShell; import groovy.lang.MissingPropertyException; import groovy.lang.Script; + import java.io.File; import java.io.FileOutputStream; import java.io.PrintWriter; @@ -23,13 +25,19 @@ import org.codehaus.groovy.control.MultipleCompilationErrorsException; import org.codehaus.groovy.control.Phases; import org.codehaus.groovy.control.SourceUnit; +import org.codehaus.groovy.control.customizers.ImportCustomizer; +import org.codehaus.groovy.control.customizers.SecureASTCustomizer; +import org.codehaus.groovy.control.messages.ExceptionMessage; +import org.codehaus.groovy.control.messages.Message; import org.codehaus.groovy.control.messages.SyntaxErrorMessage; import org.codehaus.groovy.runtime.InvokerHelper; import org.codehaus.groovy.syntax.SyntaxException; import org.codehaus.groovy.tools.GroovyClass; + import play.Logger; import play.Play; import play.Play.Mode; +import play.classloading.ApplicationClassloader; import play.classloading.BytecodeCache; import play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer; import play.data.binding.Unbinder; @@ -61,7 +69,7 @@ public class GroovyTemplate extends BaseTemplate { static final Map safeFormatters = new HashMap(); - + static { safeFormatters.put("csv", new SafeCSVFormatter()); safeFormatters.put("html", new SafeHTMLFormatter()); @@ -75,7 +83,7 @@ public static void registerFormatter(String format, SafeFormatter formatter) static { new GroovyShell().evaluate("java.lang.String.metaClass.if = { condition -> if(condition) delegate; else '' }"); } - + public GroovyTemplate(String name, String source) { super(name, source); } @@ -89,7 +97,7 @@ public static class TClassLoader extends GroovyClassLoader { public TClassLoader() { super(Play.classloader); } - + public Class defineTemplate(String name, byte[] byteCode) { return defineClass(name, byteCode, 0, byteCode.length, Play.classloader.protectionDomain); } @@ -110,6 +118,19 @@ void directLoad(byte[] code) throws Exception { } } } + + /** + * Define the Compiler configuration + * @return the compiler Configuration + */ + protected CompilerConfiguration setUpCompilerConfiguration(){ + CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); + compilerConfiguration.setSourceEncoding("utf-8"); // ouf + return compilerConfiguration; + } + + protected void onCompileEnd(){ + } public void compile() { if (compiledTemplate == null) { @@ -117,14 +138,14 @@ public void compile() { long start = System.currentTimeMillis(); TClassLoader tClassLoader = new TClassLoader(); - // Let's compile the groovy source final List groovyClassesForThisTemplate = new ArrayList(); // ~~~ Please ! - CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); - compilerConfiguration.setSourceEncoding("utf-8"); // ouf + CompilerConfiguration compilerConfiguration = this.setUpCompilerConfiguration(); + CompilationUnit compilationUnit = new CompilationUnit(compilerConfiguration); - compilationUnit.addSource(new SourceUnit(name, compiledSource, compilerConfiguration, tClassLoader, compilationUnit.getErrorCollector())); + compilationUnit.addSource(new SourceUnit(name, compiledSource, compilerConfiguration, tClassLoader, compilationUnit.getErrorCollector())); + Field phasesF = compilationUnit.getClass().getDeclaredField("phaseOperations"); phasesF.setAccessible(true); LinkedList[] phases = (LinkedList[]) phasesF.get(compilationUnit); @@ -175,21 +196,32 @@ public void call(GroovyClass gclass) { } catch (MultipleCompilationErrorsException e) { if (e.getErrorCollector().getLastError() != null) { - SyntaxErrorMessage errorMessage = (SyntaxErrorMessage) e.getErrorCollector().getLastError(); - SyntaxException syntaxException = errorMessage.getCause(); - Integer line = this.linesMatrix.get(syntaxException.getLine()); - if (line == null) { - line = 0; - } - String message = syntaxException.getMessage(); - if (message.indexOf("@") > 0) { - message = message.substring(0, message.lastIndexOf("@")); + Message errorMsg = e.getErrorCollector().getLastError(); + if (errorMsg instanceof SyntaxErrorMessage) { + SyntaxErrorMessage errorMessage = (SyntaxErrorMessage) e.getErrorCollector().getLastError(); + SyntaxException syntaxException = errorMessage.getCause(); + Integer line = this.linesMatrix.get(syntaxException.getLine()); + if (line == null) { + line = 0; + } + String message = syntaxException.getMessage(); + if (message.indexOf("@") > 0) { + message = message.substring(0, message.lastIndexOf("@")); + } + throw new TemplateCompilationException(this, line, message); + } else{ + ExceptionMessage errorMessage = (ExceptionMessage ) e.getErrorCollector().getLastError(); + Exception exception = errorMessage.getCause(); + Integer line = 0; + String message = exception.getMessage(); + throw new TemplateCompilationException(this, line, message); } - throw new TemplateCompilationException(this, line, message); } throw new UnexpectedException(e); } catch (Exception e) { throw new UnexpectedException(e); + } finally{ + this.onCompileEnd(); } } compiledTemplateName = compiledTemplate.getName(); @@ -204,13 +236,20 @@ public String render(Map args) { } } - @Override - protected String internalRender(Map args) { - compile(); + protected Binding setUpBindingVariables(Map args){ Binding binding = new Binding(args); binding.setVariable("play", new Play()); binding.setVariable("messages", new Messages()); binding.setVariable("lang", Lang.get()); + return binding; + } + + @Override + protected String internalRender(Map args) { + compile(); + + Binding binding = this.setUpBindingVariables(args); + // If current response-object is present, add _response_encoding' Http.Response currentResponse = Http.Response.current(); if (currentResponse != null) { @@ -299,7 +338,7 @@ protected String internalRender(Map args) { return null; } - Throwable cleanStackTrace(Throwable e) { + protected Throwable cleanStackTrace(Throwable e) { List cleanTrace = new ArrayList(); for (StackTraceElement se : e.getStackTrace()) { //Here we are parsing the classname to find the file on disk the template was generated from. @@ -406,7 +445,22 @@ public void invokeTag(Integer fromLine, String tag, Map attrs, C TagContext.exitTag(); } + /** + * @deprecated '_' should not be used as an identifier, since it is a reserved keyword from source level 1.8 on + * use {@link #__loadClass} instead + */ + @Deprecated public Class _(String className) throws Exception { + return __loadClass(className); + } + + /** + * Load the class from Pay Class loader + * @param className : the class name + * @return the given class + * @throws Exception + */ + public Class __loadClass(String className) throws Exception { try { return Play.classloader.loadClass(className); } catch (ClassNotFoundException e) { @@ -557,7 +611,7 @@ public Object invokeMethod(String name, Object param) { } } - static boolean isSimpleParam(Class type) { + protected static boolean isSimpleParam(Class type) { return Number.class.isAssignableFrom(type) || type.equals(String.class) || type.isPrimitive(); } } diff --git a/framework/src/play/templates/GroovyTemplateCompiler.java b/framework/src/play/templates/GroovyTemplateCompiler.java index 3ad124568c..61d024429a 100644 --- a/framework/src/play/templates/GroovyTemplateCompiler.java +++ b/framework/src/play/templates/GroovyTemplateCompiler.java @@ -42,7 +42,7 @@ public BaseTemplate compile(BaseTemplate template) { } @Override - String source() { + protected String source() { String source = template.source; // If a plugin has something to change in the template before the compilation @@ -111,7 +111,7 @@ public int compare(String o1, String o2) { } @Override - void head() { + protected void head() { print("class "); //This generated classname is parsed when creating cleanStackTrace. //The part after "Template_" is used as key when @@ -131,7 +131,7 @@ void head() { @Override @SuppressWarnings("unused") - void end() { + protected void end() { for (String n : extensionsClassnames) { println(" } "); } @@ -148,7 +148,7 @@ void end() { */ @Override - void plain() { + protected void plain() { String text = parser.getToken().replace("\\", "\\\\").replaceAll("\"", "\\\\\"").replace("$", "\\$"); if (skipLineBreak && text.startsWith("\n")) { text = text.substring(1); @@ -184,7 +184,7 @@ void plain() { } @Override - void script() { + protected void script() { String text = parser.getToken(); if (text.indexOf("\n") > -1) { String[] lines = parser.getToken().split("\n"); @@ -202,7 +202,7 @@ void script() { } @Override - void expr() { + protected void expr() { String expr = parser.getToken().trim(); print(";out.print(__safeFaster("+expr+"))"); markLine(parser.getLine()); @@ -210,7 +210,7 @@ void expr() { } @Override - void message() { + protected void message() { String expr = parser.getToken().trim(); print(";out.print(__getMessage("+expr+"))"); markLine(parser.getLine()); @@ -218,7 +218,7 @@ void message() { } @Override - void action(boolean absolute) { + protected void action(boolean absolute) { String action = parser.getToken().trim(); if (action.trim().matches("^'.*'$")) { if (absolute) { @@ -241,7 +241,7 @@ void action(boolean absolute) { } @Override - void startTag() { + protected void startTag() { tagIndex++; String tagText = parser.getToken().trim().replaceAll("\r", "").replaceAll("\n", " "); String tagName = ""; @@ -302,7 +302,7 @@ void startTag() { } @Override - void endTag() { + protected void endTag() { String tagName = parser.getToken().trim(); if (tagsStack.isEmpty()) { throw new TemplateCompilationException(template, parser.getLine(), "#{/" + tagName + "} is not opened."); diff --git a/framework/src/play/templates/TemplateCompiler.java b/framework/src/play/templates/TemplateCompiler.java index 1255b0826e..804f4bc540 100644 --- a/framework/src/play/templates/TemplateCompiler.java +++ b/framework/src/play/templates/TemplateCompiler.java @@ -28,23 +28,23 @@ public BaseTemplate compile(VirtualFile file) { return compile(new GroovyTemplate(file.relativePath(), file.contentAsString())); } - StringBuilder compiledSource = new StringBuilder(); - BaseTemplate template; - TemplateParser parser; - boolean doNextScan = true; - TemplateParser.Token state; - Stack tagsStack = new Stack(); - int tagIndex; - boolean skipLineBreak; - int currentLine = 1; - - static class Tag { + protected StringBuilder compiledSource = new StringBuilder(); + protected BaseTemplate template; + protected TemplateParser parser; + protected boolean doNextScan = true; + protected TemplateParser.Token state; + protected Stack tagsStack = new Stack(); + protected int tagIndex; + protected boolean skipLineBreak; + protected int currentLine = 1; + + protected static class Tag { String name; int startLine; boolean hasBody; } - void generate(BaseTemplate template) { + protected void generate(BaseTemplate template) { this.template = template; String source = source(); this.parser = new TemplateParser(source); @@ -113,41 +113,41 @@ void generate(BaseTemplate template) { } - abstract String source(); + protected abstract String source(); - abstract void head(); + protected abstract void head(); - abstract void end(); + protected abstract void end(); - abstract void plain(); + protected abstract void plain(); - abstract void script(); + protected abstract void script(); - abstract void expr(); + protected abstract void expr(); - abstract void message(); + protected abstract void message(); - abstract void action(boolean absolute); + protected abstract void action(boolean absolute); - abstract void startTag(); + protected abstract void startTag(); - abstract void endTag(); + protected abstract void endTag(); - void markLine(int line) { + protected void markLine(int line) { compiledSource.append("// line ").append(line); template.linesMatrix.put(currentLine, line); } - void println() { + protected void println() { compiledSource.append("\n"); currentLine++; } - void print(String text) { + protected void print(String text) { compiledSource.append(text); } - void println(String text) { + protected void println(String text) { compiledSource.append(text); println(); }