View Javadoc
1   package org.apache.maven.model.interpolation;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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 javax.inject.Inject;
31  
32  import org.apache.maven.model.Model;
33  import org.apache.maven.model.building.ModelBuildingRequest;
34  import org.apache.maven.model.building.ModelProblemCollector;
35  import org.apache.maven.model.path.PathTranslator;
36  import org.apache.maven.model.path.UrlNormalizer;
37  import org.codehaus.plexus.interpolation.AbstractValueSource;
38  import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
39  import org.codehaus.plexus.interpolation.MapBasedValueSource;
40  import org.codehaus.plexus.interpolation.ObjectBasedValueSource;
41  import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
42  import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
43  import org.codehaus.plexus.interpolation.PrefixedValueSourceWrapper;
44  import org.codehaus.plexus.interpolation.RecursionInterceptor;
45  import org.codehaus.plexus.interpolation.ValueSource;
46  
47  /**
48   * Use a regular expression search to find and resolve expressions within the POM.
49   *
50   * @author jdcasey Created on Feb 3, 2005
51   */
52  public abstract class AbstractStringBasedModelInterpolator
53      implements ModelInterpolator
54  {
55      public static final String SHA1_PROPERTY = "sha1";
56  
57      public static final String CHANGELIST_PROPERTY = "changelist";
58  
59      public static final String REVISION_PROPERTY = "revision";
60  
61      private static final List<String> PROJECT_PREFIXES = Arrays.asList( "pom.", "project." );
62  
63      private static final Collection<String> TRANSLATED_PATH_EXPRESSIONS;
64  
65      static
66      {
67          Collection<String> translatedPrefixes = new HashSet<>();
68  
69          // MNG-1927, MNG-2124, MNG-3355:
70          // If the build section is present and the project directory is non-null, we should make
71          // sure interpolation of the directories below uses translated paths.
72          // Afterward, we'll double back and translate any paths that weren't covered during interpolation via the
73          // code below...
74          translatedPrefixes.add( "build.directory" );
75          translatedPrefixes.add( "build.outputDirectory" );
76          translatedPrefixes.add( "build.testOutputDirectory" );
77          translatedPrefixes.add( "build.sourceDirectory" );
78          translatedPrefixes.add( "build.testSourceDirectory" );
79          translatedPrefixes.add( "build.scriptSourceDirectory" );
80          translatedPrefixes.add( "reporting.outputDirectory" );
81  
82          TRANSLATED_PATH_EXPRESSIONS = translatedPrefixes;
83      }
84  
85      @Inject
86      private PathTranslator pathTranslator;
87  
88      @Inject
89      private UrlNormalizer urlNormalizer;
90  
91      public AbstractStringBasedModelInterpolator()
92      {
93      }
94  
95      public AbstractStringBasedModelInterpolator setPathTranslator( PathTranslator pathTranslator )
96      {
97          this.pathTranslator = pathTranslator;
98          return this;
99      }
100 
101     public AbstractStringBasedModelInterpolator setUrlNormalizer( UrlNormalizer urlNormalizer )
102     {
103         this.urlNormalizer = urlNormalizer;
104         return this;
105     }
106 
107     protected List<ValueSource> createValueSources( final Model model, final File projectDir,
108                                                     final ModelBuildingRequest config,
109                                                     final ModelProblemCollector problems )
110     {
111         Properties modelProperties = model.getProperties();
112 
113         ValueSource modelValueSource1 = new PrefixedObjectValueSource( PROJECT_PREFIXES, model, false );
114         if ( config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
115         {
116             modelValueSource1 = new ProblemDetectingValueSource( modelValueSource1, "pom.", "project.", problems );
117         }
118 
119         ValueSource modelValueSource2 = new ObjectBasedValueSource( model );
120         if ( config.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
121         {
122             modelValueSource2 = new ProblemDetectingValueSource( modelValueSource2, "", "project.", problems );
123         }
124 
125         // NOTE: Order counts here!
126         List<ValueSource> valueSources = new ArrayList<>( 9 );
127 
128         if ( projectDir != null )
129         {
130             ValueSource basedirValueSource = new PrefixedValueSourceWrapper( new AbstractValueSource( false )
131             {
132                 @Override
133                 public Object getValue( String expression )
134                 {
135                     if ( "basedir".equals( expression ) )
136                     {
137                         return projectDir.getAbsolutePath();
138                     }
139                     return null;
140                 }
141             }, PROJECT_PREFIXES, true );
142             valueSources.add( basedirValueSource );
143 
144             ValueSource baseUriValueSource = new PrefixedValueSourceWrapper( new AbstractValueSource( false )
145             {
146                 @Override
147                 public Object getValue( String expression )
148                 {
149                     if ( "baseUri".equals( expression ) )
150                     {
151                         return projectDir.getAbsoluteFile().toPath().toUri().toASCIIString();
152                     }
153                     return null;
154                 }
155             }, PROJECT_PREFIXES, false );
156             valueSources.add( baseUriValueSource );
157             valueSources.add( new BuildTimestampValueSource( config.getBuildStartTime(), modelProperties ) );
158         }
159 
160         valueSources.add( modelValueSource1 );
161 
162         valueSources.add( new MapBasedValueSource( config.getUserProperties() ) );
163 
164         // Overwrite existing values in model properties. Otherwise it's not possible
165         // to define the version via command line: mvn -Drevision=6.5.7 ...
166         if ( config.getSystemProperties().containsKey( REVISION_PROPERTY ) )
167         {
168             modelProperties.put( REVISION_PROPERTY, config.getSystemProperties().get( REVISION_PROPERTY ) );
169         }
170         if ( config.getSystemProperties().containsKey( CHANGELIST_PROPERTY ) )
171         {
172             modelProperties.put( CHANGELIST_PROPERTY, config.getSystemProperties().get( CHANGELIST_PROPERTY ) );
173         }
174         if ( config.getSystemProperties().containsKey( SHA1_PROPERTY ) )
175         {
176             modelProperties.put( SHA1_PROPERTY, config.getSystemProperties().get( SHA1_PROPERTY ) );
177         }
178         valueSources.add( new MapBasedValueSource( modelProperties ) );
179 
180         valueSources.add( new MapBasedValueSource( config.getSystemProperties() ) );
181 
182         valueSources.add( new AbstractValueSource( false )
183         {
184             @Override
185             public Object getValue( String expression )
186             {
187                 return config.getSystemProperties().getProperty( "env." + expression );
188             }
189         } );
190 
191         valueSources.add( modelValueSource2 );
192 
193         return valueSources;
194     }
195 
196     protected List<? extends InterpolationPostProcessor> createPostProcessors( final Model model,
197                                                                                final File projectDir,
198                                                                                final ModelBuildingRequest config )
199     {
200         List<InterpolationPostProcessor> processors = new ArrayList<>( 2 );
201         if ( projectDir != null )
202         {
203             processors.add( new PathTranslatingPostProcessor( PROJECT_PREFIXES, TRANSLATED_PATH_EXPRESSIONS,
204                                                               projectDir, pathTranslator ) );
205         }
206         processors.add( new UrlNormalizingPostProcessor( urlNormalizer ) );
207         return processors;
208     }
209 
210     protected RecursionInterceptor createRecursionInterceptor()
211     {
212         return new PrefixAwareRecursionInterceptor( PROJECT_PREFIXES );
213     }
214 
215 }