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