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