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