JomcToolTask.java
/*
* Copyright (C) Christian Schulte <cs@schulte.it>, 2005-206
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* o Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $JOMC: JomcToolTask.java 5043 2015-05-27 07:03:39Z schulte $
*
*/
package org.jomc.ant;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.jomc.ant.types.KeyValueType;
import org.jomc.ant.types.LocaleType;
import org.jomc.ant.types.PropertiesResourceType;
import org.jomc.model.Implementation;
import org.jomc.model.Module;
import org.jomc.model.Modules;
import org.jomc.model.Specification;
import org.jomc.model.modlet.ModelHelper;
import org.jomc.modlet.Model;
import org.jomc.tools.JomcTool;
/**
* Base class for executing tool based tasks.
*
* @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
* @version $JOMC: JomcToolTask.java 5043 2015-05-27 07:03:39Z schulte $
*/
public class JomcToolTask extends JomcModelTask
{
/**
* The default encoding to use for reading templates.
*/
private String defaultTemplateEncoding;
/**
* The default template profile to use when accessing templates.
*/
private String defaultTemplateProfile;
/**
* The encoding to use for reading files.
*/
private String inputEncoding;
/**
* The encoding to use for writing files.
*/
private String outputEncoding;
/**
* The encoding to use for reading templates.
*/
private String templateEncoding;
/**
* Additional location to search for templates.
*/
private String templateLocation;
/**
* The template profile to use when accessing templates.
*/
private String templateProfile;
/**
* The indentation string ('\t' for tab).
*/
private String indentation;
/**
* The line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix).
*/
private String lineSeparator;
/**
* The locale.
*/
private LocaleType locale;
/**
* The identifier of a specification to process.
*/
private String specification;
/**
* The identifier of an implementation to process.
*/
private String implementation;
/**
* The name of a module to process.
*/
private String module;
/**
* The Velocity runtime properties.
*/
private List<KeyValueType> velocityProperties;
/**
* The Velocity runtime property resources.
*/
private List<PropertiesResourceType> velocityPropertyResources;
/**
* The template parameters.
*/
private List<KeyValueType> templateParameters;
/**
* The template parameter resources.
*/
private List<PropertiesResourceType> templateParameterResources;
/**
* Creates a new {@code JomcToolTask} instance.
*/
public JomcToolTask()
{
super();
}
/**
* Gets the encoding to use for reading files.
*
* @return The encoding to use for reading files or {@code null}.
*
* @see #setInputEncoding(java.lang.String)
*/
public final String getInputEncoding()
{
return this.inputEncoding;
}
/**
* Sets the encoding to use for reading files.
*
* @param value The new encoding to use for reading files or {@code null}.
*
* @see #getInputEncoding()
*/
public final void setInputEncoding( final String value )
{
this.inputEncoding = value;
}
/**
* Gets the encoding to use for writing files.
*
* @return The encoding to use for writing files or {@code null}.
*
* @see #setOutputEncoding(java.lang.String)
*/
public final String getOutputEncoding()
{
return this.outputEncoding;
}
/**
* Sets the encoding to use for writing files.
*
* @param value The new encoding to use for writing files or {@code null}.
*
* @see #getOutputEncoding()
*/
public final void setOutputEncoding( final String value )
{
this.outputEncoding = value;
}
/**
* Gets the encoding to use for reading templates.
*
* @return The encoding to use for reading templates or {@code null}.
*
* @see #setTemplateEncoding(java.lang.String)
*
* @deprecated As of JOMC 1.3, replaced by method {@link #getDefaultTemplateEncoding()}. This method will be removed
* in JOMC 2.0.
*/
@Deprecated
public final String getTemplateEncoding()
{
return this.templateEncoding;
}
/**
* Sets the encoding to use for reading templates.
*
* @param value The new encoding to use for reading templates or {@code null}.
*
* @see #getTemplateEncoding()
*
* @deprecated As of JOMC 1.3, replaced by method {@link #setDefaultTemplateEncoding(java.lang.String)}. This method
* will be removed in JOMC 2.0.
*/
@Deprecated
public final void setTemplateEncoding( final String value )
{
this.templateEncoding = value;
}
/**
* Gets the encoding to use for reading templates.
*
* @return The encoding to use for reading templates or {@code null}.
*
* @see #setDefaultTemplateEncoding(java.lang.String)
*
* @since 1.3
*/
public final String getDefaultTemplateEncoding()
{
return this.defaultTemplateEncoding;
}
/**
* Sets the encoding to use for reading templates.
*
* @param value The new encoding to use for reading templates or {@code null}.
*
* @see #getDefaultTemplateEncoding()
*
* @since 1.3
*/
public final void setDefaultTemplateEncoding( final String value )
{
this.defaultTemplateEncoding = value;
}
/**
* Gets the location to search for templates in addition to searching the class path of the task.
*
* @return The location to search for templates in addition to searching the class path of the task or {@code null}.
*
* @see #setTemplateLocation(java.lang.String)
*/
public final String getTemplateLocation()
{
return this.templateLocation;
}
/**
* Sets the location to search for templates in addition to searching the class path of the task.
*
* @param value The new location to search for templates in addition to searching the class path of the task or
* {@code null}.
*
* @see #getTemplateLocation()
*/
public final void setTemplateLocation( final String value )
{
this.templateLocation = value;
}
/**
* Gets the default template profile to use when accessing templates.
*
* @return The default template profile to use when accessing templates or {@code null}.
*
* @see #setDefaultTemplateProfile(java.lang.String)
*/
public final String getDefaultTemplateProfile()
{
return this.defaultTemplateProfile;
}
/**
* Sets the default template profile to use when accessing templates.
*
* @param value The new default template profile to use when accessing templates or {@code null}.
*
* @see #getDefaultTemplateProfile()
*/
public final void setDefaultTemplateProfile( final String value )
{
this.defaultTemplateProfile = value;
}
/**
* Gets the template profile to use when accessing templates.
*
* @return The template profile to use when accessing templates or {@code null}.
*
* @see #setTemplateProfile(java.lang.String)
*/
public final String getTemplateProfile()
{
return this.templateProfile;
}
/**
* Sets the template profile to use when accessing templates.
*
* @param value The new template profile to use when accessing templates or {@code null}.
*
* @see #getTemplateProfile()
*/
public final void setTemplateProfile( final String value )
{
this.templateProfile = value;
}
/**
* Gets the indentation string ('\t' for tab).
*
* @return The indentation string ('\t' for tab) or {@code null}.
*
* @see #setIndentation(java.lang.String)
*/
public final String getIndentation()
{
return this.indentation;
}
/**
* Sets the indentation string ('\t' for tab).
*
* @param value The new indentation string ('\t' for tab) or {@code null}.
*
* @see #getIndentation()
*/
public final void setIndentation( final String value )
{
this.indentation = value;
}
/**
* Gets the line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix).
*
* @return The line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix) or {@code null}.
*
* @see #setLineSeparator(java.lang.String)
*/
public final String getLineSeparator()
{
return this.lineSeparator;
}
/**
* Sets the line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix).
*
* @param value The new line separator ('\r\n' for DOS, '\r' for Mac, '\n' for Unix) or {@code null}.
*
* @see #getLineSeparator()
*/
public final void setLineSeparator( final String value )
{
this.lineSeparator = value;
}
/**
* Gets the locale.
*
* @return The locale or {@code null}.
*
* @see #createLocale()
*/
public final LocaleType getLocale()
{
return this.locale;
}
/**
* Creates a new {@code locale} element instance.
*
* @return A new {@code locale} element instance.
*
* @throws BuildException if a value already has been created.
*
* @see #getLocale()
*/
public LocaleType createLocale()
{
if ( this.locale != null )
{
throw new BuildException( Messages.getMessage( "multipleElements", "locale" ), this.getLocation() );
}
this.locale = new LocaleType();
return this.locale;
}
/**
* Gets the identifier of a specification to process.
*
* @return The identifier of a specification to process or {@code null}.
*
* @see #setSpecification(java.lang.String)
*/
public final String getSpecification()
{
return this.specification;
}
/**
* Sets the identifier of a specification to process.
*
* @param value The new identifier of a specification to process or {@code null}.
*
* @see #getSpecification()
*/
public final void setSpecification( final String value )
{
this.specification = value;
}
/**
* Gets the specification to process from a given model.
*
* @param model The model to get the specification to process from.
*
* @return The specification to process or {@code null}.
*
* @throws NullPointerException if {@code model} is {@code null}.
*
* @see #getSpecification()
*/
public final Specification getSpecification( final Model model )
{
if ( model == null )
{
throw new NullPointerException( "model" );
}
Specification s = null;
if ( this.getSpecification() != null )
{
final Modules modules = ModelHelper.getModules( model );
if ( modules != null )
{
s = modules.getSpecification( this.getSpecification() );
}
if ( s == null )
{
this.log( Messages.getMessage( "specificationNotFound", this.getSpecification() ), Project.MSG_WARN );
}
}
return s;
}
/**
* Gets the identifier of an implementation to process.
*
* @return The identifier of an implementation to process or {@code null}.
*
* @see #setImplementation(java.lang.String)
*/
public final String getImplementation()
{
return this.implementation;
}
/**
* Sets the identifier of an implementation to process.
*
* @param value The new identifier of an implementation to process or {@code null}.
*
* @see #getImplementation()
*/
public final void setImplementation( final String value )
{
this.implementation = value;
}
/**
* Gets the implementation to process from a given model.
*
* @param model The model to get the implementation to process from.
*
* @return The implementation to process or {@code null}.
*
* @throws NullPointerException if {@code model} is {@code null}.
*
* @see #getImplementation()
*/
public final Implementation getImplementation( final Model model )
{
if ( model == null )
{
throw new NullPointerException( "model" );
}
Implementation i = null;
if ( this.getImplementation() != null )
{
final Modules modules = ModelHelper.getModules( model );
if ( modules != null )
{
i = modules.getImplementation( this.getImplementation() );
}
if ( i == null )
{
this.log( Messages.getMessage( "implementationNotFound", this.getImplementation() ), Project.MSG_WARN );
}
}
return i;
}
/**
* Gets the identifier of a module to process.
*
* @return The identifier of a module to process or {@code null}.
*
* @see #setModule(java.lang.String)
*/
public final String getModule()
{
return this.module;
}
/**
* Sets the identifier of a module to process.
*
* @param value The new identifier of a module to process or {@code null}.
*
* @see #getModule()
*/
public final void setModule( final String value )
{
this.module = value;
}
/**
* Gets the module to process from a given model.
*
* @param model The model to get the module to process from.
*
* @return The module to process or {@code null}.
*
* @throws NullPointerException if {@code model} is {@code null}.
*
* @see #getModule()
*/
public final Module getModule( final Model model )
{
if ( model == null )
{
throw new NullPointerException( "model" );
}
Module m = null;
if ( this.getModule() != null )
{
final Modules modules = ModelHelper.getModules( model );
if ( modules != null )
{
m = modules.getModule( this.getModule() );
}
if ( m == null )
{
this.log( Messages.getMessage( "moduleNotFound", this.getModule() ), Project.MSG_WARN );
}
}
return m;
}
/**
* Gets a flag indicating all modules are requested to be processed.
*
* @return {@code true}, if processing of all modules is requested; {@code false}, else.
*
* @see #getSpecification()
* @see #getImplementation()
* @see #getModule()
*/
public boolean isModulesProcessingRequested()
{
return this.getSpecification() == null && this.getImplementation() == null && this.getModule() == null;
}
/**
* Gets the Velocity runtime properties to apply.
* <p>
* This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
* to the returned list will be present inside the object. This is why there is no {@code set} method for the
* velocity properties property.
* </p>
*
* @return The Velocity runtime properties to apply.
*
* @see #createVelocityProperty()
*/
public final List<KeyValueType> getVelocityProperties()
{
if ( this.velocityProperties == null )
{
this.velocityProperties = new LinkedList<KeyValueType>();
}
return this.velocityProperties;
}
/**
* Creates a new {@code velocityProperty} element instance.
*
* @return A new {@code velocityProperty} element instance.
*
* @see #getVelocityProperties()
*/
public KeyValueType createVelocityProperty()
{
final KeyValueType velocityProperty = new KeyValueType();
this.getVelocityProperties().add( velocityProperty );
return velocityProperty;
}
/**
* Gets the Velocity runtime property resources to apply.
* <p>
* This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
* to the returned list will be present inside the object. This is why there is no {@code set} method for the
* velocity property resources property.
* </p>
*
* @return The Velocity runtime property resources to apply.
*
* @see #createVelocityPropertyResource()
*/
public final List<PropertiesResourceType> getVelocityPropertyResources()
{
if ( this.velocityPropertyResources == null )
{
this.velocityPropertyResources = new LinkedList<PropertiesResourceType>();
}
return this.velocityPropertyResources;
}
/**
* Creates a new {@code velocityPropertyResource} element instance.
*
* @return A new {@code velocityPropertyResource} element instance.
*
* @see #getVelocityPropertyResources()
*/
public PropertiesResourceType createVelocityPropertyResource()
{
final PropertiesResourceType velocityPropertyResource = new PropertiesResourceType();
this.getVelocityPropertyResources().add( velocityPropertyResource );
return velocityPropertyResource;
}
/**
* Gets the template parameters to apply.
* <p>
* This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
* to the returned list will be present inside the object. This is why there is no {@code set} method for the
* template parameters property.
* </p>
*
* @return The template parameters to apply.
*
* @see #createTemplateParameter()
*/
public final List<KeyValueType> getTemplateParameters()
{
if ( this.templateParameters == null )
{
this.templateParameters = new LinkedList<KeyValueType>();
}
return this.templateParameters;
}
/**
* Creates a new {@code templateParameter} element instance.
*
* @return A new {@code templateParameter} element instance.
*
* @see #getTemplateParameters()
*/
public KeyValueType createTemplateParameter()
{
final KeyValueType templateParameter = new KeyValueType();
this.getTemplateParameters().add( templateParameter );
return templateParameter;
}
/**
* Gets the template parameter resources to apply.
* <p>
* This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make
* to the returned list will be present inside the object. This is why there is no {@code set} method for the
* template parameter resources property.
* </p>
*
* @return The template parameter resources to apply.
*
* @see #createTemplateParameterResource()
*/
public final List<PropertiesResourceType> getTemplateParameterResources()
{
if ( this.templateParameterResources == null )
{
this.templateParameterResources = new LinkedList<PropertiesResourceType>();
}
return this.templateParameterResources;
}
/**
* Creates a new {@code templateParameterResource} element instance.
*
* @return A new {@code templateParameterResource} element instance.
*
* @see #getTemplateParameterResources()
*/
public PropertiesResourceType createTemplateParameterResource()
{
final PropertiesResourceType templateParameterResource = new PropertiesResourceType();
this.getTemplateParameterResources().add( templateParameterResource );
return templateParameterResource;
}
/**
* {@inheritDoc}
*/
@Override
public void preExecuteTask() throws BuildException
{
super.preExecuteTask();
this.assertKeysNotNull( this.getVelocityProperties() );
this.assertKeysNotNull( this.getTemplateParameters() );
this.assertLocationsNotNull( this.getTemplateParameterResources() );
this.assertLocationsNotNull( this.getVelocityPropertyResources() );
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings( "deprecation" )
public void postExecuteTask() throws BuildException
{
JomcTool.setDefaultTemplateProfile( null );
super.postExecuteTask();
}
/**
* Configures a given {@code JomcTool} instance using the properties of the instance.
*
* @param tool The tool to configure.
*
* @throws NullPointerException if {@code tool} is {@code null}.
* @throws BuildException if configuring {@code tool} fails.
*/
@SuppressWarnings( "deprecation" )
public void configureJomcTool( final JomcTool tool ) throws BuildException
{
if ( tool == null )
{
throw new NullPointerException( "tool" );
}
try
{
tool.setLogLevel( Level.ALL );
tool.setIndentation( StringEscapeUtils.unescapeJava( this.getIndentation() ) );
tool.setInputEncoding( this.getInputEncoding() );
tool.setLineSeparator( StringEscapeUtils.unescapeJava( this.getLineSeparator() ) );
tool.setOutputEncoding( this.getOutputEncoding() );
tool.setDefaultTemplateProfile( this.getDefaultTemplateProfile() );
tool.setTemplateProfile( this.getTemplateProfile() );
tool.getListeners().add( new JomcTool.Listener()
{
@Override
public void onLog( final Level level, final String message, final Throwable throwable )
{
super.onLog( level, message, throwable );
if ( level.intValue() >= Level.SEVERE.intValue() )
{
log( message, throwable, Project.MSG_ERR );
}
else if ( level.intValue() >= Level.WARNING.intValue() )
{
log( message, throwable, Project.MSG_WARN );
}
else if ( level.intValue() >= Level.INFO.intValue() )
{
log( message, throwable, Project.MSG_INFO );
}
else
{
log( message, throwable, Project.MSG_DEBUG );
}
}
} );
if ( this.getTemplateEncoding() != null )
{
this.log( Messages.getMessage( "deprecationWarning", "templateEncoding", "defaultTemplateEncoding" ),
null, Project.MSG_WARN );
tool.setDefaultTemplateEncoding( this.getTemplateEncoding() );
}
else
{
tool.setDefaultTemplateEncoding( this.getDefaultTemplateEncoding() );
}
for ( int i = 0, s0 = this.getVelocityPropertyResources().size(); i < s0; i++ )
{
for ( final Map.Entry<Object, Object> e
: this.getProperties( this.getVelocityPropertyResources().get( i ) ).entrySet() )
{
if ( e.getValue() != null )
{
tool.getVelocityEngine().setProperty( e.getKey().toString(), e.getValue() );
}
else
{
tool.getVelocityEngine().clearProperty( e.getKey().toString() );
}
}
}
for ( int i = 0, s0 = this.getVelocityProperties().size(); i < s0; i++ )
{
final KeyValueType p = this.getVelocityProperties().get( i );
final Object object = p.getObject( this.getLocation() );
if ( object != null )
{
tool.getVelocityEngine().setProperty( p.getKey(), object );
}
else
{
tool.getVelocityEngine().clearProperty( p.getKey() );
}
}
for ( final Map.Entry<Object, Object> e : System.getProperties().entrySet() )
{
tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
}
for ( final Iterator<Map.Entry<?, ?>> it = this.getProject().getProperties().entrySet().iterator();
it.hasNext(); )
{
final Map.Entry<?, ?> e = it.next();
tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
}
for ( int i = 0, s0 = this.getTemplateParameterResources().size(); i < s0; i++ )
{
for ( final Map.Entry<Object, Object> e
: this.getProperties( this.getTemplateParameterResources().get( i ) ).entrySet() )
{
if ( e.getValue() != null )
{
tool.getTemplateParameters().put( e.getKey().toString(), e.getValue() );
}
else
{
tool.getTemplateParameters().remove( e.getKey().toString() );
}
}
}
for ( int i = 0, s0 = this.getTemplateParameters().size(); i < s0; i++ )
{
final KeyValueType p = this.getTemplateParameters().get( i );
final Object object = p.getObject( this.getLocation() );
if ( object != null )
{
tool.getTemplateParameters().put( p.getKey(), object );
}
else
{
tool.getTemplateParameters().remove( p.getKey() );
}
}
if ( this.getTemplateLocation() != null )
{
final URL url = this.getDirectory( this.getTemplateLocation() );
tool.setTemplateLocation( url );
if ( url == null )
{
this.log( Messages.getMessage( "templateLocationNotFound", this.getTemplateLocation() ),
Project.MSG_WARN );
}
}
if ( this.getLocale() != null )
{
tool.setLocale( new Locale( StringUtils.defaultString( this.getLocale().getLanguage() ),
StringUtils.defaultString( this.getLocale().getCountry() ),
StringUtils.defaultString( this.getLocale().getVariant() ) ) );
}
}
catch ( final IOException e )
{
throw new BuildException( Messages.getMessage( e ), e, this.getLocation() );
}
}
/**
* {@inheritDoc}
*/
@Override
public JomcToolTask clone()
{
final JomcToolTask clone = (JomcToolTask) super.clone();
if ( this.locale != null )
{
clone.locale = this.locale.clone();
}
if ( this.velocityPropertyResources != null )
{
clone.velocityPropertyResources =
new ArrayList<PropertiesResourceType>( this.velocityPropertyResources.size() );
for ( final PropertiesResourceType e : this.velocityPropertyResources )
{
clone.velocityPropertyResources.add( e.clone() );
}
}
if ( this.velocityProperties != null )
{
clone.velocityProperties = new ArrayList<KeyValueType>( this.velocityProperties.size() );
for ( final KeyValueType e : this.velocityProperties )
{
clone.velocityProperties.add( e.clone() );
}
}
if ( this.velocityPropertyResources != null )
{
clone.velocityPropertyResources =
new ArrayList<PropertiesResourceType>( this.velocityPropertyResources.size() );
for ( final PropertiesResourceType e : this.velocityPropertyResources )
{
clone.velocityPropertyResources.add( e.clone() );
}
}
if ( this.templateParameters != null )
{
clone.templateParameters = new ArrayList<KeyValueType>( this.templateParameters.size() );
for ( final KeyValueType e : this.templateParameters )
{
clone.templateParameters.add( e.clone() );
}
}
if ( this.templateParameterResources != null )
{
clone.templateParameterResources =
new ArrayList<PropertiesResourceType>( this.templateParameterResources.size() );
for ( final PropertiesResourceType e : this.templateParameterResources )
{
clone.templateParameterResources.add( e.clone() );
}
}
return clone;
}
}