View Javadoc
1   /*
2    *   Copyright (C) 2005 Christian Schulte <cs@schulte.it>
3    *   All rights reserved.
4    *
5    *   Redistribution and use in source and binary forms, with or without
6    *   modification, are permitted provided that the following conditions
7    *   are met:
8    *
9    *     o Redistributions of source code must retain the above copyright
10   *       notice, this list of conditions and the following disclaimer.
11   *
12   *     o Redistributions in binary form must reproduce the above copyright
13   *       notice, this list of conditions and the following disclaimer in
14   *       the documentation and/or other materials provided with the
15   *       distribution.
16   *
17   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   *   $JOMC: JomcToolTask.java 5328 2016-09-01 01:05:43Z schulte $
29   *
30   */
31  package org.jomc.ant;
32  
33  import java.net.URL;
34  import java.util.ArrayList;
35  import java.util.Iterator;
36  import java.util.LinkedList;
37  import java.util.List;
38  import java.util.Locale;
39  import java.util.Map;
40  import java.util.logging.Level;
41  import org.apache.commons.lang.StringEscapeUtils;
42  import org.apache.commons.lang.StringUtils;
43  import org.apache.tools.ant.BuildException;
44  import org.apache.tools.ant.Project;
45  import org.jomc.ant.types.KeyValueType;
46  import org.jomc.ant.types.LocaleType;
47  import org.jomc.ant.types.PropertiesResourceType;
48  import org.jomc.model.Implementation;
49  import org.jomc.model.Module;
50  import org.jomc.model.Modules;
51  import org.jomc.model.Specification;
52  import org.jomc.model.modlet.ModelHelper;
53  import org.jomc.modlet.Model;
54  import org.jomc.tools.JomcTool;
55  
56  /**
57   * Base class for executing tool based tasks.
58   *
59   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
60   * @version $JOMC: JomcToolTask.java 5328 2016-09-01 01:05:43Z schulte $
61   */
62  public class JomcToolTask extends JomcModelTask
63  {
64  
65      /**
66       * The default encoding to use for reading templates.
67       */
68      private String defaultTemplateEncoding;
69  
70      /**
71       * The default template profile to use when accessing templates.
72       */
73      private String defaultTemplateProfile;
74  
75      /**
76       * The encoding to use for reading files.
77       */
78      private String inputEncoding;
79  
80      /**
81       * The encoding to use for writing files.
82       */
83      private String outputEncoding;
84  
85      /**
86       * The encoding to use for reading templates.
87       */
88      private String templateEncoding;
89  
90      /**
91       * Additional location to search for templates.
92       */
93      private String templateLocation;
94  
95      /**
96       * The template profile to use when accessing templates.
97       */
98      private String templateProfile;
99  
100     /**
101      * The indentation string ('\t' for tab).
102      */
103     private String indentation;
104 
105     /**
106      * The line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix).
107      */
108     private String lineSeparator;
109 
110     /**
111      * The locale.
112      */
113     private LocaleType locale;
114 
115     /**
116      * The identifier of a specification to process.
117      */
118     private String specification;
119 
120     /**
121      * The identifier of an implementation to process.
122      */
123     private String implementation;
124 
125     /**
126      * The name of a module to process.
127      */
128     private String module;
129 
130     /**
131      * The Velocity runtime properties.
132      */
133     private List<KeyValueType> velocityProperties;
134 
135     /**
136      * The Velocity runtime property resources.
137      */
138     private List<PropertiesResourceType> velocityPropertyResources;
139 
140     /**
141      * The template parameters.
142      */
143     private List<KeyValueType> templateParameters;
144 
145     /**
146      * The template parameter resources.
147      */
148     private List<PropertiesResourceType> templateParameterResources;
149 
150     /**
151      * Creates a new {@code JomcToolTask} instance.
152      */
153     public JomcToolTask()
154     {
155         super();
156     }
157 
158     /**
159      * Gets the encoding to use for reading files.
160      *
161      * @return The encoding to use for reading files or {@code null}.
162      *
163      * @see #setInputEncoding(java.lang.String)
164      */
165     public final String getInputEncoding()
166     {
167         return this.inputEncoding;
168     }
169 
170     /**
171      * Sets the encoding to use for reading files.
172      *
173      * @param value The new encoding to use for reading files or {@code null}.
174      *
175      * @see #getInputEncoding()
176      */
177     public final void setInputEncoding( final String value )
178     {
179         this.inputEncoding = value;
180     }
181 
182     /**
183      * Gets the encoding to use for writing files.
184      *
185      * @return The encoding to use for writing files or {@code null}.
186      *
187      * @see #setOutputEncoding(java.lang.String)
188      */
189     public final String getOutputEncoding()
190     {
191         return this.outputEncoding;
192     }
193 
194     /**
195      * Sets the encoding to use for writing files.
196      *
197      * @param value The new encoding to use for writing files or {@code null}.
198      *
199      * @see #getOutputEncoding()
200      */
201     public final void setOutputEncoding( final String value )
202     {
203         this.outputEncoding = value;
204     }
205 
206     /**
207      * Gets the encoding to use for reading templates.
208      *
209      * @return The encoding to use for reading templates or {@code null}.
210      *
211      * @see #setTemplateEncoding(java.lang.String)
212      *
213      * @deprecated As of JOMC 1.3, replaced by method {@link #getDefaultTemplateEncoding()}. This method will be removed
214      * in JOMC 2.0.
215      */
216     @Deprecated
217     public final String getTemplateEncoding()
218     {
219         return this.templateEncoding;
220     }
221 
222     /**
223      * Sets the encoding to use for reading templates.
224      *
225      * @param value The new encoding to use for reading templates or {@code null}.
226      *
227      * @see #getTemplateEncoding()
228      *
229      * @deprecated As of JOMC 1.3, replaced by method {@link #setDefaultTemplateEncoding(java.lang.String)}. This method
230      * will be removed in JOMC 2.0.
231      */
232     @Deprecated
233     public final void setTemplateEncoding( final String value )
234     {
235         this.templateEncoding = value;
236     }
237 
238     /**
239      * Gets the encoding to use for reading templates.
240      *
241      * @return The encoding to use for reading templates or {@code null}.
242      *
243      * @see #setDefaultTemplateEncoding(java.lang.String)
244      *
245      * @since 1.3
246      */
247     public final String getDefaultTemplateEncoding()
248     {
249         return this.defaultTemplateEncoding;
250     }
251 
252     /**
253      * Sets the encoding to use for reading templates.
254      *
255      * @param value The new encoding to use for reading templates or {@code null}.
256      *
257      * @see #getDefaultTemplateEncoding()
258      *
259      * @since 1.3
260      */
261     public final void setDefaultTemplateEncoding( final String value )
262     {
263         this.defaultTemplateEncoding = value;
264     }
265 
266     /**
267      * Gets the location to search for templates in addition to searching the class path of the task.
268      *
269      * @return The location to search for templates in addition to searching the class path of the task or {@code null}.
270      *
271      * @see #setTemplateLocation(java.lang.String)
272      */
273     public final String getTemplateLocation()
274     {
275         return this.templateLocation;
276     }
277 
278     /**
279      * Sets the location to search for templates in addition to searching the class path of the task.
280      *
281      * @param value The new location to search for templates in addition to searching the class path of the task or
282      * {@code null}.
283      *
284      * @see #getTemplateLocation()
285      */
286     public final void setTemplateLocation( final String value )
287     {
288         this.templateLocation = value;
289     }
290 
291     /**
292      * Gets the default template profile to use when accessing templates.
293      *
294      * @return The default template profile to use when accessing templates or {@code null}.
295      *
296      * @see #setDefaultTemplateProfile(java.lang.String)
297      */
298     public final String getDefaultTemplateProfile()
299     {
300         return this.defaultTemplateProfile;
301     }
302 
303     /**
304      * Sets the default template profile to use when accessing templates.
305      *
306      * @param value The new default template profile to use when accessing templates or {@code null}.
307      *
308      * @see #getDefaultTemplateProfile()
309      */
310     public final void setDefaultTemplateProfile( final String value )
311     {
312         this.defaultTemplateProfile = value;
313     }
314 
315     /**
316      * Gets the template profile to use when accessing templates.
317      *
318      * @return The template profile to use when accessing templates or {@code null}.
319      *
320      * @see #setTemplateProfile(java.lang.String)
321      */
322     public final String getTemplateProfile()
323     {
324         return this.templateProfile;
325     }
326 
327     /**
328      * Sets the template profile to use when accessing templates.
329      *
330      * @param value The new template profile to use when accessing templates or {@code null}.
331      *
332      * @see #getTemplateProfile()
333      */
334     public final void setTemplateProfile( final String value )
335     {
336         this.templateProfile = value;
337     }
338 
339     /**
340      * Gets the indentation string ('\t' for tab).
341      *
342      * @return The indentation string ('\t' for tab) or {@code null}.
343      *
344      * @see #setIndentation(java.lang.String)
345      */
346     public final String getIndentation()
347     {
348         return this.indentation;
349     }
350 
351     /**
352      * Sets the indentation string ('\t' for tab).
353      *
354      * @param value The new indentation string ('\t' for tab) or {@code null}.
355      *
356      * @see #getIndentation()
357      */
358     public final void setIndentation( final String value )
359     {
360         this.indentation = value;
361     }
362 
363     /**
364      * Gets the line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix).
365      *
366      * @return The line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix) or {@code null}.
367      *
368      * @see #setLineSeparator(java.lang.String)
369      */
370     public final String getLineSeparator()
371     {
372         return this.lineSeparator;
373     }
374 
375     /**
376      * Sets the line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix).
377      *
378      * @param value The new line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix) or {@code null}.
379      *
380      * @see #getLineSeparator()
381      */
382     public final void setLineSeparator( final String value )
383     {
384         this.lineSeparator = value;
385     }
386 
387     /**
388      * Gets the locale.
389      *
390      * @return The locale or {@code null}.
391      *
392      * @see #createLocale()
393      */
394     public final LocaleType getLocale()
395     {
396         return this.locale;
397     }
398 
399     /**
400      * Creates a new {@code locale} element instance.
401      *
402      * @return A new {@code locale} element instance.
403      *
404      * @throws BuildException if a value already has been created.
405      *
406      * @see #getLocale()
407      */
408     public LocaleType createLocale()
409     {
410         if ( this.locale != null )
411         {
412             throw new BuildException( Messages.getMessage( "multipleElements", "locale" ), this.getLocation() );
413         }
414 
415         this.locale = new LocaleType();
416         return this.locale;
417     }
418 
419     /**
420      * Gets the identifier of a specification to process.
421      *
422      * @return The identifier of a specification to process or {@code null}.
423      *
424      * @see #setSpecification(java.lang.String)
425      */
426     public final String getSpecification()
427     {
428         return this.specification;
429     }
430 
431     /**
432      * Sets the identifier of a specification to process.
433      *
434      * @param value The new identifier of a specification to process or {@code null}.
435      *
436      * @see #getSpecification()
437      */
438     public final void setSpecification( final String value )
439     {
440         this.specification = value;
441     }
442 
443     /**
444      * Gets the specification to process from a given model.
445      *
446      * @param model The model to get the specification to process from.
447      *
448      * @return The specification to process or {@code null}.
449      *
450      * @throws NullPointerException if {@code model} is {@code null}.
451      *
452      * @see #getSpecification()
453      */
454     public final Specification getSpecification( final Model model )
455     {
456         if ( model == null )
457         {
458             throw new NullPointerException( "model" );
459         }
460 
461         Specification s = null;
462 
463         if ( this.getSpecification() != null )
464         {
465             final Modules modules = ModelHelper.getModules( model );
466 
467             if ( modules != null )
468             {
469                 s = modules.getSpecification( this.getSpecification() );
470             }
471 
472             if ( s == null )
473             {
474                 this.log( Messages.getMessage( "specificationNotFound", this.getSpecification() ), Project.MSG_WARN );
475             }
476         }
477 
478         return s;
479     }
480 
481     /**
482      * Gets the identifier of an implementation to process.
483      *
484      * @return The identifier of an implementation to process or {@code null}.
485      *
486      * @see #setImplementation(java.lang.String)
487      */
488     public final String getImplementation()
489     {
490         return this.implementation;
491     }
492 
493     /**
494      * Sets the identifier of an implementation to process.
495      *
496      * @param value The new identifier of an implementation to process or {@code null}.
497      *
498      * @see #getImplementation()
499      */
500     public final void setImplementation( final String value )
501     {
502         this.implementation = value;
503     }
504 
505     /**
506      * Gets the implementation to process from a given model.
507      *
508      * @param model The model to get the implementation to process from.
509      *
510      * @return The implementation to process or {@code null}.
511      *
512      * @throws NullPointerException if {@code model} is {@code null}.
513      *
514      * @see #getImplementation()
515      */
516     public final Implementation getImplementation( final Model model )
517     {
518         if ( model == null )
519         {
520             throw new NullPointerException( "model" );
521         }
522 
523         Implementation i = null;
524 
525         if ( this.getImplementation() != null )
526         {
527             final Modules modules = ModelHelper.getModules( model );
528 
529             if ( modules != null )
530             {
531                 i = modules.getImplementation( this.getImplementation() );
532             }
533 
534             if ( i == null )
535             {
536                 this.log( Messages.getMessage( "implementationNotFound", this.getImplementation() ), Project.MSG_WARN );
537             }
538         }
539 
540         return i;
541     }
542 
543     /**
544      * Gets the identifier of a module to process.
545      *
546      * @return The identifier of a module to process or {@code null}.
547      *
548      * @see #setModule(java.lang.String)
549      */
550     public final String getModule()
551     {
552         return this.module;
553     }
554 
555     /**
556      * Sets the identifier of a module to process.
557      *
558      * @param value The new identifier of a module to process or {@code null}.
559      *
560      * @see #getModule()
561      */
562     public final void setModule( final String value )
563     {
564         this.module = value;
565     }
566 
567     /**
568      * Gets the module to process from a given model.
569      *
570      * @param model The model to get the module to process from.
571      *
572      * @return The module to process or {@code null}.
573      *
574      * @throws NullPointerException if {@code model} is {@code null}.
575      *
576      * @see #getModule()
577      */
578     public final Module getModule( final Model model )
579     {
580         if ( model == null )
581         {
582             throw new NullPointerException( "model" );
583         }
584 
585         Module m = null;
586 
587         if ( this.getModule() != null )
588         {
589             final Modules modules = ModelHelper.getModules( model );
590 
591             if ( modules != null )
592             {
593                 m = modules.getModule( this.getModule() );
594             }
595 
596             if ( m == null )
597             {
598                 this.log( Messages.getMessage( "moduleNotFound", this.getModule() ), Project.MSG_WARN );
599             }
600         }
601 
602         return m;
603     }
604 
605     /**
606      * Gets a flag indicating all modules are requested to be processed.
607      *
608      * @return {@code true}, if processing of all modules is requested; {@code false}, else.
609      *
610      * @see #getSpecification()
611      * @see #getImplementation()
612      * @see #getModule()
613      */
614     public boolean isModulesProcessingRequested()
615     {
616         return this.getSpecification() == null && this.getImplementation() == null && this.getModule() == null;
617     }
618 
619     /**
620      * Gets the Velocity runtime properties to apply.
621      * <p>
622      * This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
623      * to the returned list will be present inside the object. This is why there is no {@code set} method for the
624      * velocity properties property.
625      * </p>
626      *
627      * @return The Velocity runtime properties to apply.
628      *
629      * @see #createVelocityProperty()
630      */
631     public final List<KeyValueType> getVelocityProperties()
632     {
633         if ( this.velocityProperties == null )
634         {
635             this.velocityProperties = new LinkedList<KeyValueType>();
636         }
637 
638         return this.velocityProperties;
639     }
640 
641     /**
642      * Creates a new {@code velocityProperty} element instance.
643      *
644      * @return A new {@code velocityProperty} element instance.
645      *
646      * @see #getVelocityProperties()
647      */
648     public KeyValueType createVelocityProperty()
649     {
650         final KeyValueType velocityProperty = new KeyValueType();
651         this.getVelocityProperties().add( velocityProperty );
652         return velocityProperty;
653     }
654 
655     /**
656      * Gets the Velocity runtime property resources to apply.
657      * <p>
658      * This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
659      * to the returned list will be present inside the object. This is why there is no {@code set} method for the
660      * velocity property resources property.
661      * </p>
662      *
663      * @return The Velocity runtime property resources to apply.
664      *
665      * @see #createVelocityPropertyResource()
666      */
667     public final List<PropertiesResourceType> getVelocityPropertyResources()
668     {
669         if ( this.velocityPropertyResources == null )
670         {
671             this.velocityPropertyResources = new LinkedList<PropertiesResourceType>();
672         }
673 
674         return this.velocityPropertyResources;
675     }
676 
677     /**
678      * Creates a new {@code velocityPropertyResource} element instance.
679      *
680      * @return A new {@code velocityPropertyResource} element instance.
681      *
682      * @see #getVelocityPropertyResources()
683      */
684     public PropertiesResourceType createVelocityPropertyResource()
685     {
686         final PropertiesResourceType velocityPropertyResource = new PropertiesResourceType();
687         this.getVelocityPropertyResources().add( velocityPropertyResource );
688         return velocityPropertyResource;
689     }
690 
691     /**
692      * Gets the template parameters to apply.
693      * <p>
694      * This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
695      * to the returned list will be present inside the object. This is why there is no {@code set} method for the
696      * template parameters property.
697      * </p>
698      *
699      * @return The template parameters to apply.
700      *
701      * @see #createTemplateParameter()
702      */
703     public final List<KeyValueType> getTemplateParameters()
704     {
705         if ( this.templateParameters == null )
706         {
707             this.templateParameters = new LinkedList<KeyValueType>();
708         }
709 
710         return this.templateParameters;
711     }
712 
713     /**
714      * Creates a new {@code templateParameter} element instance.
715      *
716      * @return A new {@code templateParameter} element instance.
717      *
718      * @see #getTemplateParameters()
719      */
720     public KeyValueType createTemplateParameter()
721     {
722         final KeyValueType templateParameter = new KeyValueType();
723         this.getTemplateParameters().add( templateParameter );
724         return templateParameter;
725     }
726 
727     /**
728      * Gets the template parameter resources to apply.
729      * <p>
730      * This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
731      * to the returned list will be present inside the object. This is why there is no {@code set} method for the
732      * template parameter resources property.
733      * </p>
734      *
735      * @return The template parameter resources to apply.
736      *
737      * @see #createTemplateParameterResource()
738      */
739     public final List<PropertiesResourceType> getTemplateParameterResources()
740     {
741         if ( this.templateParameterResources == null )
742         {
743             this.templateParameterResources = new LinkedList<PropertiesResourceType>();
744         }
745 
746         return this.templateParameterResources;
747     }
748 
749     /**
750      * Creates a new {@code templateParameterResource} element instance.
751      *
752      * @return A new {@code templateParameterResource} element instance.
753      *
754      * @see #getTemplateParameterResources()
755      */
756     public PropertiesResourceType createTemplateParameterResource()
757     {
758         final PropertiesResourceType templateParameterResource = new PropertiesResourceType();
759         this.getTemplateParameterResources().add( templateParameterResource );
760         return templateParameterResource;
761     }
762 
763     /**
764      * {@inheritDoc}
765      */
766     @Override
767     public void preExecuteTask() throws BuildException
768     {
769         super.preExecuteTask();
770 
771         this.assertKeysNotNull( this.getVelocityProperties() );
772         this.assertKeysNotNull( this.getTemplateParameters() );
773         this.assertLocationsNotNull( this.getTemplateParameterResources() );
774         this.assertLocationsNotNull( this.getVelocityPropertyResources() );
775     }
776 
777     /**
778      * {@inheritDoc}
779      */
780     @Override
781     @SuppressWarnings( "deprecation" )
782     public void postExecuteTask() throws BuildException
783     {
784         JomcTool.setDefaultTemplateProfile( null );
785 
786         super.postExecuteTask();
787     }
788 
789     /**
790      * Configures a given {@code JomcTool} instance using the properties of the instance.
791      *
792      * @param tool The tool to configure.
793      *
794      * @throws NullPointerException if {@code tool} is {@code null}.
795      * @throws BuildException if configuring {@code tool} fails.
796      */
797     @SuppressWarnings( "deprecation" )
798     public void configureJomcTool( final JomcTool tool ) throws BuildException
799     {
800         if ( tool == null )
801         {
802             throw new NullPointerException( "tool" );
803         }
804 
805         tool.setExecutorService( this.getExecutorService() );
806         tool.setLogLevel( Level.ALL );
807         tool.setIndentation( StringEscapeUtils.unescapeJava( this.getIndentation() ) );
808         tool.setInputEncoding( this.getInputEncoding() );
809         tool.setLineSeparator( StringEscapeUtils.unescapeJava( this.getLineSeparator() ) );
810         tool.setOutputEncoding( this.getOutputEncoding() );
811         tool.setDefaultTemplateProfile( this.getDefaultTemplateProfile() );
812         tool.setTemplateProfile( this.getTemplateProfile() );
813         tool.getListeners().add( new JomcTool.Listener()
814         {
815 
816             @Override
817             public void onLog( final Level level, final String message, final Throwable throwable )
818             {
819                 super.onLog( level, message, throwable );
820 
821                 if ( level.intValue() >= Level.SEVERE.intValue() )
822                 {
823                     log( message, throwable, Project.MSG_ERR );
824                 }
825                 else if ( level.intValue() >= Level.WARNING.intValue() )
826                 {
827                     log( message, throwable, Project.MSG_WARN );
828                 }
829                 else if ( level.intValue() >= Level.INFO.intValue() )
830                 {
831                     log( message, throwable, Project.MSG_INFO );
832                 }
833                 else
834                 {
835                     log( message, throwable, Project.MSG_DEBUG );
836                 }
837             }
838 
839         } );
840 
841         if ( this.getTemplateEncoding() != null )
842         {
843             this.log( Messages.getMessage( "deprecationWarning", "templateEncoding", "defaultTemplateEncoding" ),
844                       null, Project.MSG_WARN );
845 
846             tool.setDefaultTemplateEncoding( this.getTemplateEncoding() );
847         }
848         else
849         {
850             tool.setDefaultTemplateEncoding( this.getDefaultTemplateEncoding() );
851         }
852 
853         for ( int i = 0, s0 = this.getVelocityPropertyResources().size(); i < s0; i++ )
854         {
855             for ( final Map.Entry<Object, Object> e
856                       : this.getProperties( this.getVelocityPropertyResources().get( i ) ).entrySet() )
857             {
858                 if ( e.getValue() != null )
859                 {
860                     tool.getVelocityEngine().setProperty( e.getKey().toString(), e.getValue() );
861                 }
862                 else
863                 {
864                     tool.getVelocityEngine().clearProperty( e.getKey().toString() );
865                 }
866             }
867         }
868 
869         for ( int i = 0, s0 = this.getVelocityProperties().size(); i < s0; i++ )
870         {
871             final KeyValueType p = this.getVelocityProperties().get( i );
872             final Object object = p.getObject( this.getLocation() );
873 
874             if ( object != null )
875             {
876                 tool.getVelocityEngine().setProperty( p.getKey(), object );
877             }
878             else
879             {
880                 tool.getVelocityEngine().clearProperty( p.getKey() );
881             }
882         }
883 
884         for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() )
885         {
886             tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
887         }
888 
889         for ( final Iterator<Map.Entry<?, ?>> it = this.getProject().getProperties().entrySet().iterator();
890               it.hasNext(); )
891         {
892             final Map.Entry<?, ?> e = it.next();
893             tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
894         }
895 
896         for ( int i = 0, s0 = this.getTemplateParameterResources().size(); i < s0; i++ )
897         {
898             for ( final Map.Entry<Object, Object> e
899                       : this.getProperties( this.getTemplateParameterResources().get( i ) ).entrySet() )
900             {
901                 if ( e.getValue() != null )
902                 {
903                     tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
904                 }
905                 else
906                 {
907                     tool.getTemplateParameters().remove( e.getKey().toString() );
908                 }
909             }
910         }
911 
912         for ( int i = 0, s0 = this.getTemplateParameters().size(); i < s0; i++ )
913         {
914             final KeyValueType p = this.getTemplateParameters().get( i );
915             final Object object = p.getObject( this.getLocation() );
916 
917             if ( object != null )
918             {
919                 tool.getTemplateParameters().put( p.getKey(), object );
920             }
921             else
922             {
923                 tool.getTemplateParameters().remove( p.getKey() );
924             }
925         }
926 
927         if ( this.getTemplateLocation() != null )
928         {
929             final URL url = this.getDirectory( this.getTemplateLocation() );
930             tool.setTemplateLocation( url );
931 
932             if ( url == null )
933             {
934                 this.log( Messages.getMessage( "templateLocationNotFound", this.getTemplateLocation() ),
935                           Project.MSG_WARN );
936 
937             }
938         }
939 
940         if ( this.getLocale() != null )
941         {
942             tool.setLocale( new Locale( StringUtils.defaultString( this.getLocale().getLanguage() ),
943                                         StringUtils.defaultString( this.getLocale().getCountry() ),
944                                         StringUtils.defaultString( this.getLocale().getVariant() ) ) );
945 
946         }
947     }
948 
949     /**
950      * {@inheritDoc}
951      */
952     @Override
953     public JomcToolTask clone()
954     {
955         final JomcToolTask clone = (JomcToolTask) super.clone();
956 
957         if ( this.locale != null )
958         {
959             clone.locale = this.locale.clone();
960         }
961 
962         if ( this.velocityPropertyResources != null )
963         {
964             clone.velocityPropertyResources =
965                 new ArrayList<PropertiesResourceType>( this.velocityPropertyResources.size() );
966 
967             for ( final PropertiesResourceType e : this.velocityPropertyResources )
968             {
969                 clone.velocityPropertyResources.add( e.clone() );
970             }
971         }
972 
973         if ( this.velocityProperties != null )
974         {
975             clone.velocityProperties = new ArrayList<KeyValueType>( this.velocityProperties.size() );
976 
977             for ( final KeyValueType e : this.velocityProperties )
978             {
979                 clone.velocityProperties.add( e.clone() );
980             }
981         }
982 
983         if ( this.velocityPropertyResources != null )
984         {
985             clone.velocityPropertyResources =
986                 new ArrayList<PropertiesResourceType>( this.velocityPropertyResources.size() );
987 
988             for ( final PropertiesResourceType e : this.velocityPropertyResources )
989             {
990                 clone.velocityPropertyResources.add( e.clone() );
991             }
992         }
993 
994         if ( this.templateParameters != null )
995         {
996             clone.templateParameters = new ArrayList<KeyValueType>( this.templateParameters.size() );
997 
998             for ( final KeyValueType e : this.templateParameters )
999             {
1000                 clone.templateParameters.add( e.clone() );
1001             }
1002         }
1003 
1004         if ( this.templateParameterResources != null )
1005         {
1006             clone.templateParameterResources =
1007                 new ArrayList<PropertiesResourceType>( this.templateParameterResources.size() );
1008 
1009             for ( final PropertiesResourceType e : this.templateParameterResources )
1010             {
1011                 clone.templateParameterResources.add( e.clone() );
1012             }
1013         }
1014 
1015         return clone;
1016     }
1017 
1018 }