Coverage report

  %line %branch
org.apache.torque.task.TorqueDataModelTask$TorqueFileResourceLoader
0% 
0% 

 1  
 package org.apache.torque.task;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.io.ByteArrayInputStream;
 23  
 import java.io.ByteArrayOutputStream;
 24  
 import java.io.File;
 25  
 import java.io.IOException;
 26  
 import java.io.InputStream;
 27  
 import java.io.InputStreamReader;
 28  
 import java.io.LineNumberReader;
 29  
 import java.io.PrintStream;
 30  
 import java.io.UnsupportedEncodingException;
 31  
 import java.io.Writer;
 32  
 import java.util.ArrayList;
 33  
 import java.util.Date;
 34  
 import java.util.Hashtable;
 35  
 import java.util.Iterator;
 36  
 import java.util.List;
 37  
 import java.util.Map;
 38  
 
 39  
 import org.apache.commons.lang.StringUtils;
 40  
 import org.apache.texen.Generator;
 41  
 import org.apache.texen.ant.TexenTask;
 42  
 import org.apache.tools.ant.BuildException;
 43  
 import org.apache.tools.ant.DirectoryScanner;
 44  
 import org.apache.tools.ant.types.FileSet;
 45  
 import org.apache.torque.engine.EngineException;
 46  
 import org.apache.torque.engine.database.model.Database;
 47  
 import org.apache.torque.engine.database.transform.XmlToAppData;
 48  
 import org.apache.velocity.VelocityContext;
 49  
 import org.apache.velocity.app.VelocityEngine;
 50  
 import org.apache.velocity.context.Context;
 51  
 import org.apache.velocity.exception.MethodInvocationException;
 52  
 import org.apache.velocity.exception.ParseErrorException;
 53  
 import org.apache.velocity.exception.ResourceNotFoundException;
 54  
 import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
 55  
 import org.apache.velocity.runtime.resource.loader.FileResourceLoader;
 56  
 
 57  
 /**
 58  
  * A base torque task that uses either a single XML schema
 59  
  * representing a data model, or a <fileset> of XML schemas.
 60  
  * We are making the assumption that an XML schema representing
 61  
  * a data model contains tables for a <strong>single</strong>
 62  
  * database.
 63  
  *
 64  
  * @author <a href="mailto:jvanzyl@zenplex.com">Jason van Zyl</a>
 65  
  * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 66  
  */
 67  
 public class TorqueDataModelTask extends TexenTask
 68  
 {
 69  
     /**
 70  
      * XML that describes the database model, this is transformed
 71  
      * into the application model object.
 72  
      */
 73  
     protected String xmlFile;
 74  
 
 75  
     /** Fileset of XML schemas which represent our data models. */
 76  
     protected List filesets = new ArrayList();
 77  
 
 78  
     /** Data models that we collect. One from each XML schema file. */
 79  
     protected List dataModels = new ArrayList();
 80  
 
 81  
     /** Velocity context which exposes our objects in the templates. */
 82  
     protected Context context;
 83  
 
 84  
     /**
 85  
      * Map of data model name to database name.
 86  
      * Should probably stick to the convention of them being the same but
 87  
      * I know right now in a lot of cases they won't be.
 88  
      */
 89  
     protected Hashtable dataModelDbMap;
 90  
 
 91  
     /**
 92  
      * Hashtable containing the names of all the databases
 93  
      * in our collection of schemas.
 94  
      */
 95  
     protected Hashtable databaseNames;
 96  
 
 97  
     //!! This is probably a crappy idea having the sql file -> db map
 98  
     // here. I can't remember why I put it here at the moment ...
 99  
     // maybe I was going to map something else. It can probably
 100  
     // move into the SQL task.
 101  
 
 102  
     /**
 103  
      * Name of the properties file that maps an SQL file
 104  
      * to a particular database.
 105  
      */
 106  
     protected String sqldbmap;
 107  
 
 108  
     /** The target database(s) we are generating SQL for. */
 109  
     private String targetDatabase;
 110  
 
 111  
     /** Target Java package to place the generated files in. */
 112  
     private String targetPackage;
 113  
 
 114  
 
 115  
     /**
 116  
      * Set the sqldbmap.
 117  
      *
 118  
      * @param sqldbmap th db map
 119  
      */
 120  
     public void setSqlDbMap(String sqldbmap)
 121  
     {
 122  
         //!! Make all these references files not strings.
 123  
         this.sqldbmap = getProject().resolveFile(sqldbmap).toString();
 124  
     }
 125  
 
 126  
     /**
 127  
      * Get the sqldbmap.
 128  
      *
 129  
      * @return String sqldbmap.
 130  
      */
 131  
     public String getSqlDbMap()
 132  
     {
 133  
         return sqldbmap;
 134  
     }
 135  
 
 136  
     /**
 137  
      * Return the data models that have been processed.
 138  
      *
 139  
      * @return List data models
 140  
      */
 141  
     public List getDataModels()
 142  
     {
 143  
         return dataModels;
 144  
     }
 145  
 
 146  
     /**
 147  
      * Return the data model to database name map.
 148  
      *
 149  
      * @return Hashtable data model name to database name map.
 150  
      */
 151  
     public Hashtable getDataModelDbMap()
 152  
     {
 153  
         return dataModelDbMap;
 154  
     }
 155  
 
 156  
     /**
 157  
      * Get the xml schema describing the application model.
 158  
      *
 159  
      * @return  String xml schema file.
 160  
      */
 161  
     public String getXmlFile()
 162  
     {
 163  
         return xmlFile;
 164  
     }
 165  
 
 166  
     /**
 167  
      * Set the xml schema describing the application model.
 168  
      *
 169  
      * @param xmlFile The new XmlFile value
 170  
      */
 171  
     public void setXmlFile(String xmlFile)
 172  
     {
 173  
         this.xmlFile = getProject().resolveFile(xmlFile).toString();
 174  
     }
 175  
 
 176  
     /**
 177  
      * Adds a set of xml schema files (nested fileset attribute).
 178  
      *
 179  
      * @param set a Set of xml schema files
 180  
      */
 181  
     public void addFileset(FileSet set)
 182  
     {
 183  
         filesets.add(set);
 184  
     }
 185  
 
 186  
     /**
 187  
      * Get the current target database.
 188  
      *
 189  
      * @return String target database(s)
 190  
      */
 191  
     public String getTargetDatabase()
 192  
     {
 193  
         return targetDatabase;
 194  
     }
 195  
 
 196  
     /**
 197  
      * Set the current target database. (e.g. mysql, oracle, ..)
 198  
      *
 199  
      * @param v target database(s)
 200  
      */
 201  
     public void setTargetDatabase(String v)
 202  
     {
 203  
         targetDatabase = v;
 204  
     }
 205  
 
 206  
     /**
 207  
      * Get the current target package.
 208  
      *
 209  
      * @return return target java package.
 210  
      */
 211  
     public String getTargetPackage()
 212  
     {
 213  
         return targetPackage;
 214  
     }
 215  
 
 216  
     /**
 217  
      * Set the current target package. This is where generated java classes will
 218  
      * live.
 219  
      *
 220  
      * @param v target java package.
 221  
      */
 222  
     public void setTargetPackage(String v)
 223  
     {
 224  
         targetPackage = v;
 225  
     }
 226  
 
 227  
     /**
 228  
      * Set up the initial context for generating the SQL from the XML schema.
 229  
      *
 230  
      * @return the context
 231  
      * @throws Exception
 232  
      */
 233  
     public Context initControlContext() throws Exception
 234  
     {
 235  
         XmlToAppData xmlParser;
 236  
 
 237  
         if (xmlFile == null && filesets.isEmpty())
 238  
         {
 239  
             throw new BuildException("You must specify an XML schema or "
 240  
                     + "fileset of XML schemas!");
 241  
         }
 242  
 
 243  
         try
 244  
         {
 245  
             if (xmlFile != null)
 246  
             {
 247  
                 // Transform the XML database schema into
 248  
                 // data model object.
 249  
                 xmlParser = new XmlToAppData(getTargetDatabase(),
 250  
                         getTargetPackage());
 251  
                 Database ad = xmlParser.parseFile(xmlFile);
 252  
                 ad.setFileName(grokName(xmlFile));
 253  
                 dataModels.add(ad);
 254  
             }
 255  
             else
 256  
             {
 257  
                 // Deal with the filesets.
 258  
                 for (int i = 0; i < filesets.size(); i++)
 259  
                 {
 260  
                     FileSet fs = (FileSet) filesets.get(i);
 261  
                     DirectoryScanner ds = fs.getDirectoryScanner(getProject());
 262  
                     File srcDir = fs.getDir(getProject());
 263  
 
 264  
                     String[] dataModelFiles = ds.getIncludedFiles();
 265  
 
 266  
                     // Make a transaction for each file
 267  
                     for (int j = 0; j < dataModelFiles.length; j++)
 268  
                     {
 269  
                         File f = new File(srcDir, dataModelFiles[j]);
 270  
                         xmlParser = new XmlToAppData(getTargetDatabase(),
 271  
                                 getTargetPackage());
 272  
                         Database ad = xmlParser.parseFile(f.toString());
 273  
                         ad.setFileName(grokName(f.toString()));
 274  
                         dataModels.add(ad);
 275  
                     }
 276  
                 }
 277  
             }
 278  
 
 279  
             Iterator i = dataModels.iterator();
 280  
             databaseNames = new Hashtable();
 281  
             dataModelDbMap = new Hashtable();
 282  
 
 283  
             // Different datamodels may state the same database
 284  
             // names, we just want the unique names of databases.
 285  
             while (i.hasNext())
 286  
             {
 287  
                 Database database = (Database) i.next();
 288  
                 databaseNames.put(database.getName(), database.getName());
 289  
                 dataModelDbMap.put(database.getFileName(), database.getName());
 290  
             }
 291  
         }
 292  
         catch (EngineException ee)
 293  
         {
 294  
             throw new BuildException(ee);
 295  
         }
 296  
 
 297  
         context = new VelocityContext();
 298  
 
 299  
         // Place our set of data models into the context along
 300  
         // with the names of the databases as a convenience for now.
 301  
         context.put("dataModels", dataModels);
 302  
         context.put("databaseNames", databaseNames);
 303  
         context.put("targetDatabase", targetDatabase);
 304  
         context.put("targetPackage", targetPackage);
 305  
 
 306  
         return context;
 307  
     }
 308  
 
 309  
     /**
 310  
      * Change type of "now" to java.util.Date
 311  
      *
 312  
      * @see org.apache.texen.ant.TexenTask#populateInitialContext(org.apache.velocity.context.Context)
 313  
      */
 314  
     protected void populateInitialContext(Context context) throws Exception
 315  
     {
 316  
         super.populateInitialContext(context);
 317  
         context.put("now", new Date());
 318  
     }
 319  
 
 320  
     /**
 321  
      * Gets a name to use for the application's data model.
 322  
      *
 323  
      * @param xmlFile The path to the XML file housing the data model.
 324  
      * @return The name to use for the <code>AppData</code>.
 325  
      */
 326  
     private String grokName(String xmlFile)
 327  
     {
 328  
         // This can't be set from the file name as it is an unreliable
 329  
         // method of naming the descriptor. Not everyone uses the same
 330  
         // method as I do in the TDK. jvz.
 331  
 
 332  
         String name = "data-model";
 333  
         int i = xmlFile.lastIndexOf(System.getProperty("file.separator"));
 334  
         if (i != -1)
 335  
         {
 336  
             // Creep forward to the start of the file name.
 337  
             i++;
 338  
 
 339  
             int j = xmlFile.lastIndexOf('.');
 340  
             if (i < j)
 341  
             {
 342  
                 name = xmlFile.substring(i, j);
 343  
             }
 344  
             else
 345  
             {
 346  
                 // Weirdo
 347  
                 name = xmlFile.substring(i);
 348  
             }
 349  
         }
 350  
         return name;
 351  
     }
 352  
 
 353  
     /**
 354  
      * Override Texen's context properties to map the
 355  
      * torque.xxx properties (including defaults set by the
 356  
      * org/apache/torque/defaults.properties) to just xxx.
 357  
      *
 358  
      * <p>
 359  
      * Also, move xxx.yyy properties to xxxYyy as Velocity
 360  
      * doesn't like the xxx.yyy syntax.
 361  
      * </p>
 362  
      *
 363  
      * @param file the file to read the properties from
 364  
      */
 365  
     public void setContextProperties(String file)
 366  
     {
 367  
         super.setContextProperties(file);
 368  
 
 369  
         // Map the torque.xxx elements from the env to the contextProperties
 370  
         Hashtable env = super.getProject().getProperties();
 371  
         for (Iterator i = env.entrySet().iterator(); i.hasNext();)
 372  
         {
 373  
             Map.Entry entry = (Map.Entry) i.next();
 374  
             String key = (String) entry.getKey();
 375  
             if (key.startsWith("torque."))
 376  
             {
 377  
                 String newKey = key.substring("torque.".length());
 378  
                 int j = newKey.indexOf(".");
 379  
                 while (j != -1)
 380  
                 {
 381  
                     newKey =
 382  
                         newKey.substring(0, j)
 383  
                         +  StringUtils.capitalize(newKey.substring(j + 1));
 384  
                     j = newKey.indexOf(".");
 385  
                 }
 386  
 
 387  
                 contextProperties.setProperty(newKey, entry.getValue());
 388  
             }
 389  
         }
 390  
     }
 391  
     /**
 392  
      * This message fragment (telling users to consult the log or
 393  
      * invoke ant with the -debug flag) is appended to rethrown
 394  
      * exception messages.
 395  
      */
 396  
     private final static String ERR_MSG_FRAGMENT = 
 397  
         ". For more information consult the velocity log, or invoke ant " +
 398  
     "with the -debug flag.";
 399  
 
 400  
     /**
 401  
      * This method creates an VelocityEngine instance, parses
 402  
      * every template and creates the corresponding output.
 403  
      * 
 404  
      * Unfortunately the TextenTask.execute() method makes
 405  
      * everything for us but we just want to set our own
 406  
      * VelocityTemplateLoader. 
 407  
      * TODO: change once TEXEN-14 is resolved and out.
 408  
      *  
 409  
      * @see org.apache.texen.ant.TexenTask#execute()
 410  
      */
 411  
     public void execute() throws BuildException 
 412  
     {
 413  
         // Make sure the template path is set.
 414  
         if (templatePath == null && useClasspath == false)
 415  
         {
 416  
             throw new BuildException(
 417  
                 "The template path needs to be defined if you are not using "
 418  
                         + "the classpath for locating templates!");
 419  
         }
 420  
 
 421  
         // Make sure the control template is set.
 422  
         if (controlTemplate == null)
 423  
         {
 424  
             throw new BuildException(
 425  
                     "The control template needs to be defined!");
 426  
         }
 427  
 
 428  
         // Make sure the output directory is set.
 429  
         if (outputDirectory == null)
 430  
         {
 431  
             throw new BuildException(
 432  
                     "The output directory needs to be defined!");
 433  
         }
 434  
 
 435  
         // Make sure there is an output file.
 436  
         if (outputFile == null)
 437  
         {
 438  
             throw new BuildException("The output file needs to be defined!");
 439  
         }
 440  
 
 441  
         VelocityEngine ve = new VelocityEngine();
 442  
 
 443  
         try
 444  
         {
 445  
             // Setup the Velocity Runtime.
 446  
             if (templatePath != null)
 447  
             {
 448  
                 log("Using templatePath: " + templatePath, project.MSG_VERBOSE);
 449  
                 ve.setProperty("torque" + VelocityEngine.FILE_RESOURCE_LOADER_PATH,
 450  
                         templatePath);
 451  
 
 452  
                 // TR: We need our own FileResourceLoader
 453  
                 ve.addProperty(VelocityEngine.RESOURCE_LOADER, "torquefile");
 454  
                 ve.setProperty("torquefile." + VelocityEngine.RESOURCE_LOADER
 455  
                             + ".instance",
 456  
                         new TorqueFileResourceLoader(this));
 457  
             }
 458  
 
 459  
             if (useClasspath)
 460  
             {
 461  
                 log("Using classpath");
 462  
                 // TR: We need our own ClasspathResourceLoader
 463  
                 ve.addProperty(VelocityEngine.RESOURCE_LOADER, "classpath");
 464  
 
 465  
                 ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER
 466  
                         + ".instance", new TorqueClasspathResourceLoader(this));
 467  
 
 468  
                 ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER
 469  
                         + ".cache", "false");
 470  
 
 471  
                 ve.setProperty("classpath." + VelocityEngine.RESOURCE_LOADER
 472  
                         + ".modificationCheckInterval", "2");
 473  
             }
 474  
 
 475  
             ve.init();
 476  
 
 477  
             // Create the text generator.
 478  
             Generator generator = Generator.getInstance();
 479  
             generator.setVelocityEngine(ve);
 480  
             generator.setOutputPath(outputDirectory);
 481  
             generator.setInputEncoding(inputEncoding);
 482  
             generator.setOutputEncoding(outputEncoding);
 483  
 
 484  
             if (templatePath != null)
 485  
             {
 486  
                 generator.setTemplatePath(templatePath);
 487  
             }
 488  
 
 489  
             // Make sure the output directory exists, if it doesn't
 490  
             // then create it.
 491  
             File file = new File(outputDirectory);
 492  
             if (!file.exists())
 493  
             {
 494  
                 file.mkdirs();
 495  
             }
 496  
 
 497  
             String path = outputDirectory + File.separator + outputFile;
 498  
             log("Generating to file " + path, project.MSG_INFO);
 499  
             Writer writer = generator.getWriter(path, outputEncoding);
 500  
 
 501  
             // The generator and the output path should
 502  
             // be placed in the init context here and
 503  
             // not in the generator class itself.
 504  
             Context c = initControlContext();
 505  
 
 506  
             // Everything in the generator class should be
 507  
             // pulled out and placed in here. What the generator
 508  
             // class does can probably be added to the Velocity
 509  
             // class and the generator class can probably
 510  
             // be removed all together.
 511  
             populateInitialContext(c);
 512  
 
 513  
             // Feed all the options into the initial
 514  
             // control context so they are available
 515  
             // in the control/worker templates.
 516  
             if (contextProperties != null)
 517  
             {
 518  
                 Iterator i = contextProperties.getKeys();
 519  
 
 520  
                 while (i.hasNext())
 521  
                 {
 522  
                     String property = (String) i.next();
 523  
                     String value = contextProperties.getString(property);
 524  
 
 525  
                     // Now lets quickly check to see if what
 526  
                     // we have is numeric and try to put it
 527  
                     // into the context as an Integer.
 528  
                     try
 529  
                     {
 530  
                         c.put(property, new Integer(value));
 531  
                     } catch (NumberFormatException nfe)
 532  
                     {
 533  
                         // Now we will try to place the value into
 534  
                         // the context as a boolean value if it
 535  
                         // maps to a valid boolean value.
 536  
                         String booleanString = contextProperties
 537  
                                 .testBoolean(value);
 538  
 
 539  
                         if (booleanString != null)
 540  
                         {
 541  
                             c.put(property, new Boolean(booleanString));
 542  
                         } else
 543  
                         {
 544  
                             // We are going to do something special
 545  
                             // for properties that have a "file.contents"
 546  
                             // suffix: for these properties will pull
 547  
                             // in the contents of the file and make
 548  
                             // them available in the context. So for
 549  
                             // a line like the following in a properties file:
 550  
                             //
 551  
                             // license.file.contents = license.txt
 552  
                             //
 553  
                             // We will pull in the contents of license.txt
 554  
                             // and make it available in the context as
 555  
                             // $license. This should make texen a little
 556  
                             // more flexible.
 557  
                             if (property.endsWith("file.contents"))
 558  
                             {
 559  
                                 // We need to turn the license file from
 560  
                                 // relative to
 561  
                                 // absolute, and let Ant help :)
 562  
                                 value = org.apache.velocity.util.StringUtils
 563  
                                         .fileContentsToString(project
 564  
                                                 .resolveFile(value)
 565  
                                                 .getCanonicalPath());
 566  
 
 567  
                                 property = property.substring(0, property
 568  
                                         .indexOf("file.contents") - 1);
 569  
                             }
 570  
 
 571  
                             c.put(property, value);
 572  
                         }
 573  
                     }
 574  
                 }
 575  
             }
 576  
 
 577  
             writer.write(generator.parse(controlTemplate, c));
 578  
             writer.flush();
 579  
             writer.close();
 580  
             generator.shutdown();
 581  
             cleanup();
 582  
         } 
 583  
         catch (BuildException e)
 584  
         {
 585  
             throw e;
 586  
         } 
 587  
         catch (MethodInvocationException e)
 588  
         {
 589  
             throw new BuildException("Exception thrown by '"
 590  
                     + e.getReferenceName() + "." + e.getMethodName() + "'"
 591  
                     + ERR_MSG_FRAGMENT, e.getWrappedThrowable());
 592  
         } 
 593  
         catch (ParseErrorException e)
 594  
         {
 595  
             throw new BuildException(
 596  
                     "Velocity syntax error" + ERR_MSG_FRAGMENT, e);
 597  
         } 
 598  
         catch (ResourceNotFoundException e)
 599  
         {
 600  
             throw new BuildException(
 601  
                     "Resource not found" + ERR_MSG_FRAGMENT, 
 602  
                     e);
 603  
         } 
 604  
         catch (Exception e)
 605  
         {
 606  
             throw new BuildException(
 607  
                     "Generation failed" + ERR_MSG_FRAGMENT, 
 608  
                     e);
 609  
         }
 610  
     }
 611  
 
 612  
     /**
 613  
      * This method filters the template and replaces some
 614  
      * unwanted characters. For example it removes leading
 615  
      * spaces in front of velocity commands and replaces
 616  
      * tabs with spaces to prevent bounces in different
 617  
      * code editors with different tab-width-setting.
 618  
      * 
 619  
      * @param resource the input stream to filter
 620  
      * 
 621  
      * @return the filtered input stream.
 622  
      * 
 623  
      * @throws IOException if creating, reading or writing to a stream fails.
 624  
      */
 625  
     protected InputStream filter(InputStream resource) throws IOException
 626  
     {
 627  
         InputStreamReader streamReader;
 628  
         if (inputEncoding != null)
 629  
         {
 630  
             streamReader = new InputStreamReader(resource, inputEncoding);
 631  
         }
 632  
         else
 633  
         {
 634  
             streamReader = new InputStreamReader(resource);
 635  
         }
 636  
         LineNumberReader lineNumberReader = new LineNumberReader(streamReader);
 637  
         String line = null;
 638  
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 639  
         PrintStream ps = null;
 640  
         if (inputEncoding != null)
 641  
         {
 642  
             ps = new PrintStream(baos, true, inputEncoding);
 643  
         }
 644  
         else
 645  
         {
 646  
             ps = new PrintStream(baos, true);
 647  
         }
 648  
 
 649  
         while ((line = lineNumberReader.readLine()) != null)
 650  
         {
 651  
             // remove leading spaces in front of velocity commands and comments
 652  
             line = line.replaceAll("^\\s*#", "#");
 653  
             // replace tabs with spaces to prevent bounces in editors
 654  
             line = line.replaceAll("\t", "    ");
 655  
             ps.println(line);
 656  
         }
 657  
         ps.flush();
 658  
         ps.close();
 659  
 
 660  
         return new ByteArrayInputStream(baos.toByteArray());
 661  
     }
 662  
 
 663  
     
 664  
     /**
 665  
      * A custom classpath resource loader which filters tabs and removes spaces
 666  
      * from lines with velocity commands. 
 667  
      */
 668  
     public static class TorqueClasspathResourceLoader 
 669  
             extends ClasspathResourceLoader
 670  
     {
 671  
         /**
 672  
          * The task in which this resource loader is used.
 673  
          */
 674  
         private TorqueDataModelTask task;
 675  
         
 676  
         /**
 677  
          * Constructor.
 678  
          *
 679  
          * @param task the task in which this resource loader is used.
 680  
          */
 681  
         public TorqueClasspathResourceLoader(TorqueDataModelTask task)
 682  
         {
 683  
             this.task = task;
 684  
         }
 685  
         
 686  
         /**
 687  
          * @see org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader#getResourceStream(java.lang.String)
 688  
          */
 689  
         public synchronized InputStream getResourceStream(String name) 
 690  
                 throws ResourceNotFoundException 
 691  
         {
 692  
             InputStream source = null;
 693  
             try 
 694  
             {
 695  
                 source = super.getResourceStream(name);
 696  
                 return task.filter(source);
 697  
             } 
 698  
             catch (IOException uee)
 699  
             {
 700  
                 task.log(uee.getMessage());
 701  
                 throw new ResourceNotFoundException(uee.getMessage());
 702  
             }
 703  
             finally
 704  
             {
 705  
                 if (source != null)
 706  
                 {
 707  
                     try
 708  
                     {
 709  
                         source.close();
 710  
                     }
 711  
                     catch (IOException e)
 712  
                     {
 713  
                         task.log(e.getMessage());
 714  
                     }
 715  
                 }
 716  
             }
 717  
         }
 718  
     }
 719  
 
 720  
     /**
 721  
      * A custom file resource loader which filters tabs and removes spaces
 722  
      * from lines with velocity commands. 
 723  
      */
 724  
     public static class TorqueFileResourceLoader
 725  
             extends FileResourceLoader
 726  
     {
 727  
         /**
 728  
          * The task in which this resource loader is used.
 729  
          */
 730  
         private TorqueDataModelTask task;
 731  
         
 732  
         /**
 733  
          * Constructor.
 734  
          *
 735  
          * @param task the task in which this resource loader is used.
 736  
          */
 737  
         public TorqueFileResourceLoader(TorqueDataModelTask task)
 738  0
         {
 739  0
             this.task = task;
 740  0
         }
 741  
         
 742  
         /**
 743  
          * @see org.apache.velocity.runtime.resource.loader.FileResourceLoader#getResourceStream(java.lang.String)
 744  
          */
 745  
         public synchronized InputStream getResourceStream(
 746  
                 String name) 
 747  
                 throws ResourceNotFoundException
 748  
         {
 749  0
             InputStream source = null;
 750  
             try 
 751  
             {
 752  0
                 source = super.getResourceStream(name);
 753  0
                 return task.filter(source);
 754  
             } 
 755  0
             catch (IOException uee)
 756  
             {
 757  0
                 task.log(uee.getMessage());
 758  0
                 throw new ResourceNotFoundException(uee.getMessage());
 759  
             }
 760  
             finally
 761  
             {
 762  0
                 if (source != null)
 763  
                 {
 764  
                     try
 765  
                     {
 766  0
                         source.close();
 767  
                     }
 768  0
                     catch (IOException e)
 769  
                     {
 770  0
                         task.log(e.getMessage());
 771  0
                     }
 772  
                 }
 773  
             }
 774  
         }
 775  
     }
 776  
 }
 777  
 
 778  
 

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.