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