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