KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > velocity > texen > Generator


1 package org.apache.velocity.texen;
2
3 /*
4  * Copyright 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.File;
20 import java.io.InputStream;
21 import java.io.FileInputStream;
22 import java.io.BufferedInputStream;
23 import java.io.Writer;
24 import java.io.FileWriter;
25 import java.io.StringWriter;
26 import java.io.OutputStreamWriter;
27 import java.io.BufferedWriter;
28 import java.io.FileOutputStream;
29
30 import java.util.Enumeration;
31 import java.util.Hashtable;
32 import java.util.Iterator;
33 import java.util.Properties;
34
35 import org.apache.velocity.Template;
36 import org.apache.velocity.context.Context;
37 import org.apache.velocity.VelocityContext;
38 import org.apache.velocity.app.VelocityEngine;
39
40 /**
41  * A text/code generator class
42  *
43  * @author <a HREF="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
44  * @author <a HREF="mailto:jvanzyl@apache.org">Jason van Zyl</a>
45  * @version $Id: Generator.java,v 1.20.4.1 2004/03/03 23:23:07 geirm Exp $
46  */

47 public class Generator
48 {
49     /**
50      * Where the texen output will placed.
51      */

52     public static final String OUTPUT_PATH = "output.path";
53     
54     /**
55      * Where the velocity templates live.
56      */

57     public static final String TEMPLATE_PATH = "template.path";
58     
59     /**
60      * Default properties file used for controlling the
61      * tools placed in the context.
62      */

63     private static final String DEFAULT_TEXEN_PROPERTIES =
64         "org/apache/velocity/texen/defaults/texen.properties";
65
66     /**
67      * Default properties used by texen.
68      */

69     private Properties props = new Properties();
70     
71     /**
72      * Context used for generating the texen output.
73      */

74     private Context controlContext;
75
76     /**
77      * Keep track of the file writers used for outputting
78      * to files. If we come across a file writer more
79      * then once then the additional output will be
80      * appended to the file instead of overwritting
81      * the contents.
82      */

83     private Hashtable writers = new Hashtable();
84
85     /**
86      * The generator tools used for creating additional
87      * output withing the control template. This could
88      * use some cleaning up.
89      */

90     private static Generator instance = new Generator();
91
92     /**
93      * This is the encoding for the output file(s).
94      */

95     protected String outputEncoding;
96
97     /**
98      * This is the encoding for the input file(s)
99      * (templates).
100      */

101     protected String inputEncoding;
102     
103     /**
104      * Velocity engine.
105      */

106     protected VelocityEngine ve;
107
108     /**
109      * Default constructor.
110      */

111     private Generator()
112     {
113         setDefaultProps();
114     }
115
116     /**
117      * Create a new generator object with default properties.
118      *
119      * @return Generator generator used in the control context.
120      */

121     public static Generator getInstance()
122     {
123         return instance;
124     }
125     
126     /**
127      * Set the velocity engine.
128      */

129     public void setVelocityEngine(VelocityEngine ve)
130     {
131         this.ve = ve;
132     }
133
134     /**
135      * Create a new generator object with properties loaded from
136      * a file. If the file does not exist or any other exception
137      * occurs during the reading operation the default properties
138      * are used.
139      *
140      * @param String properties used to help populate the control context.
141      * @return Generator generator used in the control context.
142      */

143     public Generator (String propFile)
144     {
145         try
146         {
147             BufferedInputStream bi = null;
148             try
149             {
150                 bi = new BufferedInputStream (new FileInputStream (propFile));
151                 props.load (bi);
152             }
153             finally
154             {
155                 if (bi != null)
156                 {
157                     bi.close();
158                 }
159             }
160         }
161         catch (Exception e)
162         {
163             /*
164              * If something goes wrong we use default properties
165              */

166             setDefaultProps();
167         }
168     }
169     
170     /**
171      * Create a new Generator object with a given property
172      * set. The property set will be duplicated.
173      *
174      * @param Properties properties object to help populate the control context.
175      */

176     public Generator (Properties props)
177     {
178         this.props = (Properties)props.clone();
179     }
180     
181     /**
182      * Set default properties.
183      */

184     protected void setDefaultProps()
185     {
186         ClassLoader classLoader = VelocityEngine.class.getClassLoader();
187         try
188         {
189             InputStream inputStream = null;
190             try
191             {
192                 inputStream = classLoader.getResourceAsStream(
193                     DEFAULT_TEXEN_PROPERTIES);
194             
195                 props.load( inputStream );
196             }
197             finally
198             {
199                 if (inputStream != null)
200                 {
201                     inputStream.close();
202                 }
203             }
204         }
205         catch (Exception ioe)
206         {
207             System.err.println("Cannot get default properties!");
208         }
209     }
210     
211     /**
212      * Set the template path, where Texen will look
213      * for Velocity templates.
214      *
215      * @param String template path for velocity templates.
216      */

217     public void setTemplatePath(String templatePath)
218     {
219         props.put(TEMPLATE_PATH, templatePath);
220     }
221
222     /**
223      * Get the template path.
224      *
225      * @return String template path for velocity templates.
226      */

227     public String getTemplatePath()
228     {
229         return props.getProperty(TEMPLATE_PATH);
230     }
231
232     /**
233      * Set the output path for the generated
234      * output.
235      *
236      * @return String output path for texen output.
237      */

238     public void setOutputPath(String outputPath)
239     {
240         props.put(OUTPUT_PATH, outputPath);
241     }
242
243     /**
244      * Get the output path for the generated
245      * output.
246      *
247      * @return String output path for texen output.
248      */

249     public String getOutputPath()
250     {
251         return props.getProperty(OUTPUT_PATH);
252     }
253
254     /**
255      * Set the output encoding.
256      */

257     public void setOutputEncoding(String outputEncoding)
258     {
259         this.outputEncoding = outputEncoding;
260     }
261
262     /**
263      * Set the input (template) encoding.
264      */

265     public void setInputEncoding(String inputEncoding)
266     {
267         this.inputEncoding = inputEncoding;
268     }
269
270     /**
271      * Returns a writer, based on encoding and path.
272      *
273      * @param path path to the output file
274      * @param encoding output encoding
275      */

276     public Writer getWriter(String path, String encoding) throws Exception {
277         Writer writer;
278         if (encoding == null || encoding.length() == 0 || encoding.equals("8859-1") || encoding.equals("8859_1")) {
279             writer = new FileWriter(path);
280         }
281         else {
282             writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), encoding));
283         }
284         return writer;
285     }
286
287     /**
288      * Returns a template, based on encoding and path.
289      *
290      * @param templateName name of the template
291      * @param encoding template encoding
292      */

