KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > velocity > anakia > AnakiaTask


1 package org.apache.velocity.anakia;
2
3 /*
4  * Copyright 2001,2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.io.BufferedWriter JavaDoc;
20 import java.io.File JavaDoc;
21 import java.io.FileOutputStream JavaDoc;
22 import java.io.OutputStreamWriter JavaDoc;
23 import java.io.Writer JavaDoc;
24
25 import java.util.StringTokenizer JavaDoc;
26
27 import org.apache.tools.ant.BuildException;
28 import org.apache.tools.ant.DirectoryScanner;
29 import org.apache.tools.ant.Project;
30 import org.apache.tools.ant.taskdefs.MatchingTask;
31
32 import org.xml.sax.SAXParseException JavaDoc;
33
34 import org.jdom.Document;
35 import org.jdom.JDOMException;
36 import org.jdom.input.SAXBuilder;
37
38 import org.apache.velocity.Template;
39 import org.apache.velocity.app.VelocityEngine;
40 import org.apache.velocity.runtime.RuntimeConstants;
41 import org.apache.velocity.util.StringUtils;
42
43 import org.apache.velocity.VelocityContext;
44
45 /**
46  * The purpose of this Ant Task is to allow you to use
47  * Velocity as an XML transformation tool like XSLT is.
48  * So, instead of using XSLT, you will be able to use this
49  * class instead to do your transformations. It works very
50  * similar in concept to Ant's <style> task.
51  * <p>
52  * You can find more documentation about this class on the
53  * Velocity
54  * <a HREF="http://jakarta.apache.org/velocity/anakia.html">Website</a>.
55  *
56  * @author <a HREF="mailto:jon@latchkey.com">Jon S. Stevens</a>
57  * @author <a HREF="mailto:szegedia@freemail.hu">Attila Szegedi</a>
58  * @version $Id: AnakiaTask.java,v 1.34.4.1 2004/03/03 23:22:04 geirm Exp $
59  */

