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