Skip to content

Commit

Permalink
Call TypeAwareExpressionEvaluator.evaluate(String,Class) if available
Browse files Browse the repository at this point in the history
Only enforce types in some places (where conversion afterwards never
happens)

This closes #160
  • Loading branch information
kwin committed Aug 29, 2024
1 parent b848262 commit 92a3066
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.eclipse.sisu.plexus.Roles;

Expand All @@ -37,45 +38,72 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
// Customizable methods
// ----------------------------------------------------------------------

/**
*
* @param configuration
* @param evaluator
* @return
* @throws ComponentConfigurationException
* @deprecated Use {@link #fromExpression(PlexusConfiguration, ExpressionEvaluator, Class)} instead
*/
@Deprecated
protected Object fromExpression( final PlexusConfiguration configuration, final ExpressionEvaluator evaluator )
throws ComponentConfigurationException
{
return fromExpression( configuration, evaluator, null );
}

protected Object fromExpression( final PlexusConfiguration configuration, final ExpressionEvaluator evaluator,
final Class<?> type )
throws ComponentConfigurationException
{
return fromExpression( configuration, evaluator, type, true );
}

protected Object fromExpression( final PlexusConfiguration configuration, final ExpressionEvaluator evaluator,
final Class<?> type, boolean enforceTypeCompatibility )
throws ComponentConfigurationException

{
String value = configuration.getValue();
try
{
Object result = null;
if ( null != value && value.length() > 0 )
{
result = evaluator.evaluate( value );
}
if ( null == result && configuration.getChildCount() == 0 )
if ( null != value && !value.isEmpty() )
{
value = configuration.getAttribute( "default-value" );
if ( null != value && value.length() > 0 )
if ( evaluator instanceof TypeAwareExpressionEvaluator && type != null )
{
result = ((TypeAwareExpressionEvaluator) evaluator).evaluate( value, type );
} else
{
result = evaluator.evaluate( value );
}
}
if ( null == result && configuration.getChildCount() == 0 ) {
value = configuration.getAttribute( "default-value" );
if ( null != value && !value.isEmpty() ) {
if ( evaluator instanceof TypeAwareExpressionEvaluator && type != null ) {
result = ((TypeAwareExpressionEvaluator) evaluator).evaluate( value, type );
} else {
result = evaluator.evaluate( value );
}
}
}
if ( enforceTypeCompatibility && type != null ) {
failIfNotTypeCompatible( result, type, configuration );
}
return result;
}
catch ( final ExpressionEvaluationException e )
{
final String reason = String.format( "Cannot evaluate expression '%s' for configuration entry '%s'", value,
configuration.getName() );
final String reason =
String.format( "Cannot evaluate expression '%s' for configuration entry '%s'",
value, configuration.getName() );

throw new ComponentConfigurationException( configuration, reason, e );
}
}

protected Object fromExpression( final PlexusConfiguration configuration, final ExpressionEvaluator evaluator,
final Class<?> type )
throws ComponentConfigurationException
{
final Object result = fromExpression( configuration, evaluator );
failIfNotTypeCompatible( result, type, configuration );
return result;
}

// ----------------------------------------------------------------------
// Shared methods
// ----------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
+ "' must not contain child elements" );
}

