1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.impl;
20
21 import javax.xml.stream.Location;
22 import javax.xml.stream.XMLStreamException;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.util.Map;
27 import java.util.function.UnaryOperator;
28
29 import org.apache.maven.api.di.Inject;
30 import org.apache.maven.api.di.Named;
31 import org.apache.maven.api.services.BuilderProblem;
32 import org.apache.maven.api.services.Interpolator;
33 import org.apache.maven.api.services.ProblemCollector;
34 import org.apache.maven.api.services.Source;
35 import org.apache.maven.api.services.ToolchainsBuilder;
36 import org.apache.maven.api.services.ToolchainsBuilderException;
37 import org.apache.maven.api.services.ToolchainsBuilderRequest;
38 import org.apache.maven.api.services.ToolchainsBuilderResult;
39 import org.apache.maven.api.services.xml.ToolchainsXmlFactory;
40 import org.apache.maven.api.services.xml.XmlReaderException;
41 import org.apache.maven.api.services.xml.XmlReaderRequest;
42 import org.apache.maven.api.toolchain.PersistedToolchains;
43 import org.apache.maven.toolchain.v4.MavenToolchainsMerger;
44 import org.apache.maven.toolchain.v4.MavenToolchainsTransformer;
45
46
47
48
49
50 @Named
51 public class DefaultToolchainsBuilder implements ToolchainsBuilder {
52
53 private final MavenToolchainsMerger toolchainsMerger = new MavenToolchainsMerger();
54
55 private final Interpolator interpolator;
56
57 private final ToolchainsXmlFactory toolchainsXmlFactory;
58
59 @Inject
60 public DefaultToolchainsBuilder(Interpolator interpolator, ToolchainsXmlFactory toolchainsXmlFactory) {
61 this.interpolator = interpolator;
62 this.toolchainsXmlFactory = toolchainsXmlFactory;
63 }
64
65 @Override
66 public ToolchainsBuilderResult build(ToolchainsBuilderRequest request) throws ToolchainsBuilderException {
67 ProblemCollector<BuilderProblem> problems = ProblemCollector.create(request.getSession());
68
69 Source installationSource = request.getInstallationToolchainsSource().orElse(null);
70 PersistedToolchains installation = readToolchains(installationSource, request, problems);
71
72 Source userSource = request.getUserToolchainsSource().orElse(null);
73 PersistedToolchains user = readToolchains(userSource, request, problems);
74
75 PersistedToolchains effective = toolchainsMerger.merge(user, installation, false, null);
76
77 if (problems.hasErrorProblems()) {
78 throw new ToolchainsBuilderException("Error building toolchains", problems);
79 }
80
81 return new DefaultToolchainsBuilderResult(request, effective, problems);
82 }
83
84 private PersistedToolchains readToolchains(
85 Source toolchainsSource, ToolchainsBuilderRequest request, ProblemCollector<BuilderProblem> problems) {
86 if (toolchainsSource == null) {
87 return PersistedToolchains.newInstance();
88 }
89
90 PersistedToolchains toolchains;
91
92 try {
93 try {
94 InputStream is = toolchainsSource.openStream();
95 if (is == null) {
96 return PersistedToolchains.newInstance();
97 }
98 toolchains = toolchainsXmlFactory.read(XmlReaderRequest.builder()
99 .inputStream(is)
100 .location(toolchainsSource.getLocation())
101 .strict(true)
102 .build());
103 } catch (XmlReaderException e) {
104 InputStream is = toolchainsSource.openStream();
105 if (is == null) {
106 return PersistedToolchains.newInstance();
107 }
108 toolchains = toolchainsXmlFactory.read(XmlReaderRequest.builder()
109 .inputStream(is)
110 .location(toolchainsSource.getLocation())
111 .strict(false)
112 .build());
113 Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
114 problems.reportProblem(new DefaultBuilderProblem(
115 toolchainsSource.getLocation(),
116 loc != null ? loc.getLineNumber() : -1,
117 loc != null ? loc.getColumnNumber() : -1,
118 e,
119 e.getMessage(),
120 BuilderProblem.Severity.WARNING));
121 }
122 } catch (XmlReaderException e) {
123 Location loc = e.getCause() instanceof XMLStreamException xe ? xe.getLocation() : null;
124 problems.reportProblem(new DefaultBuilderProblem(
125 toolchainsSource.getLocation(),
126 loc != null ? loc.getLineNumber() : -1,
127 loc != null ? loc.getColumnNumber() : -1,
128 e,
129 "Non-parseable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(),
130 BuilderProblem.Severity.FATAL));
131 return PersistedToolchains.newInstance();
132 } catch (IOException e) {
133 problems.reportProblem(new DefaultBuilderProblem(
134 toolchainsSource.getLocation(),
135 -1,
136 -1,
137 e,
138 "Non-readable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(),
139 BuilderProblem.Severity.FATAL));
140 return PersistedToolchains.newInstance();
141 }
142
143 toolchains = interpolate(toolchains, request, problems);
144
145 return toolchains;
146 }
147
148 private PersistedToolchains interpolate(
149 PersistedToolchains toolchains,
150 ToolchainsBuilderRequest request,
151 ProblemCollector<BuilderProblem> problems) {
152 Map<String, String> userProperties = request.getSession().getUserProperties();
153 Map<String, String> systemProperties = request.getSession().getSystemProperties();
154 UnaryOperator<String> src = Interpolator.chain(userProperties::get, systemProperties::get);
155 return new MavenToolchainsTransformer(value -> value != null ? interpolator.interpolate(value, src) : null)
156 .visit(toolchains);
157 }
158
159
160
161
162
163 static class DefaultToolchainsBuilderResult implements ToolchainsBuilderResult {
164
165 private final ToolchainsBuilderRequest request;
166
167 private final PersistedToolchains effectiveToolchains;
168
169 private final ProblemCollector<BuilderProblem> problems;
170
171 DefaultToolchainsBuilderResult(
172 ToolchainsBuilderRequest request,
173 PersistedToolchains effectiveToolchains,
174 ProblemCollector<BuilderProblem> problems) {
175 this.request = request;
176 this.effectiveToolchains = effectiveToolchains;
177 this.problems = (problems != null) ? problems : ProblemCollector.empty();
178 }
179
180 @Override
181 public ToolchainsBuilderRequest getRequest() {
182 return request;
183 }
184
185 @Override
186 public PersistedToolchains getEffectiveToolchains() {
187 return effectiveToolchains;
188 }
189
190 @Override
191 public ProblemCollector<BuilderProblem> getProblems() {
192 return problems;
193 }
194 }
195 }