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