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