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