diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java
new file mode 100644
index 0000000..9fbd874
--- /dev/null
+++ b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java
@@ -0,0 +1,419 @@
+package org.apache.maven.model.interpolation;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Organization;
+import org.apache.maven.model.Repository;
+import org.apache.maven.model.Resource;
+import org.apache.maven.model.Scm;
+import org.apache.maven.model.building.DefaultModelBuildingRequest;
+import org.apache.maven.model.building.ModelBuildingRequest;
+import org.apache.maven.model.building.SimpleProblemCollector;
+import org.apache.maven.model.path.DefaultPathTranslator;
+import org.apache.maven.model.path.PathTranslator;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+import org.codehaus.plexus.PlexusTestCase;
+
+/**
+ * @author jdcasey
+ * @version $Id: AbstractModelInterpolatorTest.java 813569 2009-09-10 20:04:14Z jdcasey $
+ */
+public abstract class AbstractModelInterpolatorTest
+    extends PlexusTestCase
+{
+    private Properties context;
+    
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        context = new Properties();
+        context.put( "basedir", "myBasedir" );
+        context.put( "project.baseUri", "myBaseUri" );
+    }
+
+
+    private ModelBuildingRequest createModelBuildingRequest(Properties p) {
+        ModelBuildingRequest config = new DefaultModelBuildingRequest();
+        if (p!= null) config.setSystemProperties( p);
+        return config;
+    }
+    
+/*    public void testDefaultBuildTimestampFormatShouldParseTimeIn24HourFormat()
+    {
+        Calendar cal = Calendar.getInstance();
+        cal.set( Calendar.HOUR, 12 );
+        cal.set( Calendar.AM_PM, Calendar.AM );
+        
+        // just to make sure all the bases are covered...
+        cal.set( Calendar.HOUR_OF_DAY, 0 );
+        cal.set( Calendar.MINUTE, 16 );
+        cal.set( Calendar.YEAR, 1976 );
+        cal.set( Calendar.MONTH, Calendar.NOVEMBER );
+        cal.set( Calendar.DATE, 11 );
+        
+        Date firstTestDate = cal.getTime();
+        
+        cal.set( Calendar.HOUR, 11 );
+        cal.set( Calendar.AM_PM, Calendar.PM );
+        
+        // just to make sure all the bases are covered...
+        cal.set( Calendar.HOUR_OF_DAY, 23 );
+        
+        Date secondTestDate = cal.getTime();
+        
+        SimpleDateFormat format = new SimpleDateFormat( ModelInterpolator.DEFAULT_BUILD_TIMESTAMP_FORMAT );
+      assertEquals( "19761111-0016", format.format( firstTestDate ) );
+      assertEquals( "19761111-2316", format.format( secondTestDate ) );
+    }
+  */
+    public void testShouldNotThrowExceptionOnReferenceToNonExistentValue()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Scm scm = new Scm();
+        scm.setConnection( "${test}/somepath" );
+
+        model.setScm( scm );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( "${test}/somepath", out.getScm().getConnection() );
+    }
+
+    /*
+
+    public void testShouldThrowExceptionOnRecursiveScmConnectionReference()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Scm scm = new Scm();
+        scm.setConnection( "${project.scm.connection}/somepath" );
+
+        model.setScm( scm );
+
+        try
+        {
+            ModelInterpolator interpolator = createInterpolator();
+            
+            Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+            fail( "The interpolator should not allow self-referencing expressions in POM." );
+        }
+        catch ( Exception e )
+        {
+
+        }
+    }
+    */
+
+    public void testShouldNotThrowExceptionOnReferenceToValueContainingNakedExpression()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Scm scm = new Scm();
+        scm.setConnection( "${test}/somepath" );
+
+        model.setScm( scm );
+
+        model.addProperty( "test", "test" );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( "test/somepath", out.getScm().getConnection() );
+    }
+
+    public void testShouldInterpolateOrganizationNameCorrectly()
+        throws Exception
+    {
+        String orgName = "MyCo";
+
+        Model model = new Model();
+        model.setName( "${pom.organization.name} Tools" );
+
+        Organization org = new Organization();
+        org.setName( orgName );
+
+        model.setOrganization( org );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( orgName + " Tools", out.getName() );
+    }
+
+    public void testShouldInterpolateDependencyVersionToSetSameAsProjectVersion()
+        throws Exception
+    {
+        Model model = new Model();
+        model.setVersion( "3.8.1" );
+
+        Dependency dep = new Dependency();
+        dep.setVersion( "${version}" );
+
+        model.addDependency( dep );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( "3.8.1", ( (Dependency) out.getDependencies().get( 0 ) ).getVersion() );
+    }
+
+    public void testShouldNotInterpolateDependencyVersionWithInvalidReference()
+        throws Exception
+    {
+        Model model = new Model();
+        model.setVersion( "3.8.1" );
+
+        Dependency dep = new Dependency();
+        dep.setVersion( "${something}" );
+
+        model.addDependency( dep );
+
+        /*
+         // This is the desired behaviour, however there are too many crappy poms in the repo and an issue with the
+         // timing of executing the interpolation
+
+         try
+         {
+         new RegexBasedModelInterpolator().interpolate( model, context );
+         fail( "Should have failed to interpolate with invalid reference" );
+         }
+         catch ( ModelInterpolationException expected )
+         {
+         assertTrue( true );
+         }
+         */
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+        
+        assertEquals( "${something}", ( (Dependency) out.getDependencies().get( 0 ) ).getVersion() );
+    }
+
+    public void testTwoReferences()
+        throws Exception
+    {
+        Model model = new Model();
+        model.setVersion( "3.8.1" );
+        model.setArtifactId( "foo" );
+
+        Dependency dep = new Dependency();
+        dep.setVersion( "${artifactId}-${version}" );
+
+        model.addDependency( dep );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( "foo-3.8.1", ( (Dependency) out.getDependencies().get( 0 ) ).getVersion() );
+    }
+
+/*public void testBasedir()
+        throws Exception
+    {
+        Model model = new Model();
+        model.setVersion( "3.8.1" );
+        model.setArtifactId( "foo" );
+
+        Repository repository = new Repository();
+
+        repository.setUrl( "file://localhost/${basedir}/temp-repo" );
+
+        model.addRepository( repository );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( "file://localhost/myBasedir/temp-repo", ( (Repository) out.getRepositories().get( 0 ) ).getUrl() );
+    }
+  */
+/*    public void testBaseUri()
+        throws Exception
+    {
+        Model model = new Model();
+        model.setVersion( "3.8.1" );
+        model.setArtifactId( "foo" );
+
+        Repository repository = new Repository();
+
+        repository.setUrl( "${project.baseUri}/temp-repo" );
+
+        model.addRepository( repository );
+
+        ModelInterpolator interpolator = createInterpolator();
+
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( "myBaseUri/temp-repo", ( (Repository) out.getRepositories().get( 0 ) ).getUrl() );
+    }
+  */
+    public void testEnvars()
+        throws Exception
+    {
+         Properties context = new Properties();
+
+        context.put( "env.HOME", "/path/to/home" );
+
+        Model model = new Model();
+
+        Properties modelProperties = new Properties();
+
+        modelProperties.setProperty( "outputDirectory", "${env.HOME}" );
+
+        model.setProperties( modelProperties );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( "/path/to/home", out.getProperties().getProperty( "outputDirectory" ) );
+    }
+
+    public void testEnvarExpressionThatEvaluatesToNullReturnsTheLiteralString()
+        throws Exception
+    {
+        Properties envars = new Properties();
+
+        Model model = new Model();
+
+        Properties modelProperties = new Properties();
+
+        modelProperties.setProperty( "outputDirectory", "${env.DOES_NOT_EXIST}" );
+
+        model.setProperties( modelProperties );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        assertEquals( out.getProperties().getProperty( "outputDirectory" ), "${env.DOES_NOT_EXIST}" );
+    }
+
+    public void testExpressionThatEvaluatesToNullReturnsTheLiteralString()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties modelProperties = new Properties();
+
+        modelProperties.setProperty( "outputDirectory", "${DOES_NOT_EXIST}" );
+
+        model.setProperties( modelProperties );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+        
+        assertEquals( out.getProperties().getProperty( "outputDirectory" ), "${DOES_NOT_EXIST}" );
+    }
+
+/*    public void testShouldInterpolateSourceDirectoryReferencedFromResourceDirectoryCorrectly()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Build build = new Build();
+        build.setSourceDirectory( "correct" );
+
+        Resource res = new Resource();
+        res.setDirectory( "${project.build.sourceDirectory}" );
+
+        build.addResource( res );
+
+        Resource res2 = new Resource();
+        res2.setDirectory( "${pom.build.sourceDirectory}" );
+
+        build.addResource( res2 );
+
+        Resource res3 = new Resource();
+        res3.setDirectory( "${build.sourceDirectory}" );
+
+        build.addResource( res3 );
+
+        model.setBuild( build );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model out = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+        
+        List outResources = out.getBuild().getResources();
+        Iterator resIt = outResources.iterator();
+
+        assertEquals( build.getSourceDirectory(), ( (Resource) resIt.next() ).getDirectory() );
+        assertEquals( build.getSourceDirectory(), ( (Resource) resIt.next() ).getDirectory() );
+        assertEquals( build.getSourceDirectory(), ( (Resource) resIt.next() ).getDirectory() );
+    }
+  */
+/*public void testShouldInterpolateUnprefixedBasedirExpression()
+        throws Exception
+    {
+        File basedir = new File( "/test/path" );
+        Model model = new Model();
+        Dependency dep = new Dependency();
+        dep.setSystemPath( "${basedir}/artifact.jar" );
+
+        model.addDependency( dep );
+
+        ModelInterpolator interpolator = createInterpolator();
+        
+        Model result = interpolator.interpolateModel( model, new File("."), createModelBuildingRequest(context), new SimpleProblemCollector() );
+
+        List rDeps = result.getDependencies();
+        assertNotNull( rDeps );
+        assertEquals( 1, rDeps.size() );
+        assertEquals( new File( basedir, "artifact.jar" ).getAbsolutePath(), new File( ( (Dependency) rDeps.get( 0 ) )
+            .getSystemPath() ).getAbsolutePath() );
+    }
+  */  
+
+    protected abstract ModelInterpolator createInterpolator( PathTranslator translator )
+        throws Exception;
+
+    protected abstract ModelInterpolator createInterpolator()
+        throws Exception;
+
+
+}
diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java
new file mode 100644
index 0000000..3f11333
--- /dev/null
+++ b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java
@@ -0,0 +1,424 @@
+package org.apache.maven.model.interpolation;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.building.DefaultModelBuildingRequest;
+import org.apache.maven.model.building.ModelBuildingRequest;
+import org.apache.maven.model.building.SimpleProblemCollector;
+import org.codehaus.plexus.PlexusTestCase;
+
+/**
+ * @author jdcasey
+ * @version $Id: StringSearchModelInterpolatorTest.java 708543 2008-10-28 11:54:17Z bentmann $
+ */
+public class StringSearchModelInterpolatorTest
+    extends AbstractModelInterpolatorTest 
+{
+
+
+    protected ModelInterpolator interpolator;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        super.setUp();
+        interpolator =  lookup(ModelInterpolator.class);
+    }
+
+
+    protected ModelInterpolator createInterpolator( org.apache.maven.model.path.PathTranslator translator )
+        throws Exception
+    {
+        return this.interpolator;
+    }
+
+    protected ModelInterpolator createInterpolator()
+        throws Exception
+    {
+        return this.interpolator;
+    }
+
+    public void testInterpolateStringArray()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+
+        String[] values = { "${key}", "${key2}" };
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( values, model, new File( "." ), config, new SimpleProblemCollector()  );
+
+        assertEquals( "value", values[0] );
+        assertEquals( "value2", values[1] );
+    }
+
+    private ModelBuildingRequest createModelBuildingRequest(Properties p) {
+        ModelBuildingRequest config = new DefaultModelBuildingRequest();
+        config.setSystemProperties( p);
+        return config;
+    }
+
+    public void testInterpolateObjectWithStringArrayField()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+
+        String[] values = { "${key}", "${key2}" };
+
+        ObjectWithStringArrayField obj = new ObjectWithStringArrayField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config, new SimpleProblemCollector()  );
+
+        assertEquals( "value", obj.values[0] );
+        assertEquals( "value2", obj.values[1] );
+    }
+
+    public void testInterpolateObjectWithStringListField()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+
+        List values = new ArrayList();
+        values.add( "${key}" );
+        values.add( "${key2}" );
+
+        ObjectWithListField obj = new ObjectWithListField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config, new SimpleProblemCollector() );
+
+        assertEquals( "value", obj.values.get( 0 ) );
+        assertEquals( "value2", obj.values.get( 1 ) );
+    }
+
+    public void testInterpolateObjectWithStringListFieldAndOneLiteralValue()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+
+        List values = new ArrayList();
+        values.add( "key" );
+        values.add( "${key2}" );
+
+        ObjectWithListField obj = new ObjectWithListField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config, new SimpleProblemCollector() );
+
+        assertEquals( "key", obj.values.get( 0 ) );
+        assertEquals( "value2", obj.values.get( 1 ) );
+    }
+
+    public void testInterpolateObjectWithUnmodifiableStringListField()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+
+        List values = Collections.unmodifiableList( Collections.singletonList( "${key}" ) );
+
+        ObjectWithListField obj = new ObjectWithListField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config,  new SimpleProblemCollector() );
+
+        assertEquals( "${key}", obj.values.get( 0 ) );
+    }
+
+    public void testInterpolateObjectWithStringArrayListField()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+        p.setProperty( "key3", "value3" );
+        p.setProperty( "key4", "value4" );
+
+        List values = new ArrayList();
+        values.add( new String[] { "${key}", "${key2}" } );
+        values.add( new String[] { "${key3}", "${key4}" } );
+
+        ObjectWithListField obj = new ObjectWithListField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config,  new SimpleProblemCollector() );
+
+        assertEquals( "value", ( (String[]) obj.values.get( 0 ) )[0] );
+        assertEquals( "value2", ( (String[]) obj.values.get( 0 ) )[1] );
+        assertEquals( "value3", ( (String[]) obj.values.get( 1 ) )[0] );
+        assertEquals( "value4", ( (String[]) obj.values.get( 1 ) )[1] );
+    }
+
+    public void testInterpolateObjectWithStringToStringMapField()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+
+        Map values = new HashMap();
+        values.put( "key", "${key}" );
+        values.put( "key2", "${key2}" );
+
+        ObjectWithMapField obj = new ObjectWithMapField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config, new SimpleProblemCollector() );
+
+        assertEquals( "value", obj.values.get( "key" ) );
+        assertEquals( "value2", obj.values.get( "key2" ) );
+    }
+
+    public void testInterpolateObjectWithStringToStringMapFieldAndOneLiteralValue()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+
+        Map values = new HashMap();
+        values.put( "key", "val" );
+        values.put( "key2", "${key2}" );
+
+        ObjectWithMapField obj = new ObjectWithMapField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config, new SimpleProblemCollector() );
+
+        assertEquals( "val", obj.values.get( "key" ) );
+        assertEquals( "value2", obj.values.get( "key2" ) );
+    }
+
+    public void testInterpolateObjectWithUnmodifiableStringToStringMapField()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+
+        Map values = Collections.unmodifiableMap( Collections.singletonMap( "key", "${key}" ) );
+
+        ObjectWithMapField obj = new ObjectWithMapField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config, new SimpleProblemCollector() );
+
+        assertEquals( "${key}", obj.values.get( "key" ) );
+    }
+
+    public void testInterpolateObjectWithStringToStringArrayMapField()
+        throws Exception
+    {
+        Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+        p.setProperty( "key3", "value3" );
+        p.setProperty( "key4", "value4" );
+
+        Map values = new HashMap();
+        values.put( "key", new String[] { "${key}", "${key2}" } );
+        values.put( "key2", new String[] { "${key3}", "${key4}" } );
+
+        ObjectWithMapField obj = new ObjectWithMapField( values );
+
+        StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+
+        ModelBuildingRequest config = createModelBuildingRequest(p);
+
+        interpolator.interpolateObject( obj, model, new File( "." ), config, new SimpleProblemCollector() );
+
+        assertEquals( "value", ( (String[]) obj.values.get( "key" ) )[0] );
+        assertEquals( "value2", ( (String[]) obj.values.get( "key" ) )[1] );
+        assertEquals( "value3", ( (String[]) obj.values.get( "key2" ) )[0] );
+        assertEquals( "value4", ( (String[]) obj.values.get( "key2" ) )[1] );
+    }
+
+
+    public void testConcurrentInterpolation() throws Exception {
+        final Model model = new Model();
+
+        Properties p = new Properties();
+        p.setProperty( "key", "value" );
+        p.setProperty( "key2", "value2" );
+        p.setProperty( "key3", "value3" );
+        p.setProperty( "key4", "value4" );
+
+        List values = new ArrayList();
+        values.add( new String[] { "${key}", "${key2}" } );
+        values.add( new String[] { "${key3}", "${key4}" } );
+        List values2 = new ArrayList();
+        values.add( new String[] { "${key}", "${key2}" } );
+        values.add( new String[] { "${key3}", "${key4}" } );
+        List values3 = new ArrayList();
+        values.add( new String[] { "${key}", "${key2}" } );
+        values.add( new String[] { "${key3}", "${key4}" } );
+
+        // There is an interesting issue here; if I send three identical collections into the three Lists in "obj", like this:
+        // final ObjectWithMixedProtection obj = new ObjectWithMixedProtection( values, values, values );
+        // I will have concurrency issues on the interpolation of the individual collections, since current
+        // synchronization is per-field and not per-underlying object.
+        // If this turns out to be a realistic use case, we will need to synchronize on the underlying collection
+        // in the interpolate method.
+
+        final ObjectWithMixedProtection obj = new ObjectWithMixedProtection( values, values2, values3 );
+        final StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator();
+        final ModelBuildingRequest config = createModelBuildingRequest(p);
+
+
+        int numItems = 250;
+        final CountDownLatch countDownLatch = new CountDownLatch(1);
+
+        List<Future<SimpleProblemCollector>>  futures = new ArrayList<Future<SimpleProblemCollector>>();
+        for (int i = 0; i < numItems; i++){
+            Callable<SimpleProblemCollector> future = new Callable<SimpleProblemCollector>() {
+                public SimpleProblemCollector call() throws Exception {
+                    countDownLatch.await();
+                    final SimpleProblemCollector collector = new SimpleProblemCollector();
+                    interpolator.interpolateObject( obj, model, new File( "." ), config, collector);
+                    return collector;
+                };
+            };
+            FutureTask<SimpleProblemCollector> task = new FutureTask<SimpleProblemCollector>(future);
+            futures.add ( task);
+            new Thread( task).start();
+        }
+        countDownLatch.countDown(); // Start all the threads
+        for(Future<SimpleProblemCollector> result : futures){
+            result.get(); // This should not fail. ArrayIndexOutOfBoundsException are typical indication of threading issues
+        }
+    }
+
+
+    private static final class ObjectWithStringArrayField
+    {
+        private final String[] values;
+
+        public ObjectWithStringArrayField( String[] values )
+        {
+            this.values = values;
+        }
+    }
+
+    private static final class ObjectWithListField
+    {
+        private final List values;
+
+        public ObjectWithListField( List values )
+        {
+            this.values = values;
+        }
+    }
+
+    private static final class ObjectWithMapField
+    {
+        private final Map values;
+
+        public ObjectWithMapField( Map values )
+        {
+            this.values = values;
+        }
+    }
+
+    private static final class ObjectWithMixedProtection
+    {
+        private List values1;
+        protected List values2;
+        List values3;
+
+        private ObjectWithMixedProtection(List values1, List values2, List values3) {
+            this.values1 = values1;
+            this.values2 = values2;
+            this.values3 = values3;
+        }
+    }
+
+}

