1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.toolchain.building;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.IOException;
26 import java.io.StringReader;
27 import java.io.StringWriter;
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.Map;
31
32 import org.apache.maven.building.Problem;
33 import org.apache.maven.building.ProblemCollector;
34 import org.apache.maven.building.ProblemCollectorFactory;
35 import org.apache.maven.building.Source;
36 import org.apache.maven.toolchain.io.ToolchainsParseException;
37 import org.apache.maven.toolchain.io.ToolchainsReader;
38 import org.apache.maven.toolchain.io.ToolchainsWriter;
39 import org.apache.maven.toolchain.merge.MavenToolchainMerger;
40 import org.apache.maven.toolchain.model.PersistedToolchains;
41 import org.apache.maven.toolchain.model.TrackableBase;
42 import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
43 import org.codehaus.plexus.interpolation.InterpolationException;
44 import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
45
46
47
48
49
50
51 @Named
52 @Singleton
53 public class DefaultToolchainsBuilder implements ToolchainsBuilder {
54 private final MavenToolchainMerger toolchainsMerger = new MavenToolchainMerger();
55 private final ToolchainsWriter toolchainsWriter;
56 private final ToolchainsReader toolchainsReader;
57
58 @Inject
59 public DefaultToolchainsBuilder(ToolchainsWriter toolchainsWriter, ToolchainsReader toolchainsReader) {
60 this.toolchainsWriter = toolchainsWriter;
61 this.toolchainsReader = toolchainsReader;
62 }
63
64 @Override
65 public ToolchainsBuildingResult build(ToolchainsBuildingRequest request) throws ToolchainsBuildingException {
66 ProblemCollector problems = ProblemCollectorFactory.newInstance(null);
67
68 PersistedToolchains globalToolchains = readToolchains(request.getGlobalToolchainsSource(), request, problems);
69
70 PersistedToolchains userToolchains = readToolchains(request.getUserToolchainsSource(), request, problems);
71
72 toolchainsMerger.merge(userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL);
73
74 problems.setSource("");
75
76 userToolchains = interpolate(userToolchains, problems);
77
78 if (hasErrors(problems.getProblems())) {
79 throw new ToolchainsBuildingException(problems.getProblems());
80 }
81
82 return new DefaultToolchainsBuildingResult(userToolchains, problems.getProblems());
83 }
84
85 private PersistedToolchains interpolate(PersistedToolchains toolchains, ProblemCollector problems) {
86
87 StringWriter stringWriter = new StringWriter(1024 * 4);
88 try {
89 toolchainsWriter.write(stringWriter, null, toolchains);
90 } catch (IOException e) {
91 throw new IllegalStateException("Failed to serialize toolchains to memory", e);
92 }
93
94 String serializedToolchains = stringWriter.toString();
95
96 RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
97
98 try {
99 interpolator.addValueSource(new EnvarBasedValueSource());
100 } catch (IOException e) {
101 problems.add(
102 Problem.Severity.WARNING,
103 "Failed to use environment variables for interpolation: " + e.getMessage(),
104 -1,
105 -1,
106 e);
107 }
108
109 interpolator.addPostProcessor((expression, value) -> {
110 if (value != null) {
111
112 value = value.toString()
113 .replace("&", "&")
114 .replace("<", "<")
115 .replace(">", ">");
116 return value;
117 }
118 return null;
119 });
120
121 try {
122 serializedToolchains = interpolator.interpolate(serializedToolchains);
123 } catch (InterpolationException e) {
124 problems.add(Problem.Severity.ERROR, "Failed to interpolate toolchains: " + e.getMessage(), -1, -1, e);
125 return toolchains;
126 }
127
128 PersistedToolchains result;
129 try {
130 Map<String, ?> options = Collections.singletonMap(ToolchainsReader.IS_STRICT, Boolean.FALSE);
131
132 result = toolchainsReader.read(new StringReader(serializedToolchains), options);
133 } catch (IOException e) {
134 problems.add(Problem.Severity.ERROR, "Failed to interpolate toolchains: " + e.getMessage(), -1, -1, e);
135 return toolchains;
136 }
137
138 return result;
139 }
140
141 private PersistedToolchains readToolchains(
142 Source toolchainsSource, ToolchainsBuildingRequest request, ProblemCollector problems) {
143 if (toolchainsSource == null) {
144 return new PersistedToolchains();
145 }
146
147 PersistedToolchains toolchains;
148
149 try {
150 Map<String, ?> options = Collections.singletonMap(ToolchainsReader.IS_STRICT, Boolean.TRUE);
151
152 try {
153 toolchains = toolchainsReader.read(toolchainsSource.getInputStream(), options);
154 } catch (ToolchainsParseException e) {
155 options = Collections.singletonMap(ToolchainsReader.IS_STRICT, Boolean.FALSE);
156
157 toolchains = toolchainsReader.read(toolchainsSource.getInputStream(), options);
158
159 problems.add(Problem.Severity.WARNING, e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
160 }
161 } catch (ToolchainsParseException e) {
162 problems.add(
163 Problem.Severity.FATAL,
164 "Non-parseable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(),
165 e.getLineNumber(),
166 e.getColumnNumber(),
167 e);
168 return new PersistedToolchains();
169 } catch (IOException e) {
170 problems.add(
171 Problem.Severity.FATAL,
172 "Non-readable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(),
173 -1,
174 -1,
175 e);
176 return new PersistedToolchains();
177 }
178
179 return toolchains;
180 }
181
182 private boolean hasErrors(List<Problem> problems) {
183 if (problems != null) {
184 for (Problem problem : problems) {
185 if (Problem.Severity.ERROR.compareTo(problem.getSeverity()) >= 0) {
186 return true;
187 }
188 }
189 }
190
191 return false;
192 }
193 }