You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2012/08/22 16:55:33 UTC
svn commit: r1376085 -
/maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java
Author: krosenvold
Date: Wed Aug 22 14:55:33 2012
New Revision: 1376085
URL: http://svn.apache.org/viewvc?rev=1376085&view=rev
Log:
o Optimized the cache around the hotspot in interpolation somewhat
Modified:
maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java
Modified: maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java
URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java?rev=1376085&r1=1376084&r2=1376085&view=diff
==============================================================================
--- maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java (original)
+++ maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java Wed Aug 22 14:55:33 2012
@@ -22,7 +22,9 @@ package org.apache.maven.model.interpola
import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelProblem.Severity;
+import org.apache.maven.model.building.ModelProblem.Version;
import org.apache.maven.model.building.ModelProblemCollector;
+import org.apache.maven.model.building.ModelProblemCollectorRequest;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
import org.codehaus.plexus.interpolation.Interpolator;
@@ -41,19 +43,16 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import org.apache.maven.model.building.ModelProblem;
-import org.apache.maven.model.building.ModelProblem.Version;
-import org.apache.maven.model.building.ModelProblemCollectorRequest;
@Component( role = ModelInterpolator.class )
public class StringSearchModelInterpolator
extends AbstractStringBasedModelInterpolator
{
- private static final Map<Class<?>, Field[]> fieldsByClass =
- new ConcurrentHashMap<Class<?>, Field[]>( 80, 0.75f, 2 ); // Empirical data from 3.x, actual =40
- private static final Map<Class<?>, Boolean> fieldIsPrimitiveByClass =
- new ConcurrentHashMap<Class<?>, Boolean>( 62, 0.75f, 2 ); // Empirical data from 3.x, actual 31
+ private static final Map<Class<?>, InterpolateObjectAction.CacheItem> cachedEntries =
+ new ConcurrentHashMap<Class<?>, InterpolateObjectAction.CacheItem>( 80, 0.75f, 2 );
+ // Empirical data from 3.x, actual =40
+
public Model interpolateModel( Model model, File projectDir, ModelBuildingRequest config,
ModelProblemCollector problems )
@@ -69,8 +68,8 @@ public class StringSearchModelInterpolat
try
{
List<? extends ValueSource> valueSources = createValueSources( model, projectDir, config, problems );
- List<? extends InterpolationPostProcessor> postProcessors = createPostProcessors( model, projectDir,
- config );
+ List<? extends InterpolationPostProcessor> postProcessors =
+ createPostProcessors( model, projectDir, config );
InterpolateObjectAction action =
new InterpolateObjectAction( obj, valueSources, postProcessors, this, problems );
@@ -96,9 +95,13 @@ public class StringSearchModelInterpolat
{
private final LinkedList<Object> interpolationTargets;
+
private final StringSearchModelInterpolator modelInterpolator;
+
private final List<? extends ValueSource> valueSources;
+
private final List<? extends InterpolationPostProcessor> postProcessors;
+
private final ModelProblemCollector problems;
public InterpolateObjectAction( Object target, List<? extends ValueSource> valueSources,
@@ -129,6 +132,12 @@ public class StringSearchModelInterpolat
return null;
}
+
+ private String interpolate( String value )
+ {
+ return modelInterpolator.interpolateInternal( value, valueSources, postProcessors, problems );
+ }
+
private void traverseObjectWithParents( Class<?> cls, Object target )
{
if ( cls == null )
@@ -136,265 +145,379 @@ public class StringSearchModelInterpolat
return;
}
- if ( cls.isArray() )
+ CacheItem cacheEntry = getCacheEntry( cls );
+ if ( cacheEntry.isArray() )
+ {
+ evaluateArray( target, this );
+ }
+ else if ( cacheEntry.isQualifiedForInterpolation )
+ {
+ cacheEntry.interpolate( target, problems, this );
+
+ traverseObjectWithParents( cls.getSuperclass(), target );
+ }
+ }
+
+
+ private CacheItem getCacheEntry( Class<?> cls )
+ {
+ CacheItem cacheItem = cachedEntries.get( cls );
+ if ( cacheItem == null )
+ {
+ cacheItem = new CacheItem( cls );
+ cachedEntries.put( cls, cacheItem );
+ }
+ return cacheItem;
+ }
+
+ private boolean isQualifiedForInterpolation( Class<?> cls )
+ {
+ return !cls.getName().startsWith( "java" );
+ }
+
+ private boolean isQualifiedForInterpolation( Field field, Class<?> fieldType )
+ {
+ if ( Map.class.equals( fieldType ) && "locations".equals( field.getName() ) )
+ {
+ return false;
+ }
+
+ if ( fieldType.isPrimitive() )
{
- evaluateArray( target );
+ return false;
}
- else if ( isQualifiedForInterpolation( cls ) )
+
+ return !"parent".equals( field.getName() );
+ }
+
+ private static void evaluateArray( Object target, InterpolateObjectAction ctx )
+ {
+ int len = Array.getLength( target );
+ for ( int i = 0; i < len; i++ )
{
- for ( Field currentField : getFields( cls ) )
+ Object value = Array.get( target, i );
+ if ( value != null )
{
- Class<?> type = currentField.getType();
- if ( isQualifiedForInterpolation( currentField, type ) )
+ if ( String.class == value.getClass() )
{
- synchronized ( currentField )
+ String interpolated = ctx.interpolate( (String) value );
+
+ if ( !interpolated.equals( value ) )
{
- interpolateField( cls, target, currentField, type );
+ Array.set( target, i, interpolated );
}
}
+ else
+ {
+ ctx.interpolationTargets.add( value );
+ }
}
-
- traverseObjectWithParents( cls.getSuperclass(), target );
}
}
- private void interpolateField( Class<?> cls, Object target, Field field, Class<?> type )
+ private static class CacheItem
{
- boolean isAccessible = field.isAccessible();
- field.setAccessible( true );
- try
+ private final boolean isArray;
+
+ private final boolean isQualifiedForInterpolation;
+
+ private final CacheField[] fields;
+
+ private boolean isQualifiedForInterpolation( Class<?> cls )
{
- if ( String.class == type )
- {
- interpolateStringField( target, field );
- }
- else if ( Collection.class.isAssignableFrom( type ) )
+ return !cls.getName().startsWith( "java" );
+ }
+
+ private boolean isQualifiedForInterpolation( Field field, Class<?> fieldType )
+ {
+ if ( Map.class.equals( fieldType ) && "locations".equals( field.getName() ) )
{
- interpolateCollectionField( target, field );
+ return false;
}
- else if ( Map.class.isAssignableFrom( type ) )
+
+ if ( fieldType.isPrimitive() )
{
- interpolateMapField( target, field );
+ return false;
}
- else
+
+ return !"parent".equals( field.getName() );
+ }
+
+ CacheItem( Class clazz )
+ {
+ this.isQualifiedForInterpolation = isQualifiedForInterpolation( clazz );
+ this.isArray = clazz.isArray();
+ List<CacheField> fields = new ArrayList<CacheField>();
+ for ( Field currentField : clazz.getDeclaredFields() )
{
- Object value = field.get( target );
- if ( value != null )
+ Class<?> type = currentField.getType();
+ if ( isQualifiedForInterpolation( currentField, type ) )
{
- if ( field.getType().isArray() )
+ if ( String.class == type )
+ {
+ if ( !Modifier.isFinal( currentField.getModifiers() ) )
+ {
+ fields.add( new StringField( currentField ) );
+ }
+ }
+ else if ( Collection.class.isAssignableFrom( type ) )
+ {
+ fields.add( new CollectionField( currentField ) );
+ }
+ else if ( Map.class.isAssignableFrom( type ) )
{
- evaluateArray( value );
+ fields.add( new MapField( currentField ) );
}
else
{
- interpolationTargets.add( value );
+ fields.add( new ObjectField( currentField ) );
}
}
+
}
+ this.fields = fields.toArray( new CacheField[fields.size()] );
+
}
- catch ( IllegalArgumentException e )
- {
- problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE)
- .setMessage( "Failed to interpolate field3: " + field + " on class: " + cls.getName())
- .setException(e));
- }
- catch ( IllegalAccessException e )
+
+ public void interpolate( Object target, ModelProblemCollector problems,
+ InterpolateObjectAction interpolateObjectAction )
{
- problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE)
- .setMessage( "Failed to interpolate field4: " + field + " on class: " + cls.getName())
- .setException(e));
+ for ( CacheField field : fields )
+ {
+ field.interpolate( target, problems, interpolateObjectAction );
+ }
}
- finally
+
+ public boolean isArray()
{
- field.setAccessible( isAccessible );
+ return isArray;
}
}
- private void interpolateStringField( Object target, Field field )
- throws IllegalAccessException
+ static abstract class CacheField
{
- String value = (String) field.get( target );
- if ( value == null || Modifier.isFinal( field.getModifiers() ) )
+ protected final Field field;
+
+ CacheField( Field field )
{
- return;
+ this.field = field;
}
- String interpolated =
- modelInterpolator.interpolateInternal( value, valueSources, postProcessors, problems );
-
- if ( !interpolated.equals( value ) )
+ void interpolate( Object target, ModelProblemCollector problems,
+ InterpolateObjectAction interpolateObjectAction )
{
- field.set( target, interpolated );
+ synchronized ( field )
+ {
+ boolean isAccessible = field.isAccessible();
+ field.setAccessible( true );
+ try
+ {
+ doInterpolate( target, interpolateObjectAction );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ interpolateObjectAction.problems.add(
+ new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
+ "Failed to interpolate field3: " + field + " on class: "
+ + field.getType().getName() ).setException(
+ e ) ); // todo: Not entirely the same message
+ }
+ catch ( IllegalAccessException e )
+ {
+ interpolateObjectAction.problems.add(
+ new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
+ "Failed to interpolate field4: " + field + " on class: "
+ + field.getType().getName() ).setException( e ) );
+ }
+ finally
+ {
+ field.setAccessible( isAccessible );
+ }
+ }
+
+
}
+
+ abstract void doInterpolate( Object target, InterpolateObjectAction ctx )
+ throws IllegalAccessException;
}
- private void interpolateCollectionField( Object target, Field field )
- throws IllegalAccessException
+ static final class StringField
+ extends CacheField
{
- @SuppressWarnings( "unchecked" )
- Collection<Object> c = (Collection<Object>) field.get( target );
- if ( c == null || c.isEmpty() )
+ StringField( Field field )
{
- return;
+ super( field );
}
- List<Object> originalValues = new ArrayList<Object>( c );
- try
+ @Override
+ void doInterpolate( Object target, InterpolateObjectAction ctx )
+ throws IllegalAccessException
{
- c.clear();
+ String value = (String) field.get( target );
+ if ( value == null )
+ {
+ return;
+ }
+
+ String interpolated = ctx.interpolate( value );
+
+ if ( !interpolated.equals( value ) )
+ {
+ field.set( target, interpolated );
+ }
}
- catch ( UnsupportedOperationException e )
+ }
+
+ static final class CollectionField
+ extends CacheField
+ {
+ CollectionField( Field field )
{
- return;
+ super( field );
}
- for ( Object value : originalValues )
+ @Override
+ void doInterpolate( Object target, InterpolateObjectAction ctx )
+ throws IllegalAccessException
{
- if ( value == null )
+ @SuppressWarnings( "unchecked" ) Collection<Object> c = (Collection<Object>) field.get( target );
+ if ( c == null || c.isEmpty() )
+ {
+ return;
+ }
+
+ List<Object> originalValues = new ArrayList<Object>( c );
+ try
{
- // add the null back in...not sure what else to do...
- c.add( value );
+ c.clear();
}
- else if ( String.class == value.getClass() )
+ catch ( UnsupportedOperationException e )
{
- String interpolated =
- modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors, problems );
+ return;
+ }
- if ( !interpolated.equals( value ) )
- {
- c.add( interpolated );
- }
- else
+ for ( Object value : originalValues )
+ {
+ if ( value == null )
{
+ // add the null back in...not sure what else to do...
c.add( value );
}
- }
- else
- {
- c.add( value );
- if ( value.getClass().isArray() )
+ else if ( String.class == value.getClass() )
{
- evaluateArray( value );
+ String interpolated = ctx.interpolate( (String) value );
+
+ if ( !interpolated.equals( value ) )
+ {
+ c.add( interpolated );
+ }
+ else
+ {
+ c.add( value );
+ }
}
else
{
- interpolationTargets.add( value );
+ c.add( value );
+ if ( value.getClass().isArray() )
+ {
+ evaluateArray( value, ctx );
+ }
+ else
+ {
+ ctx.interpolationTargets.add( value );
+ }
}
}
}
}
- private void interpolateMapField( Object target, Field field )
- throws IllegalAccessException
+ static final class MapField
+ extends CacheField
{
- @SuppressWarnings( "unchecked" )
- Map<Object, Object> m = (Map<Object, Object>) field.get( target );
- if ( m == null || m.isEmpty() )
+ MapField( Field field )
{
- return;
+ super( field );
}
- for ( Map.Entry<Object, Object> entry : m.entrySet() )
+ @Override
+ void doInterpolate( Object target, InterpolateObjectAction ctx )
+ throws IllegalAccessException
{
- Object value = entry.getValue();
-
- if ( value == null )
+ @SuppressWarnings( "unchecked" ) Map<Object, Object> m = (Map<Object, Object>) field.get( target );
+ if ( m == null || m.isEmpty() )
{
- continue;
+ return;
}
- if ( String.class == value.getClass() )
+ for ( Map.Entry<Object, Object> entry : m.entrySet() )
{
- String interpolated =
- modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors, problems );
+ Object value = entry.getValue();
- if ( !interpolated.equals( value ) )
+ if ( value == null )
{
- try
- {
- entry.setValue( interpolated );
- }
- catch ( UnsupportedOperationException e )
+ continue;
+ }
+
+ if ( String.class == value.getClass() )
+ {
+ String interpolated = ctx.interpolate( (String) value );
+
+ if ( !interpolated.equals( value ) )
{
- continue;
+ try
+ {
+ entry.setValue( interpolated );
+ }
+ catch ( UnsupportedOperationException e )
+ {
+ continue;
+ }
}
}
+ else if ( value.getClass().isArray() )
+ {
+ evaluateArray( value, ctx );
+ }
+ else
+ {
+ ctx.interpolationTargets.add( value );
+ }
}
- else if ( value.getClass().isArray() )
- {
- evaluateArray( value );
- }
- else
- {
- interpolationTargets.add( value );
- }
- }
- }
-
- private Field[] getFields( Class<?> cls )
- {
- Field[] fields = fieldsByClass.get( cls );
- if ( fields == null )
- {
- fields = cls.getDeclaredFields();
- fieldsByClass.put( cls, fields );
}
- return fields;
- }
-
- private boolean isQualifiedForInterpolation( Class<?> cls )
- {
- return !cls.getName().startsWith( "java" );
}
- private boolean isQualifiedForInterpolation( Field field, Class<?> fieldType )
+ static final class ObjectField
+ extends CacheField
{
- if ( Map.class.equals( fieldType ) && "locations".equals( field.getName() ) )
- {
- return false;
- }
+ private final boolean isArray;
- Boolean primitive = fieldIsPrimitiveByClass.get( fieldType );
- if ( primitive == null )
+ ObjectField( Field field )
{
- primitive = fieldType.isPrimitive();
- fieldIsPrimitiveByClass.put( fieldType, primitive );
+ super( field );
+ this.isArray = field.getType().isArray();
}
- if ( primitive )
- {
- return false;
- }
-
- return !"parent".equals( field.getName() );
- }
-
- private void evaluateArray( Object target )
- {
- int len = Array.getLength( target );
- for ( int i = 0; i < len; i++ )
+ @Override
+ void doInterpolate( Object target, InterpolateObjectAction ctx )
+ throws IllegalAccessException
{
- Object value = Array.get( target, i );
+ Object value = field.get( target );
if ( value != null )
{
- if ( String.class == value.getClass() )
+ if ( isArray )
{
- String interpolated =
- modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors,
- problems );
-
- if ( !interpolated.equals( value ) )
- {
- Array.set( target, i, interpolated );
- }
+ evaluateArray( value, ctx );
}
else
{
- interpolationTargets.add( value );
+ ctx.interpolationTargets.add( value );
}
}
}
}
+
}
}