1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.settings.building;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.StringReader;
24 import java.io.StringWriter;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Map;
28 import javax.inject.Inject;
29 import javax.inject.Named;
30 import javax.inject.Singleton;
31 import org.apache.maven.api.settings.Settings;
32 import org.apache.maven.building.FileSource;
33 import org.apache.maven.building.Source;
34 import org.apache.maven.settings.TrackableBase;
35 import org.apache.maven.settings.io.SettingsParseException;
36 import org.apache.maven.settings.io.SettingsReader;
37 import org.apache.maven.settings.io.SettingsWriter;
38 import org.apache.maven.settings.merge.MavenSettingsMerger;
39 import org.apache.maven.settings.validation.SettingsValidator;
40 import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
41 import org.codehaus.plexus.interpolation.InterpolationException;
42 import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
43 import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
44
45
46
47
48
49
50 @Named
51 @Singleton
52 public class DefaultSettingsBuilder implements SettingsBuilder {
53
54 private SettingsReader settingsReader;
55
56 private SettingsWriter settingsWriter;
57
58 private SettingsValidator settingsValidator;
59
60 private final MavenSettingsMerger settingsMerger = new MavenSettingsMerger();
61
62 @Inject
63 public DefaultSettingsBuilder(
64 SettingsReader settingsReader, SettingsWriter settingsWriter, SettingsValidator settingsValidator) {
65 this.settingsReader = settingsReader;
66 this.settingsWriter = settingsWriter;
67 this.settingsValidator = settingsValidator;
68 }
69
70 public DefaultSettingsBuilder setSettingsReader(SettingsReader settingsReader) {
71 this.settingsReader = settingsReader;
72 return this;
73 }
74
75 public DefaultSettingsBuilder setSettingsWriter(SettingsWriter settingsWriter) {
76 this.settingsWriter = settingsWriter;
77 return this;
78 }
79
80 public DefaultSettingsBuilder setSettingsValidator(SettingsValidator settingsValidator) {
81 this.settingsValidator = settingsValidator;
82 return this;
83 }
84
85 @Override
86 public SettingsBuildingResult build(SettingsBuildingRequest request) throws SettingsBuildingException {
87 DefaultSettingsProblemCollector problems = new DefaultSettingsProblemCollector(null);
88
89 Source globalSettingsSource =
90 getSettingsSource(request.getGlobalSettingsFile(), request.getGlobalSettingsSource());
91 Settings globalSettings = readSettings(globalSettingsSource, request, problems);
92
93 Source userSettingsSource = getSettingsSource(request.getUserSettingsFile(), request.getUserSettingsSource());
94 Settings userSettings = readSettings(userSettingsSource, request, problems);
95
96 userSettings = settingsMerger.merge(userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL);
97
98 problems.setSource("");
99
100 userSettings = interpolate(userSettings, request, problems);
101
102
103 String localRepository = userSettings.getLocalRepository();
104 if (localRepository != null && localRepository.length() > 0) {
105 File file = new File(localRepository);
106 if (!file.isAbsolute() && file.getPath().startsWith(File.separator)) {
107 userSettings = userSettings.withLocalRepository(file.getAbsolutePath());
108 }
109 }
110
111 if (hasErrors(problems.getProblems())) {
112 throw new SettingsBuildingException(problems.getProblems());
113 }
114
115 return new DefaultSettingsBuildingResult(
116 new org.apache.maven.settings.Settings(userSettings), problems.getProblems());
117 }
118
119 private boolean hasErrors(List<SettingsProblem> problems) {
120 if (problems != null) {
121 for (SettingsProblem problem : problems) {
122 if (SettingsProblem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
123 return true;
124 }
125 }
126 }
127
128 return false;
129 }
130
131 private Source getSettingsSource(File settingsFile, Source settingsSource) {
132 if (settingsSource != null) {
133 return settingsSource;
134 } else if (settingsFile != null && settingsFile.exists()) {
135 return new FileSource(settingsFile);
136 }
137 return null;
138 }
139
140 private Settings readSettings(
141 Source settingsSource, SettingsBuildingRequest request, DefaultSettingsProblemCollector problems) {
142 if (settingsSource == null) {
143 return Settings.newInstance();
144 }
145
146 problems.setSource(settingsSource.getLocation());
147
148 Settings settings;
149
150 try {
151 Map<String, ?> options = Collections.singletonMap(SettingsReader.IS_STRICT, Boolean.TRUE);
152
153 try {
154 settings = settingsReader.read(settingsSource.getInputStream(), options);
155 } catch (SettingsParseException e) {
156 options = Collections.singletonMap(SettingsReader.IS_STRICT, Boolean.FALSE);
157
158 settings = settingsReader.read(settingsSource.getInputStream(), options);
159
160 problems.add(
161 SettingsProblem.Severity.WARNING, e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
162 }
163 } catch (SettingsParseException e) {
164 problems.add(
165 SettingsProblem.Severity.FATAL,
166 "Non-parseable settings " + settingsSource.getLocation() + ": " + e.getMessage(),
167 e.getLineNumber(),
168 e.getColumnNumber(),
169 e);
170 return Settings.newInstance();
171 } catch (IOException e) {
172 problems.add(
173 SettingsProblem.Severity.FATAL,
174 "Non-readable settings " + settingsSource.getLocation() + ": " + e.getMessage(),
175 -1,
176 -1,
177 e);
178 return Settings.newInstance();
179 }
180
181 settingsValidator.validate(settings, problems);
182
183 return settings;
184 }
185
186 private Settings interpolate(
187 Settings settings, SettingsBuildingRequest request, SettingsProblemCollector problems) {
188 StringWriter writer = new StringWriter(1024 * 4);
189
190 try {
191 settingsWriter.write(writer, null, settings);
192 } catch (IOException e) {
193 throw new IllegalStateException("Failed to serialize settings to memory", e);
194 }
195
196 String serializedSettings = writer.toString();
197
198 RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
199
200 interpolator.addValueSource(new PropertiesBasedValueSource(request.getUserProperties()));
201
202 interpolator.addValueSource(new PropertiesBasedValueSource(request.getSystemProperties()));
203
204 try {
205 interpolator.addValueSource(new EnvarBasedValueSource());
206 } catch (IOException e) {
207 problems.add(
208 SettingsProblem.Severity.WARNING,
209 "Failed to use environment variables for interpolation: " + e.getMessage(),
210 -1,
211 -1,
212 e);
213 }
214
215 interpolator.addPostProcessor((expression, value) -> {
216 if (value != null) {
217
218 value = value.toString()
219 .replace("&", "&")
220 .replace("<", "<")
221 .replace(">", ">");
222 return value;
223 }
224 return null;
225 });
226
227 try {
228 serializedSettings = interpolator.interpolate(serializedSettings, "settings");
229 } catch (InterpolationException e) {
230 problems.add(
231 SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1, e);
232
233 return settings;
234 }
235
236 Settings result;
237 try {
238 Map<String, ?> options = Collections.singletonMap(SettingsReader.IS_STRICT, Boolean.FALSE);
239 result = settingsReader.read(new StringReader(serializedSettings), options);
240 } catch (IOException e) {
241 problems.add(
242 SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1, e);
243 return settings;
244 }
245
246 return result;
247 }
248 }