Skip to content

Commit

Permalink
Use constructor taking a single String argument as fallback
Browse files Browse the repository at this point in the history
This closes #43
  • Loading branch information
kwin committed Jul 31, 2023
1 parent 8800f2d commit c63963b
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*******************************************************************************/
package org.codehaus.plexus.component.configurator.converters.composite;

import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Map;
Expand Down Expand Up @@ -51,14 +52,31 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
{
return null; // nothing to process
}
final Object bean = instantiateObject( implType );
if ( null == value )
Object bean = null;
// first try empty constructor with calling set/add methods or injecting fields
try
{
processConfiguration( lookup, bean, loader, configuration, evaluator, listener );
bean = instantiateObject( implType );
if ( null == value )
{
processConfiguration( lookup, bean, loader, configuration, evaluator, listener );
}
else
{
new CompositeBeanHelper( lookup, loader, evaluator, listener ).setDefault( bean, value, configuration );
}
}
else
catch( ComponentConfigurationException e )
{
new CompositeBeanHelper( lookup, loader, evaluator, listener ).setDefault( bean, value, configuration );
// fallback: try with constructor taking single string
if ( configuration.getChildCount() == 0 && value instanceof String )
{
bean = fromConstructorTakingString( type, (String) value, e );
}
else
{
throw e;
}
}
return bean;
}
Expand All @@ -72,6 +90,39 @@ public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfi
}
}

private Object fromConstructorTakingString( final Class<?> type, String value, ComponentConfigurationException precedingException ) throws ComponentConfigurationException
{
try
{
try
{
Constructor<?> constructor = type.getConstructor( String.class );
return constructor.newInstance( value );
}
catch ( NoSuchMethodException e )
{
// suppress emitting this exception if there is a preceding exception
if ( precedingException != null )
{
throw precedingException;
}
else
{
throw e;
}
}
}
catch ( ReflectiveOperationException e )
{
ComponentConfigurationException cce = new ComponentConfigurationException( "Cannot create instance of " + type + " with public constructor having a single String argument", e );
if ( precedingException != null )
{
cce.addSuppressed( precedingException );
}
throw cce;
}
}

public void processConfiguration( final ConverterLookup lookup, final Object bean, final ClassLoader loader,
final PlexusConfiguration configuration, final ExpressionEvaluator evaluator )
throws ComponentConfigurationException
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*******************************************************************************
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.sisu.plexus;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.codehaus.plexus.component.configurator.BasicComponentConfigurator;
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.ExpressionEvaluator;
import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import static org.junit.Assert.assertEquals;

public class BasicComponentConfiguratorTest
{
@Rule
public TemporaryFolder tmpDirectory = new TemporaryFolder();

private ComponentConfigurator configurator;

@Before
public void setUp()
{
configurator = new BasicComponentConfigurator();
}

@Test
public void testSimplePathOnDefaultFileSystem()
throws ComponentConfigurationException
{
PathTestComponent component = new PathTestComponent();
Path absolutePath = Paths.get( "" ).resolve( "absolute" ).toAbsolutePath();
configure( component, "path", "readme.txt", "absolutePath", absolutePath.toString(), "file", "readme.txt",
"absoluteFile", absolutePath.toString() );
// path must be converted to absolute one
assertEquals( tmpDirectory.getRoot().toPath().resolve( "readme.txt" ), component.path );
assertEquals( FileSystems.getDefault(), component.path.getFileSystem() );
assertEquals( absolutePath, component.absolutePath );
assertEquals( new File( tmpDirectory.getRoot(), "readme.txt" ), component.file );
assertEquals( absolutePath.toFile(), component.absoluteFile );
}

@Test
public void testTypeWithoutConverterButConstructorAcceptingString()
throws ComponentConfigurationException, IOException
{
CustomTypeComponent component = new CustomTypeComponent();
configure( component, "custom", "hello world" );
assertEquals( "hello world", component.custom.toString() );
}

private void configure( Object component, String... keysAndValues )
throws ComponentConfigurationException
{
final DefaultPlexusConfiguration config = new DefaultPlexusConfiguration( "testConfig" );
if ( keysAndValues.length % 2 != 0 )
{
throw new IllegalArgumentException( "Even number of keys and values expected" );
}
for ( int i = 0; i < keysAndValues.length; i += 2 )
{
config.addChild( keysAndValues[i], keysAndValues[i + 1] );
}
configure( component, config );
}

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

static final class PathTestComponent
{
Path path;

Path absolutePath;

File file;

File absoluteFile;
}

public static final class CustomType
{
private final String input;

public CustomType()
{
this.input = "invalid";
}

public CustomType( String input )
{
this.input = input;
}

@Override
public String toString()
{
return input;
}
}

static final class CustomTypeComponent
{
CustomType custom;
}
}

0 comments on commit c63963b

Please sign in to comment.