View Javadoc

1   /*
2    * joey-gen and its relative products are published under the terms
3    * of the Apache Software License.
4    * 
5    * Created on 2004/12/20 13:58:36
6    */
7   package org.asyrinx.joey.gen.task;
8   
9   import java.io.File;
10  import java.io.FileInputStream;
11  import java.io.IOException;
12  import java.io.InputStream;
13  import java.io.Writer;
14  import java.util.Date;
15  import java.util.Iterator;
16  import java.util.List;
17  import java.util.StringTokenizer;
18  
19  import org.apache.commons.collections.ExtendedProperties;
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.apache.tools.ant.BuildException;
23  import org.apache.tools.ant.Project;
24  import org.apache.tools.ant.Task;
25  import org.apache.velocity.VelocityContext;
26  import org.apache.velocity.app.VelocityEngine;
27  import org.apache.velocity.context.Context;
28  import org.apache.velocity.exception.MethodInvocationException;
29  import org.apache.velocity.exception.ParseErrorException;
30  import org.apache.velocity.exception.ResourceNotFoundException;
31  import org.apache.velocity.texen.Generator;
32  import org.apache.velocity.util.StringUtils;
33  
34  /***
35   * @author takeshi
36   */
37  public class MultiTargetTexenTask extends Task {
38  
39      protected final Log log = LogFactory.getLog(this.getClass());
40  
41      private static final String ERR_MSG_FRAGMENT = ". For more information consult the velocity log, or invoke ant "
42              + "with the -debug flag.";
43  
44      protected String templatePath;
45  
46      protected String outputEncoding;
47  
48      protected String inputEncoding;
49  
50      protected ExtendedProperties contextProperties;
51  
52      protected boolean useClasspath;
53  
54      public void setTemplatePath(String templatePath) throws Exception {
55          StringBuffer resolvedPath = new StringBuffer();
56          StringTokenizer st = new StringTokenizer(templatePath, ",");
57          while (st.hasMoreTokens()) {
58              final File fullPath = project.resolveFile(st.nextToken());
59              resolvedPath.append(fullPath.getCanonicalPath());
60              if (st.hasMoreTokens()) {
61                  resolvedPath.append(",");
62              }
63          }
64          this.templatePath = resolvedPath.toString();
65          System.out.println(templatePath);
66      }
67  
68      public String getTemplatePath() {
69          return templatePath;
70      }
71  
72      public void setOutputEncoding(String outputEncoding) {
73          this.outputEncoding = outputEncoding;
74      }
75  
76      public void setInputEncoding(String inputEncoding) {
77          this.inputEncoding = inputEncoding;
78      }
79  
80      public void setContextProperties(String file) {
81          final String[] sources = StringUtils.split(file, ",");
82          contextProperties = new ExtendedProperties();
83          for (int i = 0; i < sources.length; i++) {
84              ExtendedProperties source = new ExtendedProperties();
85              try {
86                  final File fullPath = project.resolveFile(sources[i]);
87                  log("Using contextProperties file: " + fullPath);
88                  source.load(new FileInputStream(fullPath));
89              } catch (Exception e) {
90                  final ClassLoader classLoader = this.getClass().getClassLoader();
91                  try {
92                      final InputStream inputStream = classLoader.getResourceAsStream(sources[i]);
93  
94                      if (inputStream == null) {
95                          throw new BuildException("Context properties file " + sources[i]
96                                  + " could not be found in the file system or on the classpath!");
97                      } else {
98                          source.load(inputStream);
99                      }
100                 } catch (IOException ioe) {
101                     source = null;
102                 }
103             }
104             for (Iterator j = source.getKeys(); j.hasNext();) {
105                 final String name = (String) j.next();
106                 final String value = source.getString(name);
107                 contextProperties.setProperty(name, value);
108             }
109         }
110     }
111 
112     public ExtendedProperties getContextProperties() {
113         return contextProperties;
114     }
115 
116     public void setUseClasspath(boolean useClasspath) {
117         this.useClasspath = useClasspath;
118     }
119 
120     public Context initControlContext() {
121         return new VelocityContext();
122     }
123 
124     protected void populateInitialContext(Context context) {
125         context.put("now", new Date().toString());
126     }
127 
128     protected void cleanup() throws Exception {
129         //
130     }
131 
132     protected List initTargets() {
133         return null;
134     }
135 
136     protected void checkTargets(JoeyGenerateTarget target) {
137         if (target.getControlTemplate() == null)
138             throw new BuildException("The control template needs to be defined!");
139         if (target.getOutputDirectory() == null)
140             throw new BuildException("The output directory needs to be defined!");
141         if (target.getOutputFile() == null)
142             throw new BuildException("The output file needs to be defined!");
143         log.info("target=" + target.getTargetName());
144         log.info("outputDirectory=" + target.getOutputDirectory());
145         log.info("controlTemplate=" + target.getControlTemplate());
146     }
147 
148     public void execute() throws BuildException {
149         final List targets = initTargets();
150         if (templatePath == null && useClasspath == false) {
151             throw new BuildException("The template path needs to be defined if you are not using "
152                     + "the classpath for locating templates!");
153         }
154         //
155         final Context c = initControlContext();
156         populateInitialContext(c);
157         try {
158             prepareContextProperties(c);
159         } catch (IOException e) {
160             throw new BuildException("failed to prepareContextProperties", e);
161         }
162         //
163         final VelocityEngine ve = initVelocityEngine();
164         for (Iterator j = targets.iterator(); j.hasNext();) {
165             final JoeyGenerateTarget target = (JoeyGenerateTarget) j.next();
166             checkTargets(target);
167             try {
168                 final Generator generator = initGenerator();
169                 generator.setVelocityEngine(ve);
170                 generator.setOutputPath(target.getOutputDirectory());
171                 generator.setInputEncoding(inputEncoding);
172                 generator.setOutputEncoding(outputEncoding);
173 
174                 if (templatePath != null)
175                     generator.setTemplatePath(templatePath);
176 
177                 final File file = new File(target.getOutputDirectory());
178                 if (!file.exists())
179                     file.mkdirs();
180 
181                 final String path = target.getOutputDirectory() + File.separator + target.getOutputFile();
182                 log("Generating to file " + path, Project.MSG_INFO);
183                 final Writer writer = generator.getWriter(path, outputEncoding);
184 
185                 writer.write(generator.parse(target.getControlTemplate(), c));
186                 writer.flush();
187                 writer.close();
188                 generator.shutdown();
189                 cleanup();
190             } catch (BuildException e) {
191                 throw e;
192             } catch (MethodInvocationException e) {
193                 throw new BuildException("Exception thrown by '" + e.getReferenceName() + "." + e.getMethodName() + "'"
194                         + ERR_MSG_FRAGMENT, e.getWrappedThrowable());
195             } catch (ParseErrorException e) {
196                 throw new BuildException("Velocity syntax error" + ERR_MSG_FRAGMENT, e);
197             } catch (ResourceNotFoundException e) {
198                 throw new BuildException("Resource not found" + ERR_MSG_FRAGMENT, e);
199             } catch (Exception e) {
200                 throw new BuildException("Generation failed" + ERR_MSG_FRAGMENT, e);
201             }
202         }
203     }
204 
205     /***
206      * @return
207      */
208     protected Generator initGenerator() {
209         return Generator.getInstance();
210     }
211 
212     /***
213      * @return
214      */
215     protected VelocityEngine initVelocityEngine() {
216         VelocityEngine ve = new VelocityEngine();
217         // Setup the Velocity Runtime.
218         if (templatePath != null) {
219             log("Using templatePath: " + templatePath, Project.MSG_VERBOSE);
220             ve.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, templatePath);
221         }
222         if (useClasspath) {
223             log("Using classpath");
224             ve.addProperty(VelocityEngine.RESOURCE_LOADER, "classpath");
225             ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".class",
226                     "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
227             ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".cache", "false");
228             ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".modificationCheckInterval", "2");
229         }
230         try {
231             ve.init();
232         } catch (Exception e) {
233             throw new BuildException("VelocityEngine#init() failed " + ERR_MSG_FRAGMENT, e);
234         }
235         return ve;
236     }
237 
238     /***
239      * @param c
240      * @throws IOException
241      */
242     protected void prepareContextProperties(final Context c) throws IOException {
243         if (contextProperties != null) {
244             final Iterator i = contextProperties.getKeys();
245 
246             while (i.hasNext()) {
247                 String property = (String) i.next();
248                 String value = contextProperties.getString(property);
249                 try {
250                     c.put(property, new Integer(value));
251                 } catch (NumberFormatException nfe) {
252                     final String booleanString = contextProperties.testBoolean(value);
253                     if (booleanString != null) {
254                         c.put(property, new Boolean(booleanString));
255                     } else {
256                         if (property.endsWith("file.contents")) {
257                             value = StringUtils.fileContentsToString(project.resolveFile(value).getCanonicalPath());
258                             property = property.substring(0, property.indexOf("file.contents") - 1);
259                         }
260                         c.put(property, value);
261                     }
262                 }
263             }
264         }
265     }
266 
267 }