Object result = fromExpression( configuration, evaluator );
Object result = fromExpression( configuration, evaluator, type, false );
if ( result instanceof String )
{
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
final ConfigurationListener listener )
throws ComponentConfigurationException
{
final Object value = fromExpression( configuration, evaluator );
final Object value = fromExpression( configuration, evaluator, type, false );
if ( type.isInstance( value ) )
{
return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
final ConfigurationListener listener )
throws ComponentConfigurationException
{
final Object value = fromExpression( configuration, evaluator );
final Object value = fromExpression( configuration, evaluator, type, false );
if ( type.isInstance( value ) )
{
return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
try
{
final Map<Object, Object> map = instantiateMap( configuration, type, loader );
final Type elementType = findElementType( typeArguments );
final Type elementType = findElementClass( typeArguments );
if ( Object.class == elementType || String.class == elementType )
{
for ( int i = 0, size = configuration.getChildCount(); i < size; i++ )
{
final PlexusConfiguration element = configuration.getChild( i );
map.put( element.getName(), fromExpression( element, evaluator ) );
map.put( element.getName(), fromExpression( element, evaluator, (Class<?>)elementType ) );
}
return map;
}
Expand Down Expand Up @@ -96,7 +96,7 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
// TEMP: remove when http://jira.codehaus.org/browse/MSHADE-168 is fixed
catch ( final ComponentConfigurationException e )
{
elementValue = fromExpression( element, evaluator );
elementValue = fromExpression( element, evaluator, type );

Logs.warn( "Map in " + enclosingType + " declares value type as: {} but saw: {} at runtime",
elementType, null != elementValue ? elementValue.getClass() : null );
Expand Down Expand Up @@ -132,12 +132,13 @@ private Map<Object, Object> instantiateMap( final PlexusConfiguration configurat
return (Map<Object, Object>) impl;
}

private static Type findElementType( final Type[] typeArguments )
private static Type findElementClass( final Type[] typeArguments )
{
if ( null != typeArguments && typeArguments.length > 1 )
{
return typeArguments[1];
}
return Object.class;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
final ExpressionEvaluator evaluator, final ConfigurationListener listener )
throws ComponentConfigurationException
{
final Object value = fromExpression( configuration, evaluator );
// no type enforcement as also accepting string types used in the custom types constructor
final Object value = fromExpression( configuration, evaluator, type, false );
if ( type.isInstance( value ) )
{
return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
final PlexusConfiguration element = configuration.getChild( i );
if ( element.getChildCount() > 0 )
{
final Object name = fromExpression( element.getChild( "name" ), evaluator );
final Object name = fromExpression( element.getChild( "name" ), evaluator, String.class, false );
setProperty( properties, name, element.getChild( "value" ), evaluator );
}
else
Expand Down Expand Up @@ -91,7 +91,7 @@ private void setProperty( final Properties properties, final Object name,
final String key = null != name ? name.toString() : null;
if ( null != key )
{
final Object value = fromExpression( valueConfiguration, evaluator );
final Object value = fromExpression( valueConfiguration, evaluator, String.class, false );
properties.setProperty( key, null != value ? value.toString() : "" );
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.component.configurator.expression.DefaultExpressionEvaluator;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator;
import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.junit.Before;
Expand All @@ -40,6 +42,7 @@
import org.junit.rules.TemporaryFolder;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

Expand Down Expand Up @@ -81,6 +84,35 @@ public void testTypeWithoutConverterButConstructorAcceptingString()
assertEquals( "hello world", component.custom.toString() );
}

@Test
public void testTypePassedToExpressionEvaluator()
throws ComponentConfigurationException
{
CustomTypeComponent component = new CustomTypeComponent();
ExpressionEvaluator evaluator = new TypeAwareExpressionEvaluator() {

@Override
public Object evaluate(String expression, Class<?> type)
throws ExpressionEvaluationException {
assertEquals( CustomType.class, type );
return expression;
}

@Override
public Object evaluate(String expression) throws ExpressionEvaluationException {
fail( "Wrong evaluate method being called (without type)" );
return expression; // unreachable
}

@Override
public File alignToBaseDirectory(File path) {
return path;
}
};
configure( evaluator, component, "custom", "hello world" );
assertEquals( "hello world", component.custom.toString() );
}

@Test
public void testTemporalConvertersWithoutMillisecondsAndOffset()
throws ComponentConfigurationException
Expand Down Expand Up @@ -119,7 +151,6 @@ public void testTemporalConvertersWithISO8601StringWithOffset()

@Test
public void testTemporalConvertersWithInvalidString()
throws ComponentConfigurationException
{
TemporalComponent component = new TemporalComponent();
String dateString = "invalid";
Expand All @@ -143,7 +174,7 @@ public void testConfigureComplexBean()

config.addChild( child );

configure( complexBean, config,
configure( null, complexBean, config,
new ClassWorld( "foo", Thread.currentThread().getContextClassLoader() ).getClassRealm( "foo" ) );

assertEquals( complexBean.resources.size(), 2 );
Expand All @@ -153,6 +184,12 @@ public void testConfigureComplexBean()

private void configure( Object component, String... keysAndValues )
throws ComponentConfigurationException
{
configure( null, component, keysAndValues );
}

private void configure( ExpressionEvaluator evaluator, Object component, String... keysAndValues )
throws ComponentConfigurationException
{
final DefaultPlexusConfiguration config = new DefaultPlexusConfiguration( "testConfig" );
if ( keysAndValues.length % 2 != 0 )
Expand All @@ -163,33 +200,35 @@ private void configure( Object component, String... keysAndValues )
{
config.addChild( keysAndValues[i], keysAndValues[i + 1] );
}
configure( component, config );
configure( evaluator, component, config );
}

private void configure( Object component, PlexusConfiguration config )
private void configure( ExpressionEvaluator evaluator, Object component, PlexusConfiguration config )
throws ComponentConfigurationException
{
configure( component, config, null );
configure( evaluator, component, config, null );
}

private void configure( Object component, PlexusConfiguration config, ClassRealm loader )
private void configure( ExpressionEvaluator evaluator, Object component, PlexusConfiguration config, ClassRealm loader )
throws ComponentConfigurationException
{
final ExpressionEvaluator evaluator = new DefaultExpressionEvaluator()
{
@Override
public File alignToBaseDirectory( File path )
if (evaluator == null) {
evaluator = new DefaultExpressionEvaluator()
{
if ( !path.isAbsolute() )
{
return new File( tmpDirectory.getRoot(), path.getPath() );
}
else
@Override
public File alignToBaseDirectory( File path )
{
return path;
if ( !path.isAbsolute() )
{
return new File( tmpDirectory.getRoot(), path.getPath() );
}
else
{
return path;
}
}
}
};
};
}
configurator.configureComponent( component, config, evaluator, loader );
}

Expand Down

0 comments on commit 92a3066

Please sign in to comment.