EMMA Coverage Report (generated Tue May 18 22:13:27 CDT 2004)
[all classes][org.apache.velocity.anakia]

COVERAGE SUMMARY FOR SOURCE FILE [AnakiaTask.java]

nameclass, %method, %block, %line, %
AnakiaTask.java100% (1/1)92%  (12/13)68%  (443/656)71%  (99.5/141)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AnakiaTask100% (1/1)92%  (12/13)68%  (443/656)71%  (99.5/141)
setVelocityPropertiesFile (File): void 0%   (0/1)0%   (0/4)0%   (0/2)
ensureDirectoryFor (File): void 100% (1/1)38%  (10/26)60%  (3/5)
setLastModifiedCheck (String): void 100% (1/1)50%  (8/16)78%  (2.3/3)
setTemplatePath (File): void 100% (1/1)50%  (6/12)60%  (3/5)
execute (): void 100% (1/1)64%  (131/204)69%  (25/36)
process (File, String, File, Document): void 100% (1/1)66%  (182/275)61%  (32.4/53)
getRelativePath (String): String 100% (1/1)70%  (31/44)68%  (6.8/10)
AnakiaTask (): void 100% (1/1)100% (55/55)100% (17/17)
setBasedir (File): void 100% (1/1)100% (4/4)100% (2/2)
setDestdir (File): void 100% (1/1)100% (4/4)100% (2/2)
setExtension (String): void 100% (1/1)100% (4/4)100% (2/2)
setProjectFile (String): void 100% (1/1)100% (4/4)100% (2/2)
setStyle (String): void 100% (1/1)100% (4/4)100% (2/2)

1package 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 
19import java.io.BufferedWriter;
20import java.io.File;
21import java.io.FileOutputStream;
22import java.io.OutputStreamWriter;
23import java.io.Writer;
24 
25import java.util.StringTokenizer;
26 
27import org.apache.tools.ant.BuildException;
28import org.apache.tools.ant.DirectoryScanner;
29import org.apache.tools.ant.Project;
30import org.apache.tools.ant.taskdefs.MatchingTask;
31 
32import org.xml.sax.SAXParseException;
33 
34import org.jdom.Document;
35import org.jdom.JDOMException;
36import org.jdom.input.SAXBuilder;
37 
38import org.apache.velocity.Template;
39import org.apache.velocity.app.VelocityEngine;
40import org.apache.velocity.runtime.RuntimeConstants;
41import org.apache.velocity.util.StringUtils;
42 
43import 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 */
60public 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 destDir = null;
67    
68    /** the base directory */
69    private File baseDir = null;
70 
71    /** the style= attribute */
72    private String style = null;
73    
74    /** the File to the style file */
75    private File styleFile = null;
76    
77    /** last modified of the style sheet */
78    private long styleSheetLastModified = 0;
79 
80    /** the projectFile= attribute */
81    private String projectAttribute = null;
82    
83    /** the File for the project.xml file */
84    private File 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 extension = ".html";
94 
95    /** the template path */
96    private String templatePath = null;
97 
98    /** the file to get the velocity properties file */
99    private File 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 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 dir)
127    {
128        destDir = dir;
129    }
130    
131    /**
132     * Allow people to set the default output file extension
133     */
134    public void setExtension(String 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 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 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 templatePath)
166     {
167         try 
168         {
169             this.templatePath = templatePath.getCanonicalPath();
170         } 
171         catch (java.io.IOException 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 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 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[]         list;
208        String[]         dirs;
209 
210        if (baseDir == null)
211        {
212            baseDir = project.resolveFile(".");
213        }
214        if (destDir == null )
215        {
216            String 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("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(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 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 baseDir, String xmlFile, File destDir, 
302                         Document projectDocument)
303        throws BuildException
304    {
305        File   outFile=null;
306        File   inFile=null;
307        Writer writer = null;
308        try
309        {
310            // the current input file relative to the baseDir
311            inFile = new File(baseDir,xmlFile);
312            // the output file relative to basedir
313            outFile = new File(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 encoding = (String) 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() );
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(new OutputStreamWriter(
365                                            new FileOutputStream(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 rootCause = e.getCause();
380                if (rootCause instanceof SAXParseException)
381                {
382                    System.out.println("");
383                    System.out.println("Error: " + rootCause.getMessage());
384                    System.out.println(
385                        "       Line: " + 
386                            ((SAXParseException)rootCause).getLineNumber() + 
387                        " Column: " + 
388                            ((SAXParseException)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 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 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 getRelativePath(String file)
433    {
434        if (file == null || file.length()==0)
435            return "";
436        StringTokenizer st = new StringTokenizer(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 sb = new StringBuffer();        
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 targetFile ) throws BuildException
459    {
460        File directory = new File( 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}    

[all classes][org.apache.velocity.anakia]
EMMA 2.0.4015 (stable) (C) Vladimir Roubtsov