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