1 package org.apache.maven.project.interpolation;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.model.Model;
23 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
24 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
25 import org.apache.maven.project.DefaultProjectBuilderConfiguration;
26 import org.apache.maven.project.ProjectBuilderConfiguration;
27 import org.apache.maven.project.path.PathTranslator;
28 import org.codehaus.plexus.interpolation.AbstractValueSource;
29 import org.codehaus.plexus.interpolation.InterpolationException;
30 import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
31 import org.codehaus.plexus.interpolation.Interpolator;
32 import org.codehaus.plexus.interpolation.MapBasedValueSource;
33 import org.codehaus.plexus.interpolation.ObjectBasedValueSource;
34 import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
35 import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
36 import org.codehaus.plexus.interpolation.PrefixedValueSourceWrapper;
37 import org.codehaus.plexus.interpolation.RecursionInterceptor;
38 import org.codehaus.plexus.interpolation.ValueSource;
39 import org.codehaus.plexus.logging.AbstractLogEnabled;
40 import org.codehaus.plexus.logging.Logger;
41 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
42 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
43 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
44
45 import java.io.File;
46 import java.io.IOException;
47 import java.io.StringReader;
48 import java.io.StringWriter;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.Collections;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Properties;
55
56
57
58
59
60
61
62
63 @Deprecated
64 public abstract class AbstractStringBasedModelInterpolator
65 extends AbstractLogEnabled
66 implements ModelInterpolator, Initializable
67 {
68 private static final List<String> PROJECT_PREFIXES = Arrays.asList( new String[]{ "pom.", "project." } );
69
70 private static final List<String> TRANSLATED_PATH_EXPRESSIONS;
71
72 static
73 {
74 List<String> translatedPrefixes = new ArrayList<String>();
75
76
77
78
79
80
81 translatedPrefixes.add( "build.directory" );
82 translatedPrefixes.add( "build.outputDirectory" );
83 translatedPrefixes.add( "build.testOutputDirectory" );
84 translatedPrefixes.add( "build.sourceDirectory" );
85 translatedPrefixes.add( "build.testSourceDirectory" );
86 translatedPrefixes.add( "build.scriptSourceDirectory" );
87 translatedPrefixes.add( "reporting.outputDirectory" );
88
89 TRANSLATED_PATH_EXPRESSIONS = translatedPrefixes;
90 }
91
92 private PathTranslator pathTranslator;
93
94 private Interpolator interpolator;
95
96 private RecursionInterceptor recursionInterceptor;
97
98
99 protected AbstractStringBasedModelInterpolator( PathTranslator pathTranslator )
100 {
101 this.pathTranslator = pathTranslator;
102 }
103
104
105
106
107
108 protected AbstractStringBasedModelInterpolator()
109 {
110 }
111
112 public Model interpolate( Model model, Map<String, ?> context )
113 throws ModelInterpolationException
114 {
115 return interpolate( model, context, true );
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130 public Model interpolate( Model model, Map<String, ?> context, boolean strict )
131 throws ModelInterpolationException
132 {
133 Properties props = new Properties();
134 props.putAll( context );
135
136 return interpolate( model,
137 null,
138 new DefaultProjectBuilderConfiguration().setExecutionProperties( props ),
139 true );
140 }
141
142 public Model interpolate( Model model,
143 File projectDir,
144 ProjectBuilderConfiguration config,
145 boolean debugEnabled )
146 throws ModelInterpolationException
147 {
148 StringWriter sWriter = new StringWriter( 1024 );
149
150 MavenXpp3Writer writer = new MavenXpp3Writer();
151 try
152 {
153 writer.write( sWriter, model );
154 }
155 catch ( IOException e )
156 {
157 throw new ModelInterpolationException( "Cannot serialize project model for interpolation.", e );
158 }
159
160 String serializedModel = sWriter.toString();
161 serializedModel = interpolate( serializedModel, model, projectDir, config, debugEnabled );
162
163 StringReader sReader = new StringReader( serializedModel );
164
165 MavenXpp3Reader modelReader = new MavenXpp3Reader();
166 try
167 {
168 model = modelReader.read( sReader );
169 }
170 catch ( IOException e )
171 {
172 throw new ModelInterpolationException(
173 "Cannot read project model from interpolating filter of serialized version.", e );
174 }
175 catch ( XmlPullParserException e )
176 {
177 throw new ModelInterpolationException(
178 "Cannot read project model from interpolating filter of serialized version.", e );
179 }
180
181 return model;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 public String interpolate( String src,
199 Model model,
200 final File projectDir,
201 ProjectBuilderConfiguration config,
202 boolean debug )
203 throws ModelInterpolationException
204 {
205 try
206 {
207 List<ValueSource> valueSources = createValueSources( model, projectDir, config );
208 List<InterpolationPostProcessor> postProcessors = createPostProcessors( model, projectDir, config );
209
210 return interpolateInternal( src, valueSources, postProcessors, debug );
211 }
212 finally
213 {
214 interpolator.clearAnswers();
215 }
216 }
217
218 protected List<ValueSource> createValueSources( final Model model, final File projectDir,
219 final ProjectBuilderConfiguration config )
220 {
221 String timestampFormat = DEFAULT_BUILD_TIMESTAMP_FORMAT;
222
223 Properties modelProperties = model.getProperties();
224 if ( modelProperties != null )
225 {
226 timestampFormat = modelProperties.getProperty( BUILD_TIMESTAMP_FORMAT_PROPERTY, timestampFormat );
227 }
228
229 ValueSource modelValueSource1 = new PrefixedObjectValueSource( PROJECT_PREFIXES, model, false );
230 ValueSource modelValueSource2 = new ObjectBasedValueSource( model );
231
232 ValueSource basedirValueSource = new PrefixedValueSourceWrapper( new AbstractValueSource( false )
233 {
234 public Object getValue( String expression )
235 {
236 if ( projectDir != null && "basedir".equals( expression ) )
237 {
238 return projectDir.getAbsolutePath();
239 }
240 return null;
241 }
242 }, PROJECT_PREFIXES, true );
243 ValueSource baseUriValueSource = new PrefixedValueSourceWrapper( new AbstractValueSource( false )
244 {
245 public Object getValue( String expression )
246 {
247 if ( projectDir != null && "baseUri".equals( expression ) )
248 {
249 return projectDir.getAbsoluteFile().toURI().toString();
250 }
251 return null;
252 }
253 }, PROJECT_PREFIXES, false );
254
255 List<ValueSource> valueSources = new ArrayList<ValueSource>( 9 );
256
257
258 valueSources.add( basedirValueSource );
259 valueSources.add( baseUriValueSource );
260 valueSources.add( new BuildTimestampValueSource( config.getBuildStartTime(), timestampFormat ) );
261 valueSources.add( modelValueSource1 );
262 valueSources.add( new MapBasedValueSource( config.getUserProperties() ) );
263 valueSources.add( new MapBasedValueSource( modelProperties ) );
264 valueSources.add( new MapBasedValueSource( config.getExecutionProperties() ) );
265 valueSources.add( new AbstractValueSource( false )
266 {
267 public Object getValue( String expression )
268 {
269 return config.getExecutionProperties().getProperty( "env." + expression );
270 }
271 } );
272 valueSources.add( modelValueSource2 );
273
274 return valueSources;
275 }
276
277 protected List<InterpolationPostProcessor> createPostProcessors( final Model model, final File projectDir,
278 final ProjectBuilderConfiguration config )
279 {
280 return Collections.singletonList( (InterpolationPostProcessor) new PathTranslatingPostProcessor(
281 PROJECT_PREFIXES,
282 TRANSLATED_PATH_EXPRESSIONS,
283 projectDir,
284 pathTranslator ) );
285 }
286
287 @SuppressWarnings("unchecked")
288 protected String interpolateInternal( String src, List<ValueSource> valueSources,
289 List<InterpolationPostProcessor> postProcessors, boolean debug )
290 throws ModelInterpolationException
291 {
292 if ( src.indexOf( "${" ) < 0 )
293 {
294 return src;
295 }
296
297 Logger logger = getLogger();
298
299 String result = src;
300 synchronized( this )
301 {
302
303 for ( ValueSource vs : valueSources )
304 {
305 interpolator.addValueSource( vs );
306 }
307
308 for ( InterpolationPostProcessor postProcessor : postProcessors )
309 {
310 interpolator.addPostProcessor( postProcessor );
311 }
312
313 try
314 {
315 try
316 {
317 result = interpolator.interpolate( result, recursionInterceptor );
318 }
319 catch( InterpolationException e )
320 {
321 throw new ModelInterpolationException( e.getMessage(), e );
322 }
323
324 if ( debug )
325 {
326 List<Object> feedback = interpolator.getFeedback();
327 if ( feedback != null && !feedback.isEmpty() )
328 {
329 logger.debug( "Maven encountered the following problems during initial POM interpolation:" );
330
331 Object last = null;
332 for ( Object next : feedback )
333 {
334 if ( next instanceof Throwable )
335 {
336 if ( last == null )
337 {
338 logger.debug( "", ( (Throwable) next ) );
339 }
340 else
341 {
342 logger.debug( String.valueOf( last ), ( (Throwable) next ) );
343 }
344 }
345 else
346 {
347 if ( last != null )
348 {
349 logger.debug( String.valueOf( last ) );
350 }
351
352 last = next;
353 }
354 }
355
356 if ( last != null )
357 {
358 logger.debug( String.valueOf( last ) );
359 }
360 }
361 }
362
363 interpolator.clearFeedback();
364 }
365 finally
366 {
367 for ( ValueSource vs : valueSources )
368 {
369 interpolator.removeValuesSource( vs );
370 }
371
372 for ( InterpolationPostProcessor postProcessor : postProcessors )
373 {
374 interpolator.removePostProcessor( postProcessor );
375 }
376 }
377 }
378
379 return result;
380 }
381
382 protected RecursionInterceptor getRecursionInterceptor()
383 {
384 return recursionInterceptor;
385 }
386
387 protected void setRecursionInterceptor( RecursionInterceptor recursionInterceptor )
388 {
389 this.recursionInterceptor = recursionInterceptor;
390 }
391
392 protected abstract Interpolator createInterpolator();
393
394 public void initialize()
395 throws InitializationException
396 {
397 interpolator = createInterpolator();
398 recursionInterceptor = new PrefixAwareRecursionInterceptor( PROJECT_PREFIXES );
399 }
400
401 protected final Interpolator getInterpolator()
402 {
403 return interpolator;
404 }
405
406 }