1 package org.apache.maven.model.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.building.ModelBuildingRequest;
24 import org.apache.maven.model.building.ModelProblemCollector;
25 import org.apache.maven.model.building.ModelProblem.Severity;
26 import org.apache.maven.model.path.PathTranslator;
27 import org.apache.maven.model.path.UrlNormalizer;
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
41 import java.io.File;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collection;
45 import java.util.HashSet;
46 import java.util.List;
47 import java.util.Properties;
48 import org.apache.maven.model.building.ModelProblem;
49 import org.apache.maven.model.building.ModelProblem.Version;
50 import org.apache.maven.model.building.ModelProblemCollectorRequest;
51
52
53
54
55
56
57 public abstract class AbstractStringBasedModelInterpolator
58 implements ModelInterpolator
59 {
60
61
62
63
64 static final String DEFAULT_BUILD_TIMESTAMP_FORMAT = "yyyyMMdd-HHmm";
65
66
67
68
69
70 private static final String BUILD_TIMESTAMP_FORMAT_PROPERTY = "maven.build.timestamp.format";
71
72 private static final List<String> PROJECT_PREFIXES = Arrays.asList( new String[]{ "pom.", "project." } );
73
74 private static final Collection<String> TRANSLATED_PATH_EXPRESSIONS;
75
76 static
77 {
78 Collection<String> translatedPrefixes = new HashSet<String>();
79
80
81
82
83
84
85 translatedPrefixes.add( "build.directory" );
86 translatedPrefixes.add( "build.outputDirectory" );
87 translatedPrefixes.add( "build.testOutputDirectory" );
88 translatedPrefixes.add( "build.sourceDirectory" );
89 translatedPrefixes.add( "build.testSourceDirectory" );
90 translatedPrefixes.add( "build.scriptSourceDirectory" );
91 translatedPrefixes.add( "reporting.outputDirectory" );
92
93 TRANSLATED_PATH_EXPRESSIONS = translatedPrefixes;
94 }
95
96 @Requirement
97 private PathTranslator pathTranslator;
98
99 @Requirement
100 private UrlNormalizer urlNormalizer;
101
102 private Interpolator interpolator;
103
104 private RecursionInterceptor recursionInterceptor;
105
106 public AbstractStringBasedModelInterpolator()
107 {
108 interpolator = createInterpolator();
109 recursionInterceptor = new PrefixAwareRecursionInterceptor( PROJECT_PREFIXES );
110 }
111
112 public AbstractStringBasedModelInterpolator setPathTranslator( PathTranslator pathTranslator )
113 {
114 this.pathTranslator = pathTranslator;
115 return this;
116 }
117
118 public AbstractStringBasedModelInterpolator setUrlNormalizer( UrlNormalizer urlNormalizer )
119 {
120 this.urlNormalizer = urlNormalizer;
121 return this;
122 }
123
124 protected List<ValueSource> createValueSources( final Model model, final File projectDir,
125 final ModelBuildingRequest config,
126 final ModelProblemCollector problems )
127 {
128 Properties modelProperties = model.getProperties();
129
130 ValueSource modelValueSource1 = new PrefixedObjectValueSource( PROJECT_PREFIXES, model, false );
131 if ( config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
132 {
133 modelValueSource1 = new ProblemDetectingValueSource( modelValueSource1, "pom.", "project.", problems );
134 }
135
136 ValueSource modelValueSource2 = new ObjectBasedValueSource( model );
137 if ( config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
138 {
139 modelValueSource2 = new ProblemDetectingValueSource( modelValueSource2, "", "project.", problems );
140 }
141
142
143 List<ValueSource> valueSources = new ArrayList<ValueSource>( 9 );
144
145 if ( projectDir != null )
146 {
147 ValueSource basedirValueSource = new PrefixedValueSourceWrapper( new AbstractValueSource( false )
148 {
149 public Object getValue( String expression )
150 {
151 if ( "basedir".equals( expression ) )
152 {
153 return projectDir.getAbsolutePath();
154 }
155 return null;
156 }
157 }, PROJECT_PREFIXES, true );
158 valueSources.add( basedirValueSource );
159
160 ValueSource baseUriValueSource = new PrefixedValueSourceWrapper( new AbstractValueSource( false )
161 {
162 public Object getValue( String expression )
163 {
164 if ( "baseUri".equals( expression ) )
165 {
166 return projectDir.getAbsoluteFile().toURI().toString();
167 }
168 return null;
169 }
170 }, PROJECT_PREFIXES, false );
171 valueSources.add( baseUriValueSource );
172
173 String timestampFormat = DEFAULT_BUILD_TIMESTAMP_FORMAT;
174 if ( modelProperties != null )
175 {
176 timestampFormat = modelProperties.getProperty( BUILD_TIMESTAMP_FORMAT_PROPERTY, timestampFormat );
177 }
178 valueSources.add( new BuildTimestampValueSource( config.getBuildStartTime(), timestampFormat ) );
179 }
180
181 valueSources.add( modelValueSource1 );
182
183 valueSources.add( new MapBasedValueSource( config.getUserProperties() ) );
184
185 valueSources.add( new MapBasedValueSource( modelProperties ) );
186
187 valueSources.add( new MapBasedValueSource( config.getSystemProperties() ) );
188
189 valueSources.add( new AbstractValueSource( false )
190 {
191 public Object getValue( String expression )
192 {
193 return config.getSystemProperties().getProperty( "env." + expression );
194 }
195 } );
196
197 valueSources.add( modelValueSource2 );
198
199 return valueSources;
200 }
201
202 protected List<? extends InterpolationPostProcessor> createPostProcessors( final Model model,
203 final File projectDir,
204 final ModelBuildingRequest config )
205 {
206 List<InterpolationPostProcessor> processors = new ArrayList<InterpolationPostProcessor>( 2 );
207 if ( projectDir != null )
208 {
209 processors.add( new PathTranslatingPostProcessor( PROJECT_PREFIXES, TRANSLATED_PATH_EXPRESSIONS,
210 projectDir, pathTranslator ) );
211 }
212 processors.add( new UrlNormalizingPostProcessor( urlNormalizer ) );
213 return processors;
214 }
215
216 protected String interpolateInternal( String src, List<? extends ValueSource> valueSources,
217 List<? extends InterpolationPostProcessor> postProcessors,
218 ModelProblemCollector problems )
219 {
220 if ( src.indexOf( "${" ) < 0 )
221 {
222 return src;
223 }
224
225 String result = src;
226 synchronized ( this )
227 {
228
229 for ( ValueSource vs : valueSources )
230 {
231 interpolator.addValueSource( vs );
232 }
233
234 for ( InterpolationPostProcessor postProcessor : postProcessors )
235 {
236 interpolator.addPostProcessor( postProcessor );
237 }
238
239 try
240 {
241 try
242 {
243 result = interpolator.interpolate( result, recursionInterceptor );
244 }
245 catch ( InterpolationException e )
246 {
247 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage( e.getMessage() ).setException( e ));
248 }
249
250 interpolator.clearFeedback();
251 }
252 finally
253 {
254 for ( ValueSource vs : valueSources )
255 {
256 interpolator.removeValuesSource( vs );
257 }
258
259 for ( InterpolationPostProcessor postProcessor : postProcessors )
260 {
261 interpolator.removePostProcessor( postProcessor );
262 }
263 }
264 }
265
266 return result;
267 }
268
269 protected RecursionInterceptor getRecursionInterceptor()
270 {
271 return recursionInterceptor;
272 }
273
274 protected void setRecursionInterceptor( RecursionInterceptor recursionInterceptor )
275 {
276 this.recursionInterceptor = recursionInterceptor;
277 }
278
279 protected abstract Interpolator createInterpolator();
280
281 protected final Interpolator getInterpolator()
282 {
283 return interpolator;
284 }
285
286 }