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