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 }