Coverage Report - org.apache.maven.project.interpolation.StringSearchModelInterpolator
 
Classes in this File Line Coverage Branch Coverage Complexity
StringSearchModelInterpolator
100 %
21/21
100 %
2/2
0
StringSearchModelInterpolator$InterpolateObjectAction
92 %
107/116
88 %
70/80
0
 
 1  
 package org.apache.maven.project.interpolation;
 2  
 
 3  
 import org.apache.maven.model.Model;
 4  
 import org.apache.maven.project.ProjectBuilderConfiguration;
 5  
 import org.apache.maven.project.path.PathTranslator;
 6  
 import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
 7  
 import org.codehaus.plexus.interpolation.Interpolator;
 8  
 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
 9  
 import org.codehaus.plexus.interpolation.ValueSource;
 10  
 import org.codehaus.plexus.logging.Logger;
 11  
 
 12  
 import java.io.File;
 13  
 import java.lang.reflect.Array;
 14  
 import java.lang.reflect.Field;
 15  
 import java.security.AccessController;
 16  
 import java.security.PrivilegedAction;
 17  
 import java.util.ArrayList;
 18  
 import java.util.Collection;
 19  
 import java.util.LinkedList;
 20  
 import java.util.List;
 21  
 import java.util.Map;
 22  
 import java.util.WeakHashMap;
 23  
 
 24  98510
 public class StringSearchModelInterpolator
 25  
     extends AbstractStringBasedModelInterpolator
 26  
 {
 27  
 
 28  1
     private static final Map<Class<?>, Field[]> fieldsByClass = new WeakHashMap<Class<?>, Field[]>();
 29  1
     private static final Map<Class<?>, Boolean> fieldIsPrimitiveByClass = new WeakHashMap<Class<?>, Boolean>();
 30  
 
 31  
     public StringSearchModelInterpolator()
 32  82
     {
 33  82
     }
 34  
 
 35  
     public StringSearchModelInterpolator( PathTranslator pathTranslator )
 36  
     {
 37  1
         super( pathTranslator );
 38  1
     }
 39  
 
 40  
     public Model interpolate( Model model, File projectDir, ProjectBuilderConfiguration config, boolean debugEnabled )
 41  
         throws ModelInterpolationException
 42  
     {
 43  138
         interpolateObject( model, model, projectDir, config, debugEnabled );
 44  
         
 45  137
         return model;
 46  
     }
 47  
     
 48  
     protected void interpolateObject( Object obj, Model model, File projectDir, ProjectBuilderConfiguration config,
 49  
                                       boolean debugEnabled )
 50  
         throws ModelInterpolationException
 51  
     {
 52  
         try
 53  
         {
 54  148
             List<ValueSource> valueSources = createValueSources( model, projectDir, config );
 55  148
             List<InterpolationPostProcessor> postProcessors = createPostProcessors( model, projectDir, config );
 56  
             
 57  148
             InterpolateObjectAction action =
 58  
                 new InterpolateObjectAction( obj, valueSources, postProcessors, debugEnabled,
 59  
                                              this, getLogger() );
 60  
             
 61  148
             ModelInterpolationException error =
 62  
                 (ModelInterpolationException) AccessController.doPrivileged( action );
 63  
             
 64  148
             if ( error != null )
 65  
             {
 66  1
                 throw error;
 67  
             }
 68  
         }
 69  
         finally
 70  
         {
 71  148
             getInterpolator().clearAnswers();
 72  147
         }
 73  147
     }
 74  
 
 75  
     protected Interpolator createInterpolator()
 76  
     {
 77  83
         StringSearchInterpolator interpolator = new StringSearchInterpolator();
 78  83
         interpolator.setCacheAnswers( true );
 79  
         
 80  83
         return interpolator;
 81  
     }
 82  
     
 83  148
     private static final class InterpolateObjectAction implements PrivilegedAction<ModelInterpolationException>
 84  
     {
 85  
 
 86  
         private final boolean debugEnabled;
 87  
         private final LinkedList<Object> interpolationTargets;
 88  
         private final StringSearchModelInterpolator modelInterpolator;
 89  
         private final Logger logger;
 90  
         private final List<ValueSource> valueSources;
 91  
         private final List<InterpolationPostProcessor> postProcessors;
 92  
         
 93  
         public InterpolateObjectAction( Object target, List<ValueSource> valueSources,
 94  
                                         List<InterpolationPostProcessor> postProcessors, boolean debugEnabled,
 95  
                                         StringSearchModelInterpolator modelInterpolator, Logger logger )
 96  148
         {
 97  148
             this.valueSources = valueSources;
 98  148
             this.postProcessors = postProcessors;
 99  148
             this.debugEnabled = debugEnabled;
 100  
             
 101  148
             this.interpolationTargets = new LinkedList<Object>();
 102  148
             interpolationTargets.add( target );
 103  
             
 104  148
             this.modelInterpolator = modelInterpolator;
 105  148
             this.logger = logger;
 106  148
         }
 107  
 
 108  
         public ModelInterpolationException run()
 109  
         {
 110  4479
             while( !interpolationTargets.isEmpty() )
 111  
             {
 112  4332
                 Object obj = interpolationTargets.removeFirst();
 113  
                 
 114  
                 try
 115  
                 {
 116  4332
                     traverseObjectWithParents( obj.getClass(), obj );
 117  
                 }
 118  1
                 catch ( ModelInterpolationException e )
 119  
                 {
 120  1
                     return e;
 121  4331
                 }
 122  4331
             }
 123  
             
 124  147
             return null;
 125  
         }
 126  
 
 127  
         @SuppressWarnings("unchecked")
 128  
         private void traverseObjectWithParents( Class<?> cls, Object target )
 129  
             throws ModelInterpolationException
 130  
         {
 131  12538
             if ( cls == null )
 132  
             {
 133  0
                 return;
 134  
             }
 135  
             
 136  
             
 137  12538
             if ( cls.isArray() )
 138  
             {
 139  1
                 evaluateArray( target );
 140  
             }
 141  12537
             else if ( isQualifiedForInterpolation( cls ) )
 142  
             {
 143  8207
                 Field[] fields = (Field[]) fieldsByClass.get( cls );
 144  8207
                 if ( fields == null )
 145  
                 {
 146  34
                     fields = cls.getDeclaredFields();
 147  34
                     fieldsByClass.put( cls, fields );
 148  
                 }
 149  
                 
 150  53325
                 for ( int i = 0; i < fields.length; i++ )
 151  
                 {
 152  45119
                     Class<?> type = fields[i].getType();
 153  45119
                     if ( isQualifiedForInterpolation( fields[i], type ) )
 154  
                     {
 155  38901
                         boolean isAccessible = fields[i].isAccessible();
 156  38901
                         fields[i].setAccessible( true );
 157  
                         try
 158  
                         {
 159  
                             try
 160  
                             {
 161  38901
                                 if ( String.class == type )
 162  
                                 {
 163  20331
                                     String value = (String) fields[i].get( target );
 164  20331
                                     if ( value != null )
 165  
                                     {
 166  13016
                                         String interpolated = modelInterpolator.interpolateInternal( value, valueSources, postProcessors, debugEnabled );
 167  
                                         
 168  13015
                                         if ( !interpolated.equals( value ) )
 169  
                                         {
 170  850
                                             fields[i].set( target, interpolated );
 171  
                                         }
 172  
                                     }
 173  20330
                                 }
 174  18570
                                 else if ( Collection.class.isAssignableFrom( type ) )
 175  
                                 {
 176  7955
                                     Collection<Object> c = (Collection<Object>) fields[i].get( target );
 177  7955
                                     if ( c != null && !c.isEmpty() )
 178  
                                     {
 179  914
                                         List<Object> originalValues = new ArrayList<Object>( c );
 180  
                                         try
 181  
                                         {
 182  914
                                             c.clear();
 183  
                                         }
 184  1
                                         catch( UnsupportedOperationException e )
 185  
                                         {
 186  1
                                             if ( debugEnabled && logger != null )
 187  
                                             {
 188  0
                                                 logger.debug( "Skipping interpolation of field: " + fields[i] + " in: " + cls.getName() + "; it is an unmodifiable collection." );
 189  
                                             }
 190  
                                             continue;
 191  913
                                         }
 192  
                                         
 193  913
                                         for ( Object value : originalValues )
 194  
                                         {
 195  3284
                                             if ( value != null )
 196  
                                             {
 197  3284
                                                 if( String.class == value.getClass() )
 198  
                                                 {
 199  78
                                                     String interpolated = modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors, debugEnabled );
 200  
                                                     
 201  78
                                                     if ( !interpolated.equals( value ) )
 202  
                                                     {
 203  18
                                                         c.add( interpolated );
 204  
                                                     }
 205  
                                                     else
 206  
                                                     {
 207  60
                                                         c.add( value );
 208  
                                                     }
 209  78
                                                 }
 210  
                                                 else
 211  
                                                 {
 212  3206
                                                     c.add( value );
 213  3206
                                                     if ( value.getClass().isArray() )
 214  
                                                     {
 215  2
                                                         evaluateArray( value );
 216  
                                                     }
 217  
                                                     else
 218  
                                                     {
 219  3204
                                                         interpolationTargets.add( value );
 220  
                                                     }
 221  
                                                 }
 222  
                                             }
 223  
                                             else
 224  
                                             {
 225  
                                                 // add the null back in...not sure what else to do...
 226  0
                                                 c.add( value );
 227  
                                             }
 228  
                                         }
 229  
                                     }
 230  7954
                                 }
 231  10615
                                 else if ( Map.class.isAssignableFrom( type ) )
 232  
                                 {
 233  3308
                                     Map<Object, Object> m = (Map<Object, Object>) fields[i].get( target );
 234  3308
                                     if ( m != null && !m.isEmpty() )
 235  
                                     {
 236  86
                                         for ( Map.Entry<Object, Object> entry : m.entrySet() )
 237  
                                         {
 238  100
                                             Object value = entry.getValue();
 239  
                                             
 240  100
                                             if ( value != null )
 241  
                                             {
 242  100
                                                 if( String.class == value.getClass() )
 243  
                                                 {
 244  29
                                                     String interpolated = modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors, debugEnabled );
 245  
                                                     
 246  29
                                                     if ( !interpolated.equals( value ) )
 247  
                                                     {
 248  
                                                         try
 249  
                                                         {
 250  12
                                                             entry.setValue( interpolated );
 251  
                                                         }
 252  1
                                                         catch( UnsupportedOperationException e )
 253  
                                                         {
 254  1
                                                             if ( debugEnabled && logger != null )
 255  
                                                             {
 256  0
                                                                 logger.debug( "Skipping interpolation of field: " + fields[i] + " (key: " + entry.getKey() + ") in: " + cls.getName() + "; it is an unmodifiable collection." );
 257  
                                                             }
 258  1
                                                             continue;
 259  11
                                                         }
 260  
                                                     }
 261  28
                                                 }
 262  
                                                 else
 263  
                                                 {
 264  71
                                                     if ( value.getClass().isArray() )
 265  
                                                     {
 266  2
                                                         evaluateArray( value );
 267  
                                                     }
 268  
                                                     else
 269  
                                                     {
 270  69
                                                         interpolationTargets.add( value );
 271  
                                                     }
 272  
                                                 }
 273  
                                             }
 274  99
                                         }
 275  
                                     }
 276  3308
                                 }
 277  
                                 else
 278  
                                 {
 279  7307
                                     Object value = fields[i].get( target );
 280  7307
                                     if ( value != null )
 281  
                                     {
 282  1083
                                         if ( fields[i].getType().isArray() )
 283  
                                         {
 284  172
                                             evaluateArray( value );
 285  
                                         }
 286  
                                         else
 287  
                                         {
 288  911
                                             interpolationTargets.add( value );
 289  
                                         }
 290  
                                     }
 291  
                                 }
 292  
                             }
 293  0
                             catch ( IllegalArgumentException e )
 294  
                             {
 295  0
                                 throw new ModelInterpolationException( "Failed to interpolate field: " + fields[i] + " on class: " + cls.getName(), e );
 296  
                             }
 297  0
                             catch ( IllegalAccessException e )
 298  
                             {
 299  0
                                 throw new ModelInterpolationException( "Failed to interpolate field: " + fields[i] + " on class: " + cls.getName(), e );
 300  38899
                             }
 301  
                         }
 302  
                         finally
 303  
                         {
 304  38901
                             fields[i].setAccessible( isAccessible );
 305  38899
                         }
 306  
                     }
 307  
                 }
 308  
                 
 309  8206
                 traverseObjectWithParents( cls.getSuperclass(), target );
 310  
             }
 311  12537
         }
 312  
 
 313  
         private boolean isQualifiedForInterpolation( Class<?> cls )
 314  
         {
 315  12537
             return !cls.getPackage().getName().startsWith( "java" );
 316  
         }
 317  
 
 318  
         private boolean isQualifiedForInterpolation( Field field, Class<?> fieldType )
 319  
         {
 320  45119
             if ( !fieldIsPrimitiveByClass.containsKey( fieldType ) )
 321  
             {
 322  31
                 fieldIsPrimitiveByClass.put( fieldType, Boolean.valueOf( fieldType.isPrimitive() ) );
 323  
             }
 324  
             
 325  45119
             if ( ((Boolean) fieldIsPrimitiveByClass.get( fieldType )).booleanValue() )
 326  
             {
 327  5909
                 return false;
 328  
             }
 329  
             
 330  
 //            if ( fieldType.isPrimitive() )
 331  
 //            {
 332  
 //                return false;
 333  
 //            }
 334  
             
 335  39210
             if ( "parent".equals( field.getName() ) )
 336  
             {
 337  309
                 return false;
 338  
             }
 339  
             
 340  38901
             return true;
 341  
         }
 342  
 
 343  
         private void evaluateArray( Object target )
 344  
             throws ModelInterpolationException
 345  
         {
 346  177
             int len = Array.getLength( target );
 347  189
             for( int i = 0; i < len; i++ )
 348  
             {
 349  12
                 Object value = Array.get( target, i );
 350  12
                 if ( value != null )
 351  
                 {
 352  12
                     if ( String.class == value.getClass() )
 353  
                     {
 354  12
                         String interpolated = modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors, debugEnabled );
 355  
                         
 356  12
                         if ( !interpolated.equals( value ) )
 357  
                         {
 358  12
                             Array.set( target, i, interpolated );
 359  
                         }
 360  12
                     }
 361  
                     else
 362  
                     {
 363  0
                         interpolationTargets.add( value );
 364  
                     }
 365  
                 }
 366  
             }
 367  177
         }
 368  
     }
 369  
 
 370  
 }