|
|||||||||||||||||||
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
GStringTemplateEngine.java | 0% | 0% | 0% | 0% |
|
1 |
/* $Id: GStringTemplateEngine.java,v 1.5 2004/06/22 10:06:38 tug Exp $
|
|
2 |
|
|
3 |
Copyright 2004 (C) John Wilson. All Rights Reserved.
|
|
4 |
|
|
5 |
Redistribution and use of this software and associated documentation
|
|
6 |
("Software"), with or without modification, are permitted provided
|
|
7 |
that the following conditions are met:
|
|
8 |
|
|
9 |
1. Redistributions of source code must retain copyright
|
|
10 |
statements and notices. Redistributions must also contain a
|
|
11 |
copy of this document.
|
|
12 |
|
|
13 |
2. Redistributions in binary form must reproduce the
|
|
14 |
above copyright notice, this list of conditions and the
|
|
15 |
following disclaimer in the documentation and/or other
|
|
16 |
materials provided with the distribution.
|
|
17 |
|
|
18 |
3. The name "groovy" must not be used to endorse or promote
|
|
19 |
products derived from this Software without prior written
|
|
20 |
permission of The Codehaus. For written permission,
|
|
21 |
please contact info@codehaus.org.
|
|
22 |
|
|
23 |
4. Products derived from this Software may not be called "groovy"
|
|
24 |
nor may "groovy" appear in their names without prior written
|
|
25 |
permission of The Codehaus. "groovy" is a registered
|
|
26 |
trademark of The Codehaus.
|
|
27 |
|
|
28 |
5. Due credit should be given to The Codehaus -
|
|
29 |
http://groovy.codehaus.org/
|
|
30 |
|
|
31 |
THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
|
|
32 |
``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
|
|
33 |
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
34 |
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
35 |
THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
36 |
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
37 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
38 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
39 |
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
40 |
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
41 |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
42 |
OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
43 |
|
|
44 |
*/
|
|
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 |
/**
|
|
62 |
* @author tug@wilson.co.uk
|
|
63 |
*
|
|
64 |
*/
|
|
65 |
public class GStringTemplateEngine extends TemplateEngine { |
|
66 |
/* (non-Javadoc)
|
|
67 |
* @see groovy.text.TemplateEngine#createTemplate(java.io.Reader)
|
|
68 |
*/
|
|
69 | 0 |
public Template createTemplate(final Reader reader) throws CompilationFailedException, ClassNotFoundException, IOException { |
70 | 0 |
return new GStringTemplate(reader); |
71 |
} |
|
72 |
|
|
73 |
private static class GStringTemplate implements Template { |
|
74 |
final Closure template; |
|
75 |
|
|
76 |
/**
|
|
77 |
* Turn the template into a writable Closure
|
|
78 |
* When executed the closure evaluates all the code embedded in the
|
|
79 |
* template and then writes a GString containing the fixed and variable items
|
|
80 |
* to the writer passed as a paramater
|
|
81 |
*
|
|
82 |
* For example:
|
|
83 |
*
|
|
84 |
* '<%= "test" %> of expr and <% test = 1 %>${test} script.'
|
|
85 |
*
|
|
86 |
* would compile into:
|
|
87 |
*
|
|
88 |
* { |out| out << "${"test"} of expr and "; test = 1 ; out << "${test} script."}.asWritable()
|
|
89 |
*
|
|
90 |
* @param reader
|
|
91 |
* @throws CompilationFailedException
|
|
92 |
* @throws ClassNotFoundException
|
|
93 |
* @throws IOException
|
|
94 |
*/
|
|
95 | 0 |
public GStringTemplate(final Reader reader) throws CompilationFailedException, ClassNotFoundException, IOException { |
96 | 0 |
final StringBuffer templateExpressions = new StringBuffer("class C { getTemplate() { { |out| out << \""); |
97 | 0 |
boolean writingString = true; |
98 |
|
|
99 | 0 |
while(true) { |
100 | 0 |
int c = reader.read();
|
101 |
|
|
102 | 0 |
if (c == -1) break; |
103 |
|
|
104 | 0 |
if (c == '<') {
|
105 | 0 |
c = reader.read(); |
106 |
|
|
107 | 0 |
if (c == '%') {
|
108 | 0 |
c = reader.read(); |
109 |
|
|
110 | 0 |
if (c == '=') {
|
111 | 0 |
parseExpression(reader, writingString, templateExpressions); |
112 | 0 |
writingString = true;
|
113 | 0 |
continue;
|
114 |
} else {
|
|
115 | 0 |
parseSection(reader, writingString, templateExpressions); |
116 | 0 |
writingString = false;
|
117 | 0 |
continue;
|
118 |
} |
|
119 |
} else {
|
|
120 | 0 |
appendCharacter('<', templateExpressions, writingString); |
121 | 0 |
writingString = true;
|
122 |
} |
|
123 | 0 |
} else if (c == '"') { |
124 | 0 |
appendCharacter('\\', templateExpressions, writingString); |
125 | 0 |
writingString = true;
|
126 |
} |
|
127 |
|
|
128 | 0 |
appendCharacter((char)c, templateExpressions, writingString);
|
129 | 0 |
writingString = true;
|
130 |
} |
|
131 |
|
|
132 | 0 |
if (writingString) {
|
133 | 0 |
templateExpressions.append("\"");
|
134 |
} |
|
135 |
|
|
136 | 0 |
templateExpressions.append("}.asWritable()}}");
|
137 |
|
|
138 |
// System.out.println(templateExpressions.toString());
|
|
139 |
|
|
140 | 0 |
final ClassLoader parentLoader = getClass().getClassLoader(); |
141 | 0 |
final GroovyClassLoader loader = |
142 |
(GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
|
|
143 | 0 |
public Object run() {
|
144 | 0 |
return new GroovyClassLoader(parentLoader); |
145 |
} |
|
146 |
}); |
|
147 | 0 |
final Class groovyClass = loader.parseClass(new GroovyCodeSource(templateExpressions.toString(), "C", "x")); |
148 |
|
|
149 | 0 |
try {
|
150 | 0 |
final GroovyObject object = (GroovyObject) groovyClass.newInstance(); |
151 |
|
|
152 | 0 |
this.template = (Closure)object.invokeMethod("getTemplate", null); |
153 |
} catch (InstantiationException e) {
|
|
154 | 0 |
throw new ClassNotFoundException(e.getMessage()); |
155 |
} catch (IllegalAccessException e) {
|
|
156 | 0 |
throw new ClassNotFoundException(e.getMessage()); |
157 |
} |
|
158 |
} |
|
159 |
|
|
160 | 0 |
private static void appendCharacter(final char c, |
161 |
final StringBuffer templateExpressions, |
|
162 |
final boolean writingString)
|
|
163 |
{ |
|
164 | 0 |
if (!writingString) {
|
165 | 0 |
templateExpressions.append("out << \"");
|
166 |
} |
|
167 |
|
|
168 | 0 |
templateExpressions.append(c); |
169 |
} |
|
170 |
|
|
171 |
/**
|
|
172 |
* Parse a <% .... %> section
|
|
173 |
* if we are writing a GString close and append ';'
|
|
174 |
* then write the section as a statement
|
|
175 |
*
|
|
176 |
* @param reader
|
|
177 |
* @param writingString
|
|
178 |
* @param templateExpressions
|
|
179 |
* @throws IOException
|
|
180 |
*/
|
|
181 | 0 |
private static void parseSection(final Reader reader, |
182 |
final boolean writingString,
|
|
183 |
final StringBuffer templateExpressions) |
|
184 |
throws IOException
|
|
185 |
{ |
|
186 | 0 |
if (writingString) {
|
187 | 0 |
templateExpressions.append("\"; ");
|
188 |
} |
|
189 |
|
|
190 | 0 |
while (true) { |
191 | 0 |
int c = reader.read();
|
192 |
|
|
193 | 0 |
if (c == -1) break; |
194 |
|
|
195 | 0 |
if (c =='%') {
|
196 | 0 |
c = reader.read(); |
197 |
|
|
198 | 0 |
if (c == '>') break; |
199 |
} |
|
200 |
|
|
201 | 0 |
templateExpressions.append((char)c);
|
202 |
} |
|
203 |
|
|
204 | 0 |
templateExpressions.append("; ");
|
205 |
} |
|
206 |
|
|
207 |
/**
|
|
208 |
* Parse a <%= .... %> expression
|
|
209 |
*
|
|
210 |
* @param reader
|
|
211 |
* @param writingString
|
|
212 |
* @param templateExpressions
|
|
213 |
* @throws IOException
|
|
214 |
*/
|
|
215 | 0 |
private static void parseExpression(final Reader reader, |
216 |
final boolean writingString,
|
|
217 |
final StringBuffer templateExpressions) |
|
218 |
throws IOException
|
|
219 |
{ |
|
220 | 0 |
if (!writingString) {
|
221 | 0 |
templateExpressions.append("out << \"");
|
222 |
} |
|
223 |
|
|
224 | 0 |
templateExpressions.append("${");
|
225 |
|
|
226 | 0 |
while (true) { |
227 | 0 |
int c = reader.read();
|
228 |
|
|
229 | 0 |
if (c == -1) break; |
230 |
|
|
231 | 0 |
if (c =='%') {
|
232 | 0 |
c = reader.read(); |
233 |
|
|
234 | 0 |
if (c == '>') break; |
235 |
} |
|
236 |
|
|
237 | 0 |
templateExpressions.append((char)c);
|
238 |
} |
|
239 |
|
|
240 | 0 |
templateExpressions.append('}'); |
241 |
} |
|
242 |
|
|
243 | 0 |
public Writable make() {
|
244 | 0 |
return make(null); |
245 |
} |
|
246 |
|
|
247 | 0 |
public Writable make(final Map map) {
|
248 | 0 |
final Closure delegatedClosure = (Closure)this.template.clone();
|
249 |
|
|
250 | 0 |
delegatedClosure.setDelegate(new Binding(map));
|
251 |
|
|
252 | 0 |
return new Writable() { |
253 |
/* (non-Javadoc)
|
|
254 |
* @see groovy.lang.Writable#writeTo(java.io.Writer)
|
|
255 |
*/
|
|
256 | 0 |
public Writer writeTo(final Writer writer) throws IOException { |
257 | 0 |
delegatedClosure.call(new Object[] {new PrintWriter(writer)}); |
258 |
|
|
259 | 0 |
return writer;
|
260 |
} |
|
261 |
|
|
262 |
/* (non-Javadoc)
|
|
263 |
* @see java.lang.Object#toString()
|
|
264 |
*/
|
|
265 | 0 |
public String toString() {
|
266 | 0 |
final StringWriter stringWriter = new StringWriter();
|
267 |
|
|
268 | 0 |
try {
|
269 | 0 |
writeTo(stringWriter); |
270 |
|
|
271 | 0 |
return stringWriter.toString();
|
272 |
} catch (final IOException e) {
|
|
273 | 0 |
return e.toString();
|
274 |
} |
|
275 |
} |
|
276 |
|
|
277 |
}; |
|
278 |
} |
|
279 |
} |
|
280 |
} |
|
281 |
|
|