1 package org.apache.maven.settings.building;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.StringReader;
25 import java.io.StringWriter;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.maven.building.FileSource;
31 import org.apache.maven.building.Source;
32 import org.apache.maven.settings.Settings;
33 import org.apache.maven.settings.TrackableBase;
34 import org.apache.maven.settings.io.SettingsParseException;
35 import org.apache.maven.settings.io.SettingsReader;
36 import org.apache.maven.settings.io.SettingsWriter;
37 import org.apache.maven.settings.merge.MavenSettingsMerger;
38 import org.apache.maven.settings.validation.SettingsValidator;
39 import org.codehaus.plexus.component.annotations.Component;
40 import org.codehaus.plexus.component.annotations.Requirement;
41 import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
42 import org.codehaus.plexus.interpolation.InterpolationException;
43 import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
44 import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
45 import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
46
47
48
49
50
51
52 @Component( role = SettingsBuilder.class )
53 public class DefaultSettingsBuilder
54 implements SettingsBuilder
55 {
56
57 @Requirement
58 private SettingsReader settingsReader;
59
60 @Requirement
61 private SettingsWriter settingsWriter;
62
63 @Requirement
64 private SettingsValidator settingsValidator;
65
66 private MavenSettingsMerger settingsMerger = new MavenSettingsMerger();
67
68 public DefaultSettingsBuilder setSettingsReader( SettingsReader settingsReader )
69 {
70 this.settingsReader = settingsReader;
71 return this;
72 }
73
74 public DefaultSettingsBuilder setSettingsWriter( SettingsWriter settingsWriter )
75 {
76 this.settingsWriter = settingsWriter;
77 return this;
78 }
79
80 public DefaultSettingsBuilder setSettingsValidator( SettingsValidator settingsValidator )
81 {
82 this.settingsValidator = settingsValidator;
83 return this;
84 }
85
86 @Override
87 public SettingsBuildingResult build( SettingsBuildingRequest request )
88 throws SettingsBuildingException
89 {
90 DefaultSettingsProblemCollector problems = new DefaultSettingsProblemCollector( null );
91
92 Source globalSettingsSource =
93 getSettingsSource( request.getGlobalSettingsFile(), request.getGlobalSettingsSource() );
94 Settings globalSettings = readSettings( globalSettingsSource, request, problems );
95
96 Source userSettingsSource =
97 getSettingsSource( request.getUserSettingsFile(), request.getUserSettingsSource() );
98 Settings userSettings = readSettings( userSettingsSource, request, problems );
99
100 settingsMerger.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL );
101
102 problems.setSource( "" );
103
104 userSettings = interpolate( userSettings, request, problems );
105
106
107 String localRepository = userSettings.getLocalRepository();
108 if ( localRepository != null && localRepository.length() > 0 )
109 {
110 File file = new File( localRepository );
111 if ( !file.isAbsolute() && file.getPath().startsWith( File.separator ) )
112 {
113 userSettings.setLocalRepository( file.getAbsolutePath() );
114 }
115 }
116
117 if ( hasErrors( problems.getProblems() ) )
118 {
119 throw new SettingsBuildingException( problems.getProblems() );
120 }
121
122 return new DefaultSettingsBuildingResult( userSettings, problems.getProblems() );
123 }
124
125 private boolean hasErrors( List<SettingsProblem> problems )
126 {
127 if ( problems != null )
128 {
129 for ( SettingsProblem problem : problems )
130 {
131 if ( SettingsProblem.Severity.ERROR.compareTo( problem.getSeverity() ) >= 0 )
132 {
133 return true;
134 }
135 }
136 }
137
138 return false;
139 }
140
141 private Source getSettingsSource( File settingsFile, Source settingsSource )
142 {
143 if ( settingsSource != null )
144 {
145 return settingsSource;
146 }
147 else if ( settingsFile != null && settingsFile.exists() )
148 {
149 return new FileSource( settingsFile );
150 }
151 return null;
152 }
153
154 private Settings readSettings( Source settingsSource, SettingsBuildingRequest request,
155 DefaultSettingsProblemCollector problems )
156 {
157 if ( settingsSource == null )
158 {
159 return new Settings();
160 }
161
162 problems.setSource( settingsSource.getLocation() );
163
164 Settings settings;
165
166 try
167 {
168 Map<String, ?> options = Collections.singletonMap( SettingsReader.IS_STRICT, Boolean.TRUE );
169
170 try
171 {
172 settings = settingsReader.read( settingsSource.getInputStream(), options );
173 }
174 catch ( SettingsParseException e )
175 {
176 options = Collections.singletonMap( SettingsReader.IS_STRICT, Boolean.FALSE );
177
178 settings = settingsReader.read( settingsSource.getInputStream(), options );
179
180 problems.add( SettingsProblem.Severity.WARNING, e.getMessage(), e.getLineNumber(), e.getColumnNumber(),
181 e );
182 }
183 }
184 catch ( SettingsParseException e )
185 {
186 problems.add( SettingsProblem.Severity.FATAL, "Non-parseable settings " + settingsSource.getLocation()
187 + ": " + e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e );
188 return new Settings();
189 }
190 catch ( IOException e )
191 {
192 problems.add( SettingsProblem.Severity.FATAL, "Non-readable settings " + settingsSource.getLocation()
193 + ": " + e.getMessage(), -1, -1, e );
194 return new Settings();
195 }
196
197 settingsValidator.validate( settings, problems );
198
199 return settings;
200 }
201
202 private Settings interpolate( Settings settings, SettingsBuildingRequest request,
203 SettingsProblemCollector problems )
204 {
205 StringWriter writer = new StringWriter( 1024 * 4 );
206
207 try
208 {
209 settingsWriter.write( writer, null, settings );
210 }
211 catch ( IOException e )
212 {
213 throw new IllegalStateException( "Failed to serialize settings to memory", e );
214 }
215
216 String serializedSettings = writer.toString();
217
218 RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
219
220 interpolator.addValueSource( new PropertiesBasedValueSource( request.getUserProperties() ) );
221
222 interpolator.addValueSource( new PropertiesBasedValueSource( request.getSystemProperties() ) );
223
224 try
225 {
226 interpolator.addValueSource( new EnvarBasedValueSource() );
227 }
228 catch ( IOException e )
229 {
230 problems.add( SettingsProblem.Severity.WARNING, "Failed to use environment variables for interpolation: "
231 + e.getMessage(), -1, -1, e );
232 }
233
234 interpolator.addPostProcessor( new InterpolationPostProcessor()
235 {
236 @Override
237 public Object execute( String expression, Object value )
238 {
239 if ( value != null )
240 {
241
242 value = value.toString().replace( "&", "&" ).replace( "<", "<" ).replace( ">", ">" );
243 return value;
244 }
245 return null;
246 }
247 } );
248
249 try
250 {
251 serializedSettings = interpolator.interpolate( serializedSettings, "settings" );
252 }
253 catch ( InterpolationException e )
254 {
255 problems.add( SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1,
256 e );
257
258 return settings;
259 }
260
261 Settings result;
262 try
263 {
264 Map<String, ?> options = Collections.singletonMap( SettingsReader.IS_STRICT, Boolean.FALSE );
265 result = settingsReader.read( new StringReader( serializedSettings ), options );
266 }
267 catch ( IOException e )
268 {
269 problems.add( SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1,
270 e );
271 return settings;
272 }
273
274 return result;
275 }
276
277 }