293     public Template getTemplate(String templateName, String encoding) throws Exception {
294         Template template;
295         if (encoding == null || encoding.length() == 0 || encoding.equals("8859-1") || encoding.equals("8859_1")) {
296             template = ve.getTemplate(templateName);
297         }
298         else {
299             template = ve.getTemplate(templateName, encoding);
300         }
301         return template;
302     }
303
304     /**
305      * Parse an input and write the output to an output file. If the
306      * output file parameter is null or an empty string the result is
307      * returned as a string object. Otherwise an empty string is returned.
308      *
309      * @param String input template
310      * @param String output file
311      */

312     public String parse (String inputTemplate, String outputFile)
313         throws Exception
314     {
315         return parse(inputTemplate, outputFile, null, null);
316     }
317     
318     /**
319      * Parse an input and write the output to an output file. If the
320      * output file parameter is null or an empty string the result is
321      * returned as a string object. Otherwise an empty string is returned.
322      * You can add objects to the context with the objs Hashtable.
323      *
324      * @param String input template
325      * @param String output file
326      * @param String id for object to be placed in the control context
327      * @param String object to be placed in the context
328      * @return String generated output from velocity
329      */

330     public String parse (String inputTemplate,
331                          String outputFile,
332                          String objectID,
333                          Object object)
334         throws Exception
335     {
336         return parse(inputTemplate, null, outputFile, null, objectID, object);
337     }
338     /**
339      * Parse an input and write the output to an output file. If the
340      * output file parameter is null or an empty string the result is
341      * returned as a string object. Otherwise an empty string is returned.
342      * You can add objects to the context with the objs Hashtable.
343      *
344      * @param String input template
345      * @param String inputEncoding template encoding
346      * @param String output file
347      * @param String outputEncoding encoding of output file
348      * @param String id for object to be placed in the control context
349      * @param String object to be placed in the context
350      * @return String generated output from velocity
351      */

