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