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