com.simpligility.maven.plugins.android.config.ConfigHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of android-maven-plugin Show documentation
Show all versions of android-maven-plugin Show documentation
Maven Plugin for Android Development
The newest version!
package com.simpligility.maven.plugins.android.config;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
/**
* ConfigHandler is able to parse the configuration of a Mojo based on the Maven injected parameters as well as a config
* pojo and annontations for default values on properties named parsed*. See the ProguardMojo for a working
* implementation.
*
* @author Adrian Stabiszewski https://github.com/grundid/
* @author Manfred Moser - [email protected]
* @see ConfigPojo
* @see PullParameter
*/
public class ConfigHandler
{
private Object mojo;
private Object configPojoInstance;
private String configPojoName;
private String configPojoPrefix;
private PluginParameterExpressionEvaluator evaluator;
public ConfigHandler( Object mojo, MavenSession session, MojoExecution execution )
{
this.mojo = mojo;
if ( session == null )
{
throw new IllegalArgumentException( "The argument session is required" );
}
if ( execution == null )
{
throw new IllegalArgumentException( "The argument execution is required" );
}
this.evaluator = new PluginParameterExpressionEvaluator( session, execution );
initConfigPojo();
}
private Collection< Field > findPropertiesByAnnotation( Class< ? extends Annotation > annotation )
{
Collection< Field > result = new ArrayList< Field >();
for ( Class< ? extends Object > cls = mojo.getClass(); cls != Object.class; cls = cls.getSuperclass() )
{
for ( Field field : cls.getDeclaredFields() )
{
if ( field.isAnnotationPresent( annotation ) )
{
field.setAccessible( true );
result.add( field );
}
}
}
return result;
}
public void parseConfiguration()
{
Collection< Field > parsedFields = findPropertiesByAnnotation( PullParameter.class );
for ( Field field : parsedFields )
{
Object value = null;
String fieldBaseName = getFieldNameWithoutParsedPrefix( field );
// first take the setting from the config pojo (e.g. nested config in plugin configuration)
if ( configPojoInstance != null )
{
value = getValueFromPojo( fieldBaseName );
}
// then override with value from properties supplied in pom, settings or command line
// unless it is null or an empty array
Object propertyValue = getValueFromMojo( fieldBaseName );
if ( propertyValue == null || propertyValue instanceof Object[]//
&& ( (Object[]) propertyValue ).length == 0 )
{
// no useful value
}
else
{
value = propertyValue;
}
// and only if we still have no value, get the default as declared in the annotation
if ( value == null )
{
value = getValueFromAnnotation( field );
}
try
{
field.set( mojo, value );
}
catch ( Exception e )
{
e.printStackTrace();
}
}
}
private Object getValueFromAnnotation( Field field )
{
PullParameter annotation = field.getAnnotation( PullParameter.class );
String[] defaultValue = annotation.defaultValue();
boolean required = annotation.required();
String currentParameterName = "android." + configPojoName + "." + getFieldNameWithoutParsedPrefix( field );
if ( defaultValue.length > 0 )
{
if ( defaultValue.length > 1 )
{
throw new RuntimeException( String.format( "Too many default values for field %s", field.getName() ) );
}
final Class< ? > fieldType = field.getType();
try
{
final Object defValue = evaluator.evaluate( defaultValue[0], fieldType );
if ( defValue == null || fieldType.isInstance( defValue ) )
{
return defValue;
}
return convertTo( fieldType, defValue );
}
catch ( RuntimeException e )
{
throw e;
}
catch ( Exception e )
{
throw new RuntimeException( String.format(
"Problem encountered converting default value for %s parameter to %s",
currentParameterName, fieldType ), e );
}
}
else
{
if ( !required )
{
// if no default value method, simply return null
if ( annotation.defaultValueGetterMethod().isEmpty() )
{
return null;
}
try
{
Method method = mojo.getClass().getDeclaredMethod( annotation.defaultValueGetterMethod() );
// even access it if the method is private
method.setAccessible( true );
return method.invoke( mojo );
}
catch ( Exception e )
{
throw new RuntimeException( String.format(
"Problem encountered accessing default value for %s parameter",
currentParameterName ), e );
}
}
else
{
throw new RuntimeException( String.format(
"Required parameter %1$ has no value. Please "
+ "supply with -D%1$=value on the command line or as property or "
+ "plugin configuration in your pom or settings file.",
currentParameterName ) );
}
}
}
private Object convertTo( Class< ? > javaType, Object defValue )
throws Exception
{
// try valueOf
try
{
return javaType.getMethod( "valueOf", String.class ).invoke( null, defValue );
}
catch ( NoSuchMethodException e )
{
return javaType.getConstructor( String.class ).newInstance( defValue );
}
}
private Object getValueFromMojo( String fieldBaseName )
{
return getValueFromObject( mojo, configPojoName + toFirstLetterUppercase( fieldBaseName ) );
}
private Object getValueFromPojo( String fieldBaseName )
{
return getValueFromObject( configPojoInstance, fieldBaseName );
}
private Object getValueFromObject( Object object, String fieldBaseName )
{
Object value = null;
try
{
Field pojoField = findFieldByName( object, fieldBaseName );
if ( pojoField != null )
{
value = pojoField.get( object );
}
}
catch ( Exception e )
{
// swallow
}
return value;
}
private Field findFieldByName( Object object, String name )
{
for ( Field field : object.getClass().getDeclaredFields() )
{
if ( field.getName().equals( name ) )
{
field.setAccessible( true );
return field;
}
}
return null;
}
private String getFieldNameWithoutPrefix( Field field, String prefix )
{
if ( field.getName().startsWith( prefix ) )
{
String fieldName = field.getName().substring( prefix.length() );
return fieldName.substring( 0, 1 ).toLowerCase() + fieldName.substring( 1 );
}
else
{
return field.getName();
}
}
private String toFirstLetterUppercase( String s )
{
return s.substring( 0, 1 ).toUpperCase() + s.substring( 1 );
}
private String getFieldNameWithoutParsedPrefix( Field field )
{
return getFieldNameWithoutPrefix( field, configPojoPrefix );
}
private void initConfigPojo()
{
try
{
Field configPojo = findPropertiesByAnnotation( ConfigPojo.class ).iterator().next();
configPojoName = configPojo.getName();
configPojoInstance = configPojo.get( mojo );
configPojoPrefix = configPojo.getAnnotation( ConfigPojo.class ).prefix();
}
catch ( Exception e )
{
// ignore, we can live without a config pojo
}
}
}