1 45 package groovy.text; 46 47 import groovy.lang.*; 48 49 import java.io.IOException ; 50 import java.io.PrintWriter ; 51 import java.io.Reader ; 52 import java.io.StringWriter ; 53 import java.io.Writer ; 54 import java.security.AccessController ; 55 import java.security.PrivilegedAction ; 56 import java.util.Map ; 57 58 import org.codehaus.groovy.control.CompilationFailedException; 59 60 61 65 public class GStringTemplateEngine extends TemplateEngine { 66 69 public Template createTemplate(final Reader reader) throws CompilationFailedException, ClassNotFoundException , IOException { 70 return new GStringTemplate(reader); 71 } 72 73 private static class GStringTemplate implements Template { 74 final Closure template; 75 76 95 public GStringTemplate(final Reader reader) throws CompilationFailedException, ClassNotFoundException , IOException { 96 final StringBuffer templateExpressions = new StringBuffer ("package groovy.tmp.templates\nclass C { getTemplate() { { |out| out << \""); 97 boolean writingString = true; 98 99 while(true) { 100 int c = reader.read(); 101 102 if (c == -1) break; 103 104 if (c == '<') { 105 c = reader.read(); 106 107 if (c == '%') { 108 c = reader.read(); 109 110 if (c == '=') { 111 parseExpression(reader, writingString, templateExpressions); 112 writingString = true; 113 continue; 114 } else { 115 parseSection(reader, writingString, templateExpressions); 116 writingString = false; 117 continue; 118 } 119 } else { 120 appendCharacter('<', templateExpressions, writingString); 121 writingString = true; 122 } 123 } else if (c == '"') { 124 appendCharacter('\\', templateExpressions, writingString); 125 writingString = true; 126 } 127 128 appendCharacter((char)c, templateExpressions, writingString); 129 writingString = true; 130 } 131 132 if (writingString) { 133 templateExpressions.append("\""); 134 } 135 136 templateExpressions.append("}.asWritable()}}"); 137 138 140 final ClassLoader parentLoader = getClass().getClassLoader(); 141 final GroovyClassLoader loader = 142 (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction () { 143 public Object run() { 144 return new GroovyClassLoader(parentLoader); 145 } 146 }); 147 final Class groovyClass = loader.parseClass(new GroovyCodeSource(templateExpressions.toString(), "C", "x")); 148 149 try { 150 final GroovyObject object = (GroovyObject) groovyClass.newInstance(); 151 152 this.template = (Closure)object.invokeMethod("getTemplate", null); 153 } catch (InstantiationException e) { 154 throw new ClassNotFoundException (e.getMessage()); 155 } catch (IllegalAccessException e) { 156 throw new ClassNotFoundException (e.getMessage()); 157 } 158 } 159 160 private static void appendCharacter(final char c, 161 final StringBuffer templateExpressions, 162 final boolean writingString) 163 { 164 if (!writingString) { 165 templateExpressions.append("out << \""); 166 } 167 168 templateExpressions.append(c); 169 } 170 171 181 private static void parseSection(final Reader reader, 182 final boolean writingString, 183 final StringBuffer templateExpressions) 184 throws IOException 185 { 186 if (writingString) { 187 templateExpressions.append("\"; "); 188 } 189 190 while (true) { 191 int c = reader.read(); 192 193 if (c == -1) break; 194 195 if (c =='%') { 196 c = reader.read(); 197 198 if (c == '>') break; 199 } 200 201 templateExpressions.append((char)c); 202 } 203 204 templateExpressions.append("; "); 205 } 206 207 215 private static void parseExpression(final Reader reader, 216 final boolean writingString, 217 final StringBuffer templateExpressions) 218 throws IOException 219 { 220 if (!writingString) { 221 templateExpressions.append("out << \""); 222 } 223 224 templateExpressions.append("${"); 225 226 while (true) { 227 int c = reader.read(); 228 229 if (c == -1) break; 230 231 if (c =='%') { 232 c = reader.read(); 233 234 if (c == '>') break; 235 } 236 237 templateExpressions.append((char)c); 238 } 239 240 templateExpressions.append('}'); 241 } 242 243 public Writable make() { 244 return make(null); 245 } 246 247 public Writable make(final Map map) { 248 final Closure delegatedClosure = (Closure)this.template.clone(); 249 250 delegatedClosure.setDelegate(new Binding(map)); 251 252 return new Writable() { 253 256 public Writer writeTo(final Writer writer) throws IOException { 257 delegatedClosure.call(new Object [] {new PrintWriter (writer)}); 258 259 return writer; 260 } 261 262 265 public String toString() { 266 final StringWriter stringWriter = new StringWriter (); 267 268 try { 269 writeTo(stringWriter); 270 271 return stringWriter.toString(); 272 } catch (final IOException e) { 273 return e.toString(); 274 } 275 } 276 277 }; 278 } 279 } 280 } 281 | Popular Tags |