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