001/*
002 *   Copyright (C) 2005 Christian Schulte <cs@schulte.it>
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 5328 2016-09-01 01:05:43Z schulte $
029 *
030 */
031package org.jomc.ant;
032
033import java.net.URL;
034import java.util.ArrayList;
035import java.util.Iterator;
036import java.util.LinkedList;
037import java.util.List;
038import java.util.Locale;
039import java.util.Map;
040import java.util.logging.Level;
041import org.apache.commons.lang.StringEscapeUtils;
042import org.apache.commons.lang.StringUtils;
043import org.apache.tools.ant.BuildException;
044import org.apache.tools.ant.Project;
045import org.jomc.ant.types.KeyValueType;
046import org.jomc.ant.types.LocaleType;
047import org.jomc.ant.types.PropertiesResourceType;
048import org.jomc.model.Implementation;
049import org.jomc.model.Module;
050import org.jomc.model.Modules;
051import org.jomc.model.Specification;
052import org.jomc.model.modlet.ModelHelper;
053import org.jomc.modlet.Model;
054import org.jomc.tools.JomcTool;
055
056/**
057 * Base class for executing tool based tasks.
058 *
059 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
060 * @version $JOMC: JomcToolTask.java 5328 2016-09-01 01:05:43Z schulte $
061 */
062public class JomcToolTask extends JomcModelTask
063{
064
065    /**
066     * The default encoding to use for reading templates.
067     */
068    private String defaultTemplateEncoding;
069
070    /**
071     * The default template profile to use when accessing templates.
072     */
073    private String defaultTemplateProfile;
074
075    /**
076     * The encoding to use for reading files.
077     */
078    private String inputEncoding;
079
080    /**
081     * The encoding to use for writing files.
082     */
083    private String outputEncoding;
084
085    /**
086     * The encoding to use for reading templates.
087     */
088    private String templateEncoding;
089
090    /**
091     * Additional location to search for templates.
092     */
093    private String templateLocation;
094
095    /**
096     * The template profile to use when accessing templates.
097     */
098    private String templateProfile;
099
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}