001    /*
002     *   Copyright (C) Christian Schulte, 2005-206
003     *   All rights reserved.
004     *
005     *   Redistribution and use in source and binary forms, with or without
006     *   modification, are permitted provided that the following conditions
007     *   are met:
008     *
009     *     o Redistributions of source code must retain the above copyright
010     *       notice, this list of conditions and the following disclaimer.
011     *
012     *     o Redistributions in binary form must reproduce the above copyright
013     *       notice, this list of conditions and the following disclaimer in
014     *       the documentation and/or other materials provided with the
015     *       distribution.
016     *
017     *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
018     *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
019     *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
020     *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
021     *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022     *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023     *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024     *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025     *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026     *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     *
028     *   $JOMC: JomcToolTask.java 3878 2011-10-24 00:58:09Z schulte2005 $
029     *
030     */
031    package org.jomc.ant;
032    
033    import java.io.IOException;
034    import java.net.URL;
035    import java.util.ArrayList;
036    import java.util.Iterator;
037    import java.util.LinkedList;
038    import java.util.List;
039    import java.util.Locale;
040    import java.util.Map;
041    import java.util.logging.Level;
042    import org.apache.commons.lang.StringEscapeUtils;
043    import org.apache.commons.lang.StringUtils;
044    import org.apache.tools.ant.BuildException;
045    import org.apache.tools.ant.Project;
046    import org.jomc.ant.types.KeyValueType;
047    import org.jomc.ant.types.LocaleType;
048    import org.jomc.ant.types.PropertiesResourceType;
049    import org.jomc.model.Implementation;
050    import org.jomc.model.Module;
051    import org.jomc.model.Modules;
052    import org.jomc.model.Specification;
053    import org.jomc.model.modlet.ModelHelper;
054    import org.jomc.modlet.Model;
055    import org.jomc.tools.JomcTool;
056    
057    /**
058     * Base class for executing tool based tasks.
059     *
060     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
061     * @version $JOMC: JomcToolTask.java 3878 2011-10-24 00:58:09Z schulte2005 $
062     */
063    public class JomcToolTask extends JomcModelTask
064    {
065    
066        /** The default template profile to use when accessing templates. */
067        private String defaultTemplateProfile;
068    
069        /** The encoding to use for reading files. */
070        private String inputEncoding;
071    
072        /** The encoding to use for writing files. */
073        private String outputEncoding;
074    
075        /** The encoding to use for reading templates. */
076        private String templateEncoding;
077    
078        /** Additional location to search for templates. */
079        private String templateLocation;
080    
081        /** The template profile to use when accessing templates. */
082        private String templateProfile;
083    
084        /** The indentation string ('\t' for tab). */
085        private String indentation;
086    
087        /** The line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix). */
088        private String lineSeparator;
089    
090        /** The locale. */
091        private LocaleType locale;
092    
093        /** The identifier of a specification to process. */
094        private String specification;
095    
096        /** The identifier of an implementation to process. */
097        private String implementation;
098    
099        /** The name of a module to process. */
100        private String module;
101    
102        /** The Velocity runtime properties. */
103        private List<KeyValueType> velocityProperties;
104    
105        /** The Velocity runtime property resources. */
106        private List<PropertiesResourceType> velocityPropertyResources;
107    
108        /** The template parameters. */
109        private List<KeyValueType> templateParameters;
110    
111        /** The template parameter resources. */
112        private List<PropertiesResourceType> templateParameterResources;
113    
114        /** Creates a new {@code JomcToolTask} instance. */
115        public JomcToolTask()
116        {
117            super();
118        }
119    
120        /**
121         * Gets the encoding to use for reading files.
122         *
123         * @return The encoding to use for reading files or {@code null}.
124         *
125         * @see #setInputEncoding(java.lang.String)
126         */
127        public final String getInputEncoding()
128        {
129            return this.inputEncoding;
130        }
131    
132        /**
133         * Sets the encoding to use for reading files.
134         *
135         * @param value The new encoding to use for reading files or {@code null}.
136         *
137         * @see #getInputEncoding()
138         */
139        public final void setInputEncoding( final String value )
140        {
141            this.inputEncoding = value;
142        }
143    
144        /**
145         * Gets the encoding to use for writing files.
146         *
147         * @return The encoding to use for writing files or {@code null}.
148         *
149         * @see #setOutputEncoding(java.lang.String)
150         */
151        public final String getOutputEncoding()
152        {
153            return this.outputEncoding;
154        }
155    
156        /**
157         * Sets the encoding to use for writing files.
158         *
159         * @param value The new encoding to use for writing files or {@code null}.
160         *
161         * @see #getOutputEncoding()
162         */
163        public final void setOutputEncoding( final String value )
164        {
165            this.outputEncoding = value;
166        }
167    
168        /**
169         * Gets the encoding to use for reading templates.
170         *
171         * @return The encoding to use for reading templates or {@code null}.
172         *
173         * @see #setTemplateEncoding(java.lang.String)
174         */
175        public final String getTemplateEncoding()
176        {
177            return this.templateEncoding;
178        }
179    
180        /**
181         * Sets the encoding to use for reading templates.
182         *
183         * @param value The new encoding to use for reading templates or {@code null}.
184         *
185         * @see #getTemplateEncoding()
186         */
187        public final void setTemplateEncoding( final String value )
188        {
189            this.templateEncoding = value;
190        }
191    
192        /**
193         * Gets the location to search for templates in addition to searching the class path of the task.
194         *
195         * @return The location to search for templates in addition to searching the class path of the task or {@code null}.
196         *
197         * @see #setTemplateLocation(java.lang.String)
198         */
199        public final String getTemplateLocation()
200        {
201            return this.templateLocation;
202        }
203    
204        /**
205         * Sets the location to search for templates in addition to searching the class path of the task.
206         *
207         * @param value The new location to search for templates in addition to searching the class path of the task or
208         * {@code null}.
209         *
210         * @see #getTemplateLocation()
211         */
212        public final void setTemplateLocation( final String value )
213        {
214            this.templateLocation = value;
215        }
216    
217        /**
218         * Gets the default template profile to use when accessing templates.
219         *
220         * @return The default template profile to use when accessing templates or {@code null}.
221         *
222         * @see #setDefaultTemplateProfile(java.lang.String)
223         */
224        public final String getDefaultTemplateProfile()
225        {
226            return this.defaultTemplateProfile;
227        }
228    
229        /**
230         * Sets the default template profile to use when accessing templates.
231         *
232         * @param value The new default template profile to use when accessing templates or {@code null}.
233         *
234         * @see #getDefaultTemplateProfile()
235         */
236        public final void setDefaultTemplateProfile( final String value )
237        {
238            this.defaultTemplateProfile = value;
239        }
240    
241        /**
242         * Gets the template profile to use when accessing templates.
243         *
244         * @return The template profile to use when accessing templates or {@code null}.
245         *
246         * @see #setTemplateProfile(java.lang.String)
247         */
248        public final String getTemplateProfile()
249        {
250            return this.templateProfile;
251        }
252    
253        /**
254         * Sets the template profile to use when accessing templates.
255         *
256         * @param value The new template profile to use when accessing templates or {@code null}.
257         *
258         * @see #getTemplateProfile()
259         */
260        public final void setTemplateProfile( final String value )
261        {
262            this.templateProfile = value;
263        }
264    
265        /**
266         * Gets the indentation string ('\t' for tab).
267         *
268         * @return The indentation string ('\t' for tab) or {@code null}.
269         *
270         * @see #setIndentation(java.lang.String)
271         */
272        public final String getIndentation()
273        {
274            return this.indentation;
275        }
276    
277        /**
278         * Sets the indentation string ('\t' for tab).
279         *
280         * @param value The new indentation string ('\t' for tab) or {@code null}.
281         *
282         * @see #getIndentation()
283         */
284        public final void setIndentation( final String value )
285        {
286            this.indentation = value;
287        }
288    
289        /**
290         * Gets the line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix).
291         *
292         * @return The line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix) or {@code null}.
293         *
294         * @see #setLineSeparator(java.lang.String)
295         */
296        public final String getLineSeparator()
297        {
298            return this.lineSeparator;
299        }
300    
301        /**
302         * Sets the line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix).
303         *
304         * @param value The new line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix) or {@code null}.
305         *
306         * @see #getLineSeparator()
307         */
308        public final void setLineSeparator( final String value )
309        {
310            this.lineSeparator = value;
311        }
312    
313        /**
314         * Gets the locale.
315         *
316         * @return The locale or {@code null}.
317         *
318         * @see #createLocale()
319         */
320        public final LocaleType getLocale()
321        {
322            return this.locale;
323        }
324    
325        /**
326         * Creates a new {@code locale} element instance.
327         *
328         * @return A new {@code locale} element instance.
329         *
330         * @throws BuildException if a value already has been created.
331         *
332         * @see #getLocale()
333         */
334        public LocaleType createLocale()
335        {
336            if ( this.locale != null )
337            {
338                throw new BuildException( Messages.getMessage( "multipleElements", "locale" ), this.getLocation() );
339            }
340    
341            this.locale = new LocaleType();
342            return this.locale;
343        }
344    
345        /**
346         * Gets the identifier of a specification to process.
347         *
348         * @return The identifier of a specification to process or {@code null}.
349         *
350         * @see #setSpecification(java.lang.String)
351         */
352        public final String getSpecification()
353        {
354            return this.specification;
355        }
356    
357        /**
358         * Sets the identifier of a specification to process.
359         *
360         * @param value The new identifier of a specification to process or {@code null}.
361         *
362         * @see #getSpecification()
363         */
364        public final void setSpecification( final String value )
365        {
366            this.specification = value;
367        }
368    
369        /**
370         * Gets the specification to process from a given model.
371         *
372         * @param model The model to get the specification to process from.
373         *
374         * @return The specification to process or {@code null}.
375         *
376         * @throws NullPointerException if {@code model} is {@code null}.
377         *
378         * @see #getSpecification()
379         */
380        public final Specification getSpecification( final Model model )
381        {
382            if ( model == null )
383            {
384                throw new NullPointerException( "model" );
385            }
386    
387            Specification s = null;
388    
389            if ( this.getSpecification() != null )
390            {
391                final Modules modules = ModelHelper.getModules( model );
392    
393                if ( modules != null )
394                {
395                    s = modules.getSpecification( this.getSpecification() );
396                }
397    
398                if ( s == null )
399                {
400                    this.log( Messages.getMessage( "specificationNotFound", this.getSpecification() ), Project.MSG_WARN );
401                }
402            }
403    
404            return s;
405        }
406    
407        /**
408         * Gets the identifier of an implementation to process.
409         *
410         * @return The identifier of an implementation to process or {@code null}.
411         *
412         * @see #setImplementation(java.lang.String)
413         */
414        public final String getImplementation()
415        {
416            return this.implementation;
417        }
418    
419        /**
420         * Sets the identifier of an implementation to process.
421         *
422         * @param value The new identifier of an implementation to process or {@code null}.
423         *
424         * @see #getImplementation()
425         */
426        public final void setImplementation( final String value )
427        {
428            this.implementation = value;
429        }
430    
431        /**
432         * Gets the implementation to process from a given model.
433         *
434         * @param model The model to get the implementation to process from.
435         *
436         * @return The implementation to process or {@code null}.
437         *
438         * @throws NullPointerException if {@code model} is {@code null}.
439         *
440         * @see #getImplementation()
441         */
442        public final Implementation getImplementation( final Model model )
443        {
444            if ( model == null )
445            {
446                throw new NullPointerException( "model" );
447            }
448    
449            Implementation i = null;
450    
451            if ( this.getImplementation() != null )
452            {
453                final Modules modules = ModelHelper.getModules( model );
454    
455                if ( modules != null )
456                {
457                    i = modules.getImplementation( this.getImplementation() );
458                }
459    
460                if ( i == null )
461                {
462                    this.log( Messages.getMessage( "implementationNotFound", this.getImplementation() ), Project.MSG_WARN );
463                }
464            }
465    
466            return i;
467        }
468    
469        /**
470         * Gets the identifier of a module to process.
471         *
472         * @return The identifier of a module to process or {@code null}.
473         *
474         * @see #setModule(java.lang.String)
475         */
476        public final String getModule()
477        {
478            return this.module;
479        }
480    
481        /**
482         * Sets the identifier of a module to process.
483         *
484         * @param value The new identifier of a module to process or {@code null}.
485         *
486         * @see #getModule()
487         */
488        public final void setModule( final String value )
489        {
490            this.module = value;
491        }
492    
493        /**
494         * Gets the module to process from a given model.
495         *
496         * @param model The model to get the module to process from.
497         *
498         * @return The module to process or {@code null}.
499         *
500         * @throws NullPointerException if {@code model} is {@code null}.
501         *
502         * @see #getModule()
503         */
504        public final Module getModule( final Model model )
505        {
506            if ( model == null )
507            {
508                throw new NullPointerException( "model" );
509            }
510    
511            Module m = null;
512    
513            if ( this.getModule() != null )
514            {
515                final Modules modules = ModelHelper.getModules( model );
516    
517                if ( modules != null )
518                {
519                    m = modules.getModule( this.getModule() );
520                }
521    
522                if ( m == null )
523                {
524                    this.log( Messages.getMessage( "moduleNotFound", this.getModule() ), Project.MSG_WARN );
525                }
526            }
527    
528            return m;
529        }
530    
531        /**
532         * Gets a flag indicating all modules are requested to be processed.
533         *
534         * @return {@code true}, if processing of all modules is requested; {@code false}, else.
535         *
536         * @see #getSpecification()
537         * @see #getImplementation()
538         * @see #getModule()
539         */
540        public boolean isModulesProcessingRequested()
541        {
542            return this.getSpecification() == null && this.getImplementation() == null && this.getModule() == null;
543        }
544    
545        /**
546         * Gets the Velocity runtime properties to apply.
547         * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
548         * to the returned list will be present inside the object. This is why there is no {@code set} method for the
549         * velocity properties property.</p>
550         *
551         * @return The Velocity runtime properties to apply.
552         *
553         * @see #createVelocityProperty()
554         */
555        public final List<KeyValueType> getVelocityProperties()
556        {
557            if ( this.velocityProperties == null )
558            {
559                this.velocityProperties = new LinkedList<KeyValueType>();
560            }
561    
562            return this.velocityProperties;
563        }
564    
565        /**
566         * Creates a new {@code velocityProperty} element instance.
567         *
568         * @return A new {@code velocityProperty} element instance.
569         *
570         * @see #getVelocityProperties()
571         */
572        public KeyValueType createVelocityProperty()
573        {
574            final KeyValueType velocityProperty = new KeyValueType();
575            this.getVelocityProperties().add( velocityProperty );
576            return velocityProperty;
577        }
578    
579        /**
580         * Gets the Velocity runtime property resources to apply.
581         * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
582         * to the returned list will be present inside the object. This is why there is no {@code set} method for the
583         * velocity property resources property.</p>
584         *
585         * @return The Velocity runtime property resources to apply.
586         *
587         * @see #createVelocityPropertyResource()
588         */
589        public final List<PropertiesResourceType> getVelocityPropertyResources()
590        {
591            if ( this.velocityPropertyResources == null )
592            {
593                this.velocityPropertyResources = new LinkedList<PropertiesResourceType>();
594            }
595    
596            return this.velocityPropertyResources;
597        }
598    
599        /**
600         * Creates a new {@code velocityPropertyResource} element instance.
601         *
602         * @return A new {@code velocityPropertyResource} element instance.
603         *
604         * @see #getVelocityPropertyResources()
605         */
606        public PropertiesResourceType createVelocityPropertyResource()
607        {
608            final PropertiesResourceType velocityPropertyResource = new PropertiesResourceType();
609            this.getVelocityPropertyResources().add( velocityPropertyResource );
610            return velocityPropertyResource;
611        }
612    
613        /**
614         * Gets the template parameters to apply.
615         * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
616         * to the returned list will be present inside the object. This is why there is no {@code set} method for the
617         * template parameters property.</p>
618         *
619         * @return The template parameters to apply.
620         *
621         * @see #createTemplateParameter()
622         */
623        public final List<KeyValueType> getTemplateParameters()
624        {
625            if ( this.templateParameters == null )
626            {
627                this.templateParameters = new LinkedList<KeyValueType>();
628            }
629    
630            return this.templateParameters;
631        }
632    
633        /**
634         * Creates a new {@code templateParameter} element instance.
635         *
636         * @return A new {@code templateParameter} element instance.
637         *
638         * @see #getTemplateParameters()
639         */
640        public KeyValueType createTemplateParameter()
641        {
642            final KeyValueType templateParameter = new KeyValueType();
643            this.getTemplateParameters().add( templateParameter );
644            return templateParameter;
645        }
646    
647        /**
648         * Gets the template parameter resources to apply.
649         * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
650         * to the returned list will be present inside the object. This is why there is no {@code set} method for the
651         * template parameter resources property.</p>
652         *
653         * @return The template parameter resources to apply.
654         *
655         * @see #createTemplateParameterResource()
656         */
657        public final List<PropertiesResourceType> getTemplateParameterResources()
658        {
659            if ( this.templateParameterResources == null )
660            {
661                this.templateParameterResources = new LinkedList<PropertiesResourceType>();
662            }
663    
664            return this.templateParameterResources;
665        }
666    
667        /**
668         * Creates a new {@code templateParameterResource} element instance.
669         *
670         * @return A new {@code templateParameterResource} element instance.
671         *
672         * @see #getTemplateParameterResources()
673         */
674        public PropertiesResourceType createTemplateParameterResource()
675        {
676            final PropertiesResourceType templateParameterResource = new PropertiesResourceType();
677            this.getTemplateParameterResources().add( templateParameterResource );
678            return templateParameterResource;
679        }
680    
681        /** {@inheritDoc} */
682        @Override
683        public void preExecuteTask() throws BuildException
684        {
685            super.preExecuteTask();
686    
687            this.assertKeysNotNull( this.getVelocityProperties() );
688            this.assertKeysNotNull( this.getTemplateParameters() );
689            this.assertLocationsNotNull( this.getTemplateParameterResources() );
690            this.assertLocationsNotNull( this.getVelocityPropertyResources() );
691        }
692    
693        /** {@inheritDoc} */
694        @Override
695        public void postExecuteTask() throws BuildException
696        {
697            JomcTool.setDefaultTemplateProfile( null );
698    
699            super.postExecuteTask();
700        }
701    
702        /**
703         * Configures a given {@code JomcTool} instance using the properties of the instance.
704         *
705         * @param tool The tool to configure.
706         *
707         * @throws NullPointerException if {@code tool} is {@code null}.
708         * @throws BuildException if configuring {@code tool} fails.
709         */
710        public void configureJomcTool( final JomcTool tool ) throws BuildException
711        {
712            if ( tool == null )
713            {
714                throw new NullPointerException( "tool" );
715            }
716    
717            try
718            {
719                tool.setLogLevel( Level.ALL );
720                tool.setIndentation( StringEscapeUtils.unescapeJava( this.getIndentation() ) );
721                tool.setInputEncoding( this.getInputEncoding() );
722                tool.setLineSeparator( StringEscapeUtils.unescapeJava( this.getLineSeparator() ) );
723                tool.setOutputEncoding( this.getOutputEncoding() );
724                tool.setTemplateEncoding( this.getTemplateEncoding() );
725                tool.setDefaultTemplateProfile( this.getDefaultTemplateProfile() );
726                tool.setTemplateProfile( this.getTemplateProfile() );
727                tool.getListeners().add( new JomcTool.Listener()
728                {
729    
730                    @Override
731                    public void onLog( final Level level, final String message, final Throwable throwable )
732                    {
733                        super.onLog( level, message, throwable );
734    
735                        if ( level.intValue() >= Level.SEVERE.intValue() )
736                        {
737                            log( message, throwable, Project.MSG_ERR );
738                        }
739                        else if ( level.intValue() >= Level.WARNING.intValue() )
740                        {
741                            log( message, throwable, Project.MSG_WARN );
742                        }
743                        else if ( level.intValue() >= Level.INFO.intValue() )
744                        {
745                            log( message, throwable, Project.MSG_INFO );
746                        }
747                        else
748                        {
749                            log( message, throwable, Project.MSG_DEBUG );
750                        }
751                    }
752    
753                } );
754    
755                for ( int i = 0, s0 = this.getVelocityPropertyResources().size(); i < s0; i++ )
756                {
757                    for ( Map.Entry<Object, Object> e :
758                          this.getProperties( this.getVelocityPropertyResources().get( i ) ).entrySet() )
759                    {
760                        if ( e.getValue() != null )
761                        {
762                            tool.getVelocityEngine().setProperty( e.getKey().toString(), e.getValue() );
763                        }
764                        else
765                        {
766                            tool.getVelocityEngine().clearProperty( e.getKey().toString() );
767                        }
768                    }
769                }
770    
771                for ( int i = 0, s0 = this.getVelocityProperties().size(); i < s0; i++ )
772                {
773                    final KeyValueType p = this.getVelocityProperties().get( i );
774                    final Object object = p.getObject( this.getLocation() );
775    
776                    if ( object != null )
777                    {
778                        tool.getVelocityEngine().setProperty( p.getKey(), object );
779                    }
780                    else
781                    {
782                        tool.getVelocityEngine().clearProperty( p.getKey() );
783                    }
784                }
785    
786                for ( Map.Entry<Object, Object> e : System.getProperties().entrySet() )
787                {
788                    tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
789                }
790    
791                for ( final Iterator<Map.Entry<?, ?>> it = this.getProject().getProperties().entrySet().iterator();
792                      it.hasNext(); )
793                {
794                    final Map.Entry<?, ?> e = it.next();
795                    tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
796                }
797    
798                for ( int i = 0, s0 = this.getTemplateParameterResources().size(); i < s0; i++ )
799                {
800                    for ( Map.Entry<Object, Object> e :
801                          this.getProperties( this.getTemplateParameterResources().get( i ) ).entrySet() )
802                    {
803                        if ( e.getValue() != null )
804                        {
805                            tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
806                        }
807                        else
808                        {
809                            tool.getTemplateParameters().remove( e.getKey().toString() );
810                        }
811                    }
812                }
813    
814                for ( int i = 0, s0 = this.getTemplateParameters().size(); i < s0; i++ )
815                {
816                    final KeyValueType p = this.getTemplateParameters().get( i );
817                    final Object object = p.getObject( this.getLocation() );
818    
819                    if ( object != null )
820                    {
821                        tool.getTemplateParameters().put( p.getKey(), object );
822                    }
823                    else
824                    {
825                        tool.getTemplateParameters().remove( p.getKey() );
826                    }
827                }
828    
829                if ( this.getTemplateLocation() != null )
830                {
831                    final URL url = this.getDirectory( this.getTemplateLocation() );
832                    tool.setTemplateLocation( url );
833    
834                    if ( url == null )
835                    {
836                        this.log( Messages.getMessage( "templateLocationNotFound", this.getTemplateLocation() ),
837                                  Project.MSG_WARN );
838    
839                    }
840                }
841    
842                if ( this.getLocale() != null )
843                {
844                    tool.setLocale( new Locale( StringUtils.defaultString( this.getLocale().getLanguage() ),
845                                                StringUtils.defaultString( this.getLocale().getCountry() ),
846                                                StringUtils.defaultString( this.getLocale().getVariant() ) ) );
847    
848                }
849            }
850            catch ( final IOException e )
851            {
852                throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
853            }
854        }
855    
856        /** {@inheritDoc} */
857        @Override
858        public JomcToolTask clone()
859        {
860            final JomcToolTask clone = (JomcToolTask) super.clone();
861    
862            if ( this.locale != null )
863            {
864                clone.locale = this.locale.clone();
865            }
866    
867            if ( this.velocityPropertyResources != null )
868            {
869                clone.velocityPropertyResources =
870                    new ArrayList<PropertiesResourceType>( this.velocityPropertyResources.size() );
871    
872                for ( PropertiesResourceType e : this.velocityPropertyResources )
873                {
874                    clone.velocityPropertyResources.add( e.clone() );
875                }
876            }
877    
878            if ( this.velocityProperties != null )
879            {
880                clone.velocityProperties = new ArrayList<KeyValueType>( this.velocityProperties.size() );
881    
882                for ( KeyValueType e : this.velocityProperties )
883                {
884                    clone.velocityProperties.add( e.clone() );
885                }
886            }
887    
888            if ( this.velocityPropertyResources != null )
889            {
890                clone.velocityPropertyResources =
891                    new ArrayList<PropertiesResourceType>( this.velocityPropertyResources.size() );
892    
893                for ( PropertiesResourceType e : this.velocityPropertyResources )
894                {
895                    clone.velocityPropertyResources.add( e.clone() );
896                }
897            }
898    
899            if ( this.templateParameters != null )
900            {
901                clone.templateParameters = new ArrayList<KeyValueType>( this.templateParameters.size() );
902    
903                for ( KeyValueType e : this.templateParameters )
904                {
905                    clone.templateParameters.add( e.clone() );
906                }
907            }
908    
909            if ( this.templateParameterResources != null )
910            {
911                clone.templateParameterResources =
912                    new ArrayList<PropertiesResourceType>( this.templateParameterResources.size() );
913    
914                for ( PropertiesResourceType e : this.templateParameterResources )
915                {
916                    clone.templateParameterResources.add( e.clone() );
917                }
918            }
919    
920            return clone;
921        }
922    
923    }