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      private static final String ERR_MSG_FRAGMENT = ". For more information consult the velocity log, or invoke ant "
    40              + "with the -debug flag.";
    41
    42      protected String templatePath;
    43
    44      protected String outputEncoding;
    45
    46      protected String inputEncoding;
    47
    48      protected ExtendedProperties contextProperties;
    49
    50      protected boolean useClasspath;
    51
    52      public void setTemplatePath(String templatePath) throws Exception {
    53          StringBuffer resolvedPath = new StringBuffer();
    54          StringTokenizer st = new StringTokenizer(templatePath, ",");
    55          while (st.hasMoreTokens()) {
    56              final File fullPath = project.resolveFile(st.nextToken());
    57              resolvedPath.append(fullPath.getCanonicalPath());
    58              if (st.hasMoreTokens()) {
    59                  resolvedPath.append(",");
    60              }
    61          }
    62          this.templatePath = resolvedPath.toString();
    63          System.out.println(templatePath);
    64      }
    65
    66      public String getTemplatePath() {
    67          return templatePath;
    68      }
    69
    70      public void setOutputEncoding(String outputEncoding) {
    71          this.outputEncoding = outputEncoding;
    72      }
    73
    74      public void setInputEncoding(String inputEncoding) {
    75          this.inputEncoding = inputEncoding;
    76      }
    77
    78      public void setContextProperties(String file) {
    79          final String[] sources = StringUtils.split(file, ",");
    80          contextProperties = new ExtendedProperties();
    81          for (int i = 0; i < sources.length; i++) {
    82              ExtendedProperties source = new ExtendedProperties();
    83              try {
    84                  final File fullPath = project.resolveFile(sources[i]);
    85                  log("Using contextProperties file: " + fullPath);
    86                  source.load(new FileInputStream(fullPath));
    87              } catch (Exception e) {
    88                  final ClassLoader classLoader = this.getClass().getClassLoader();
    89                  try {
    90                      final InputStream inputStream = classLoader.getResourceAsStream(sources[i]);
    91
    92                      if (inputStream == null) {
    93                          throw new BuildException("Context properties file " + sources[i]
    94                                  + " could not be found in the file system or on the classpath!");
    95                      } else {
    96                          source.load(inputStream);
    97                      }
    98                  } catch (IOException ioe) {
    99                      source = null;
    100                 }
    101             }
    102             for (Iterator j = source.getKeys(); j.hasNext();) {
    103                 final String name = (String) j.next();
    104                 final String value = source.getString(name);
    105                 contextProperties.setProperty(name, value);
    106             }
    107         }
    108     }
    109
    110     public ExtendedProperties getContextProperties() {
    111         return contextProperties;
    112     }
    113
    114     public void setUseClasspath(boolean useClasspath) {
    115         this.useClasspath = useClasspath;
    116     }
    117
    118     public Context initControlContext() {
    119         return new VelocityContext();
    120     }
    121
    122     protected void populateInitialContext(Context context) {
    123         context.put("now", new Date().toString());
    124     }
    125
    126     protected void cleanup() throws Exception {
    127         //
    128     }
    129
    130     protected List initTargets() {
    131         return null;
    132     }
    133
    134     private final Log log = LogFactory.getLog(this.getClass());
    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 = Generator.getInstance();
    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     private VelocityEngine initVelocityEngine() {
    209         VelocityEngine ve = new VelocityEngine();
    210         // Setup the Velocity Runtime.
    211         if (templatePath != null) {
    212             log("Using templatePath: " + templatePath, Project.MSG_VERBOSE);
    213             ve.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, templatePath);
    214         }
    215         if (useClasspath) {
    216             log("Using classpath");
    217             ve.addProperty(VelocityEngine.RESOURCE_LOADER, "classpath");
    218             ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".class",
    219                     "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
    220             ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".cache", "false");
    221             ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER + ".modificationCheckInterval", "2");
    222         }
    223         try {
    224             ve.init();
    225         } catch (Exception e) {
    226             throw new BuildException("VelocityEngine#init() failed " + ERR_MSG_FRAGMENT, e);
    227         }
    228         return ve;
    229     }
    230
    231     /***
    232      * @param c
    233      * @throws IOException
    234      */
    235     private void prepareContextProperties(final Context c) throws IOException {
    236         if (contextProperties != null) {
    237             final Iterator i = contextProperties.getKeys();
    238
    239             while (i.hasNext()) {
    240                 String property = (String) i.next();
    241                 String value = contextProperties.getString(property);
    242                 try {
    243                     c.put(property, new Integer(value));
    244                 } catch (NumberFormatException nfe) {
    245                     final String booleanString = contextProperties.testBoolean(value);
    246                     if (booleanString != null) {
    247                         c.put(property, new Boolean(booleanString));
    248                     } else {
    249                         if (property.endsWith("file.contents")) {
    250                             value = StringUtils.fileContentsToString(project.resolveFile(value).getCanonicalPath());
    251                             property = property.substring(0, property.indexOf("file.contents") - 1);
    252                         }
    253                         c.put(property, value);
    254                     }
    255                 }
    256             }
    257         }
    258     }
    259
    260 }