KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > groovy > text > GStringTemplateEngine


1 /* $Id: GStringTemplateEngine.java,v 1.6 2004/07/27 14:23:09 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 JavaDoc;
50 import java.io.PrintWriter JavaDoc;
51 import java.io.Reader JavaDoc;
52 import java.io.StringWriter JavaDoc;
53 import java.io.Writer JavaDoc;
54 import java.security.AccessController JavaDoc;
55 import java.security.PrivilegedAction JavaDoc;
56 import java.util.Map JavaDoc;
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     public Template createTemplate(final Reader JavaDoc reader) throws CompilationFailedException, ClassNotFoundException JavaDoc, IOException JavaDoc {
70         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         public GStringTemplate(final Reader JavaDoc reader) throws CompilationFailedException, ClassNotFoundException JavaDoc, IOException JavaDoc {
96             final StringBuffer JavaDoc templateExpressions = new StringBuffer JavaDoc("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 // System.out.println(templateExpressions.toString());
139

140             final ClassLoader JavaDoc parentLoader = getClass().getClassLoader();
141             final GroovyClassLoader loader =
142                 (GroovyClassLoader) AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
143                     public Object JavaDoc run() {
144                         return new GroovyClassLoader(parentLoader);
145                     }
146                 });
147             final Class JavaDoc 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 JavaDoc e) {
154                 throw new ClassNotFoundException JavaDoc(e.getMessage());
155             } catch (IllegalAccessException JavaDoc e) {
156                 throw new ClassNotFoundException JavaDoc(e.getMessage());
157             }
158         }
159         
160         private static void appendCharacter(final char c,
161                                           final StringBuffer JavaDoc templateExpressions,
162                                           final boolean writingString)
163         {
164             if (!writingString) {
165                 templateExpressions.append("out << \"");
166             }
167             
168             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         private static void parseSection(final Reader JavaDoc reader,
182                                         final boolean writingString,
183                                          final StringBuffer JavaDoc templateExpressions)
184             throws IOException JavaDoc
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         /**
208          * Parse a <%= .... %> expression
209          *
210          * @param reader
211          * @param writingString
212          * @param templateExpressions
213          * @throws IOException
214          */

215         private static void parseExpression(final Reader JavaDoc reader,
216                                           final boolean writingString,
217                                           final StringBuffer JavaDoc templateExpressions)
218             throws IOException JavaDoc
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 JavaDoc map) {
248        final Closure delegatedClosure = (Closure)this.template.clone();
249            
250            delegatedClosure.setDelegate(new Binding(map));
251            
252            return new Writable() {
253                /* (non-Javadoc)
254                * @see groovy.lang.Writable#writeTo(java.io.Writer)
255                */

256                public Writer JavaDoc writeTo(final Writer JavaDoc writer) throws IOException JavaDoc {
257                    delegatedClosure.call(new Object JavaDoc[] {new PrintWriter JavaDoc(writer)});
258
259                    return writer;
260                }
261
262                /* (non-Javadoc)
263                * @see java.lang.Object#toString()
264                */

265                public String JavaDoc toString() {
266                    final StringWriter JavaDoc stringWriter = new StringWriter JavaDoc();
267
268                    try {
269                        writeTo(stringWriter);
270
271                        return stringWriter.toString();
272                    } catch (final IOException JavaDoc e) {
273                        return e.toString();
274                    }
275                }
276
277            };
278        }
279     }
280 }
281
Popular Tags