352     public String parse (String inputTemplate,
353                          String intputEncoding,
354                          String outputFile,
355                          String outputEncoding,
356                          String objectID,
357                          Object object)
358         throws Exception
359     {
360         if (objectID != null && object != null)
361         {
362             controlContext.put(objectID, object);
363         }
364         
365         Template template = getTemplate(inputTemplate, inputEncoding != null ? inputEncoding : this.inputEncoding);
366         
367         if (outputFile == null || outputFile.equals(""))
368         {
369             StringWriter sw = new StringWriter();
370             template.merge (controlContext,sw);
371             return sw.toString();
372         }
373         else
374         {
375             Writer writer = null;
376             
377             if (writers.get(outputFile) == null)
378             {
379                 /*
380                  * We have never seen this file before so create
381                  * a new file writer for it.
382                  */

383                 writer = getWriter(
384                             getOutputPath() + File.separator + outputFile,
385                             outputEncoding != null ? outputEncoding : this.outputEncoding
386                          );
387                     
388                 /*
389                  * Place the file writer in our collection
390                  * of file writers.
391                  */

392                 writers.put(outputFile, writer);
393             }
394             else
395             {
396                 writer = (Writer) writers.get(outputFile);
397             }
398             
399             VelocityContext vc = new VelocityContext( controlContext );
400             template.merge (vc,writer);
401
402             // commented because it is closed in shutdown();
403
//fw.close();
404

405             return "";
406         }
407     }
408
409     /**
410      * Parse the control template and merge it with the control
411      * context. This is the starting point in texen.
412      *
413      * @param String control template
414      * @param Context control context
415      * @return String generated output
416      */

417     public String parse (String controlTemplate, Context controlContext)
418         throws Exception
419     {
420         this.controlContext = controlContext;
421         fillContextDefaults(this.controlContext);
422         fillContextProperties(this.controlContext);
423
424         Template template = getTemplate(controlTemplate, inputEncoding);
425         StringWriter sw = new StringWriter();
426         template.merge (controlContext,sw);
427         
428         return sw.toString();
429     }
430
431
432     /**
433      * Create a new context and fill it with the elements of the
434      * objs Hashtable. Default objects and objects that comes from
435      * the properties of this Generator object is also added.
436      *
437      * @param Hashtable objects to place in the control context
438      * @return Context context filled with objects
439      */

440     protected Context getContext (Hashtable objs)
441     {
442         fillContextHash (controlContext,objs);
443         return controlContext;
444     }
445
446     /**
447      * Add all the contents of a Hashtable to the context.
448      *
449      * @param Context context to fill with objects
450      * @param Hashtable source of objects
451      */

452     protected void fillContextHash (Context context, Hashtable objs)
453     {
454         Enumeration enum = objs.keys();
455         while (enum.hasMoreElements())
456         {
457             String key = enum.nextElement().toString();
458             context.put (key, objs.get(key));
459         }
460     }
461
462     /**
463      * Add properties that will aways be in the context by default
464      *
465      * @param Context control context to fill with default values.
466      */

467     protected void fillContextDefaults (Context context)
468     {
469         context.put ("generator", instance);
470         context.put ("outputDirectory", getOutputPath());
471     }
472     
473     /**
474      * Add objects to the context from the current properties.
475      *
476      * @param Context control context to fill with objects
477      * that are specified in the default.properties
478      * file
479      */

480     protected void fillContextProperties (Context context)
481     {
482         Enumeration enum = props.propertyNames();
483         
484         while (enum.hasMoreElements())
485         {
486             String nm = (String)enum.nextElement();
487             if (nm.startsWith ("context.objects."))
488             {
489                 
490                 String contextObj = props.getProperty (nm);
491                 int colon = nm.lastIndexOf ('.');
492                 String contextName = nm.substring (colon+1);
493                 
494                 try
495                 {
496                     Class cls = Class.forName (contextObj);
497                     Object o = cls.newInstance();
498                     context.put (contextName,o);
499                 }
500                 catch (Exception e)
501                 {
502                     e.printStackTrace();
503                     //TO DO: Log Something Here
504
}
505             }
506         }
507     }
508
509     /**
510      * Properly shut down the generator, right now
511      * this is simply flushing and closing the file
512      * writers that we have been holding on to.
513      */

514     public void shutdown()
515     {
516         Iterator iterator = writers.values().iterator();
517         
518         while(iterator.hasNext())
519         {
520             Writer writer = (Writer) iterator.next();
521                         
522             try
523             {
524                 writer.flush();
525                 writer.close();
526             }
527             catch (Exception e)
528             {
529                 /* do nothing */
530             }
531         }
532         // clear the file writers cache
533
writers.clear();
534     }
535 }
536
Popular Tags