60 public class AnakiaTask extends MatchingTask
61 {
62     /** <code>{@link SAXBuilder}</code> instance to use */
63     private SAXBuilder builder;
64
65     /** the destination directory */
66     private File JavaDoc destDir = null;
67     
68     /** the base directory */
69     private File JavaDoc baseDir = null;
70
71     /** the style= attribute */
72     private String JavaDoc style = null;
73     
74     /** the File to the style file */
75     private File JavaDoc styleFile = null;
76     
77     /** last modified of the style sheet */
78     private long styleSheetLastModified = 0;
79
80     /** the projectFile= attribute */
81     private String JavaDoc projectAttribute = null;
82     
83     /** the File for the project.xml file */
84     private File JavaDoc projectFile = null;
85     
86     /** last modified of the project file if it exists */
87     private long projectFileLastModified = 0;
88
89     /** check the last modified date on files. defaults to true */
90     private boolean lastModifiedCheck = true;
91
92     /** the default output extension is .html */
93     private String JavaDoc extension = ".html";
94
95     /** the template path */
96     private String JavaDoc templatePath = null;
97
98     /** the file to get the velocity properties file */
99     private File JavaDoc velocityPropertiesFile = null;
100
101     /** the VelocityEngine instance to use */
102     private VelocityEngine ve = new VelocityEngine();
103
104     /**
105      * Constructor creates the SAXBuilder.
106      */

107     public AnakiaTask()
108     {
109         builder = new SAXBuilder();
110         builder.setFactory(new AnakiaJDOMFactory());
111     }
112
113     /**
114      * Set the base directory.
115      */

116     public void setBasedir(File JavaDoc dir)
117     {
118         baseDir = dir;
119     }
120     
121     /**
122      * Set the destination directory into which the VSL result
123      * files should be copied to
124      * @param dirName the name of the destination directory
125      */

126     public void setDestdir(File JavaDoc dir)
127     {
128         destDir = dir;
129     }
130     
131     /**
132      * Allow people to set the default output file extension
133      */

134     public void setExtension(String JavaDoc extension)
135     {
136         this.extension = extension;
137     }
138     
139     /**
140      * Allow people to set the path to the .vsl file
141      */

142     public void setStyle(String JavaDoc style)
143     {
144         this.style = style;
145     }
146     
147     /**
148      * Allow people to set the path to the project.xml file
149      */

150     public void setProjectFile(String JavaDoc projectAttribute)
151     {
152         this.projectAttribute = projectAttribute;
153     }
154
155     /**
156      * Set the path to the templates.
157      * The way it works is this:
158      * If you have a Velocity.properties file defined, this method
159      * will <strong>override</strong> whatever is set in the
160      * Velocity.properties file. This allows one to not have to define
161      * a Velocity.properties file, therefore using Velocity's defaults
162      * only.
163      */

164     
165     public void setTemplatePath(File JavaDoc templatePath)
166      {
167          try
168          {
169              this.templatePath = templatePath.getCanonicalPath();
170          }
171          catch (java.io.IOException JavaDoc ioe)
172          {
173              throw new BuildException(ioe);
174          }
175      }
176
177     /**
178      * Allow people to set the path to the velocity.properties file
179      * This file is found relative to the path where the JVM was run.
180      * For example, if build.sh was executed in the ./build directory,
181      * then the path would be relative to this directory.
182      * This is optional based on the setting of setTemplatePath().
183      */

184     public void setVelocityPropertiesFile(File JavaDoc velocityPropertiesFile)
185     {
186         this.velocityPropertiesFile = velocityPropertiesFile;
187     }
188
189     /**
190      * Turn on/off last modified checking. by default, it is on.
191      */

192     public void setLastModifiedCheck(String JavaDoc lastmod)
193     {
194         if (lastmod.equalsIgnoreCase("false") || lastmod.equalsIgnoreCase("no")
195                 || lastmod.equalsIgnoreCase("off"))
196         {
197             this.lastModifiedCheck = false;
198         }
199     }
200
201     /**
202      * Main body of the application
203      */

204     public void execute () throws BuildException
205     {
206         DirectoryScanner scanner;
207         String JavaDoc[] list;
208         String JavaDoc[] dirs;
209
210         if (baseDir == null)
211         {
212             baseDir = project.resolveFile(".");
213         }
214         if (destDir == null )
215         {
216             String JavaDoc msg = "destdir attribute must be set!";
217             throw new BuildException(msg);
218         }
219         if (style == null)
220         {
221             throw new BuildException("style attribute must be set!");
222         }
223
224         if (velocityPropertiesFile == null)
225         {
226             velocityPropertiesFile = new File JavaDoc("velocity.properties");
227         }
228
229         /*
230          * If the props file doesn't exist AND a templatePath hasn't
231          * been defined, then throw the exception.
232          */

233         if ( !velocityPropertiesFile.exists() && templatePath == null )
234         {
235             throw new BuildException ("No template path and could not " +
236                 "locate velocity.properties file: " +
237                 velocityPropertiesFile.getAbsolutePath());
238         }
239
240         log("Transforming into: " + destDir.getAbsolutePath(), Project.MSG_INFO);
241
242         // projectFile relative to baseDir
243
if (projectAttribute != null && projectAttribute.length() > 0)
244         {
245             projectFile = new File JavaDoc(baseDir, projectAttribute);
246             if (projectFile.exists())
247             {
248                 projectFileLastModified = projectFile.lastModified();
249             }
250             else
251             {
252                 log ("Project file is defined, but could not be located: " +
253                     projectFile.getAbsolutePath(), Project.MSG_INFO );
254                 projectFile = null;
255             }
256         }
257
258         Document projectDocument = null;
259         try
260         {
261             if ( velocityPropertiesFile.exists() )
262             {
263                 ve.init(velocityPropertiesFile.getAbsolutePath());
264             }
265             else if (templatePath != null && templatePath.length() > 0)
266             {
267                 ve.setProperty( RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
268                     templatePath);
269                 ve.init();
270             }
271
272             // get the last modification of the VSL stylesheet
273
styleSheetLastModified = ve.getTemplate( style ).getLastModified();
274
275             // Build the Project file document
276
if (projectFile != null)
277             {
278                 projectDocument = builder.build(projectFile);
279             }
280         }
281         catch (Exception JavaDoc e)
282         {
283             log("Error: " + e.toString(), Project.MSG_INFO);
284             throw new BuildException(e);
285         }
286         
287         // find the files/directories
288
scanner = getDirectoryScanner(baseDir);
289
290         // get a list of files to work on
291
list = scanner.getIncludedFiles();
292         for (int i = 0;i < list.length; ++i)
293         {
294             process( baseDir, list[i], destDir, projectDocument );
295         }
296     }
297     
298     /**
299      * Process an XML file using Velocity
300      */

301     private void process(File JavaDoc baseDir, String JavaDoc xmlFile, File JavaDoc destDir,
302                          Document projectDocument)
303         throws BuildException
304     {
305         File JavaDoc outFile=null;
306         File JavaDoc inFile=null;
307         Writer JavaDoc writer = null;
308         try
309         {
310             // the current input file relative to the baseDir
311
inFile = new File JavaDoc(baseDir,xmlFile);
312             // the output file relative to basedir
313
outFile = new File JavaDoc(destDir,
314                             xmlFile.substring(0,
315                             xmlFile.lastIndexOf('.')) + extension);
316
317             // only process files that have changed
318
if (lastModifiedCheck == false ||
319                     (inFile.lastModified() > outFile.lastModified() ||
320                     styleSheetLastModified > outFile.lastModified() ||
321                     projectFileLastModified > outFile.lastModified()))
322             {
323                 ensureDirectoryFor( outFile );
324
325                 //-- command line status
326
log("Input: " + xmlFile, Project.MSG_INFO );
327
328                 // Build the JDOM Document
329
Document root = builder.build(inFile);
330
331                 // Shove things into the Context
332
VelocityContext context = new VelocityContext();
333
334                 /*
335                  * get the property TEMPLATE_ENCODING
336                  * we know it's a string...
337                  */

338                 String JavaDoc encoding = (String JavaDoc) ve.getProperty( RuntimeConstants.OUTPUT_ENCODING );
339                 if (encoding == null || encoding.length() == 0
340                     || encoding.equals("8859-1") || encoding.equals("8859_1"))
341                 {
342                     encoding = "ISO-8859-1";
343                 }
344
345                 OutputWrapper ow = new OutputWrapper();
346                 ow.setEncoding (encoding);
347                 
348                 context.put ("root", root.getRootElement());
349                 context.put ("xmlout", ow );
350                 context.put ("relativePath", getRelativePath(xmlFile));
351                 context.put ("treeWalk", new TreeWalker());
352                 context.put ("xpath", new XPathTool() );
353                 context.put ("escape", new Escape() );
354                 context.put ("date", new java.util.Date JavaDoc() );
355
356                 // only put this into the context if it exists.
357
if (projectDocument != null)
358                 {
359                     context.put ("project", projectDocument.getRootElement());
360                 }
361                 
362                 // Process the VSL template with the context and write out
363
// the result as the outFile.
364
writer = new BufferedWriter JavaDoc(new OutputStreamWriter JavaDoc(
365                                             new FileOutputStream JavaDoc(outFile),
366                                                 encoding));
367                 // get the template to process
368
Template template = ve.getTemplate(style);
369                 template.merge(context, writer);
370
371                 log("Output: " + outFile, Project.MSG_INFO );
372             }
373         }
374         catch (JDOMException e)
375         {
376             if (outFile != null ) outFile.delete();
377             if (e.getCause() != null)
378             {
379                 Throwable JavaDoc rootCause = e.getCause();
380                 if (rootCause instanceof SAXParseException JavaDoc)
381                 {
382                     System.out.println("");
383                     System.out.println("Error: " + rootCause.getMessage());
384                     System.out.println(
385                         " Line: " +
386                             ((SAXParseException JavaDoc)rootCause).getLineNumber() +
387                         " Column: " +
388                             ((SAXParseException JavaDoc)rootCause).getColumnNumber());
389                     System.out.println("");
390                 }
391                 else
392                 {
393                     rootCause.printStackTrace();
394                 }
395             }
396             else
397             {
398                 e.printStackTrace();
399             }
400 // log("Failed to process " + inFile, Project.MSG_INFO);
401
}
402         catch (Throwable JavaDoc e)
403         {
404 // log("Failed to process " + inFile, Project.MSG_INFO);
405
if (outFile != null)
406             {
407                 outFile.delete();
408             }
409             e.printStackTrace();
410         }
411         finally
412         {
413             if (writer != null)
414             {
415                 try
416                 {
417                     writer.flush();
418                     writer.close();
419                 }
420                 catch (Exception JavaDoc e)
421                 {
422                 }
423             }
424         }
425     }
426     
427     /**
428      * Hacky method to figure out the relative path
429      * that we are currently in. This is good for getting
430      * the relative path for images and anchor's.
431      */

432     private String JavaDoc getRelativePath(String JavaDoc file)
433     {
434         if (file == null || file.length()==0)
435             return "";
436         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(file, "/\\");
437         // needs to be -1 cause ST returns 1 even if there are no matches. huh?
438
int slashCount = st.countTokens() - 1;
439         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
440         for (int i=0;i<slashCount ;i++ )
441         {
442             sb.append ("../");
443         }
444
445         if (sb.toString().length() > 0)
446         {
447             return StringUtils.chop(sb.toString(), 1);
448         }
449         else
450         {
451             return ".";
452         }
453     }
454     
455     /**
456      * create directories as needed
457      */

458     private void ensureDirectoryFor( File JavaDoc targetFile ) throws BuildException
459     {
460         File JavaDoc directory = new File JavaDoc( targetFile.getParent() );
461         if (!directory.exists())
462         {
463             if (!directory.mkdirs())
464             {
465                 throw new BuildException("Unable to create directory: "
466                                          + directory.getAbsolutePath() );
467             }
468         }
469     }
470 }
471
Popular Tags