KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > velocity > Template


1 package org.apache.velocity;
2
3 /*
4  * Copyright 2000-2001,2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.io.InputStream JavaDoc;
20 import java.io.Writer JavaDoc;
21 import java.io.BufferedReader JavaDoc;
22 import java.io.InputStreamReader JavaDoc;
23 import java.io.UnsupportedEncodingException JavaDoc;
24
25 import org.apache.velocity.runtime.resource.Resource;
26 import org.apache.velocity.runtime.parser.ParseException;
27 import org.apache.velocity.runtime.parser.node.SimpleNode;
28
29 import org.apache.velocity.VelocityContext;
30 import org.apache.velocity.context.Context;
31 import org.apache.velocity.context.InternalContextAdapterImpl;
32
33 import org.apache.velocity.exception.ResourceNotFoundException;
34 import org.apache.velocity.exception.ParseErrorException;
35 import org.apache.velocity.exception.MethodInvocationException;
36
37 /**
38  * This class is used for controlling all template
39  * operations. This class uses a parser created
40  * by JavaCC to create an AST that is subsequently
41  * traversed by a Visitor.
42  *
43  * <pre>
44  * Template template = Velocity.getTemplate("test.wm");
45  * Context context = new VelocityContext();
46  *
47  * context.put("foo", "bar");
48  * context.put("customer", new Customer());
49  *
50  * template.merge(context, writer);
51  * </pre>
52  *
53  * @author <a HREF="mailto:jvanzyl@apache.org">Jason van Zyl</a>
54  * @author <a HREF="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
55  * @version $Id: Template.java,v 1.36.4.1 2004/03/03 22:28:24 geirm Exp $
56  */

57 public class Template extends Resource
58 {
59     /**
60      * To keep track of whether this template has been
61      * initialized. We use the document.init(context)
62      * to perform this.
63      */

64     private boolean initialized = false;
65
66     private Exception JavaDoc errorCondition = null;
67
68     /** Default constructor */
69     public Template()
70     {
71     }
72
73     /**
74      * gets the named resource as a stream, parses and inits
75      *
76      * @return true if successful
77      * @throws ResourceNotFoundException if template not found
78      * from any available source.
79      * @throws ParseErrorException if template cannot be parsed due
80      * to syntax (or other) error.
81      * @throws Exception some other problem, should only be from
82      * initialization of the template AST.
83      */

84     public boolean process()
85         throws ResourceNotFoundException, ParseErrorException, Exception JavaDoc
86     {
87         data = null;
88         InputStream JavaDoc is = null;
89         errorCondition = null;
90
91         /*
92          * first, try to get the stream from the loader
93          */

94         try
95         {
96             is = resourceLoader.getResourceStream(name);
97         }
98         catch( ResourceNotFoundException rnfe )
99         {
100             /*
101              * remember and re-throw
102              */

103
104             errorCondition = rnfe;
105             throw rnfe;
106         }
107
108         /*
109          * if that worked, lets protect in case a loader impl
110          * forgets to throw a proper exception
111          */

112
113         if (is != null)
114         {
115             /*
116              * now parse the template
117              */

118
119             try
120             {
121                 BufferedReader JavaDoc br = new BufferedReader JavaDoc( new InputStreamReader JavaDoc( is, encoding ) );
122  
123                 data = rsvc.parse( br, name);
124                 initDocument();
125                 return true;
126             }
127             catch( UnsupportedEncodingException JavaDoc uce )
128             {
129                 String JavaDoc msg = "Template.process : Unsupported input encoding : " + encoding
130                 + " for template " + name;
131
132                 errorCondition = new ParseErrorException( msg );
133                 throw errorCondition;
134             }
135             catch ( ParseException pex )
136             {
137                 /*
138                  * remember the error and convert
139                  */

140
141                errorCondition = new ParseErrorException( pex.getMessage() );
142                throw errorCondition;
143             }
144             catch( Exception JavaDoc e )
145             {
146                 /*
147                  * who knows? Something from initDocument()
148                  */

149
150                 errorCondition = e;
151                 throw e;
152             }
153             finally
154             {
155                 /*
156                  * Make sure to close the inputstream when we are done.
157                  */

158                 is.close();
159             }
160         }
161         else
162         {
163             /*
164              * is == null, therefore we have some kind of file issue
165              */

166
167             errorCondition = new ResourceNotFoundException("Unknown resource error for resource " + name );
168             throw errorCondition;
169         }
170     }
171
172     /**
173      * initializes the document. init() is not longer
174      * dependant upon context, but we need to let the
175      * init() carry the template name down throught for VM
176      * namespace features
177      */

178     public void initDocument()
179         throws Exception JavaDoc
180     {
181         /*
182          * send an empty InternalContextAdapter down into the AST to initialize it
183          */

184         
185         InternalContextAdapterImpl ica = new InternalContextAdapterImpl( new VelocityContext() );
186
187         try
188         {
189             /*
190              * put the current template name on the stack
191              */

192
193             ica.pushCurrentTemplateName( name );
194             
195             /*
196              * init the AST
197              */

198
199             ((SimpleNode)data).init( ica, rsvc);
200         }
201         finally
202         {
203             /*
204              * in case something blows up...
205              * pull it off for completeness
206              */

207
208             ica.popCurrentTemplateName();
209         }
210
211     }
212
213     /**
214      * The AST node structure is merged with the
215      * context to produce the final output.
216      *
217      * Throws IOException if failure is due to a file related
218      * issue, and Exception otherwise
219      *
220      * @param context Conext with data elements accessed by template
221      * @param writer output writer for rendered template
222      * @throws ResourceNotFoundException if template not found
223      * from any available source.
224      * @throws ParseErrorException if template cannot be parsed due
225      * to syntax (or other) error.
226      * @throws Exception anything else.
227      */

228     public void merge( Context context, Writer JavaDoc writer)
229         throws ResourceNotFoundException, ParseErrorException, MethodInvocationException, Exception JavaDoc
230     {
231         /*
232          * we shouldn't have to do this, as if there is an error condition,
233          * the application code should never get a reference to the
234          * Template
235          */

236
237         if (errorCondition != null)
238         {
239             throw errorCondition;
240         }
241
242         if( data != null)
243         {
244             /*
245              * create an InternalContextAdapter to carry the user Context down
246              * into the rendering engine. Set the template name and render()
247              */

248
249             InternalContextAdapterImpl ica = new InternalContextAdapterImpl( context );
250
251             try
252             {
253                 ica.pushCurrentTemplateName( name );
254                 ica.setCurrentResource( this );
255
256                 ( (SimpleNode) data ).render( ica, writer);
257             }
258             finally
259             {
260                 /*
261                  * lets make sure that we always clean up the context
262                  */

263                 ica.popCurrentTemplateName();
264                 ica.setCurrentResource( null );
265             }
266         }
267         else
268         {
269             /*
270              * this shouldn't happen either, but just in case.
271              */

272
273             String JavaDoc msg = "Template.merge() failure. The document is null, " +
274                 "most likely due to parsing error.";
275
276             rsvc.error(msg);
277             throw new Exception JavaDoc(msg);
278         }
279     }
280 }
281
282
283
Popular Tags