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, SettingsProblemCollector problems )
200 {
201 StringWriter writer = new StringWriter( 1024 * 4 );
202
203 try
204 {
205 settingsWriter.write( writer, null, settings );
206 }
207 catch ( IOException e )
208 {
209 throw new IllegalStateException( "Failed to serialize settings to memory", e );
210 }
211
212 String serializedSettings = writer.toString();
213
214 RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
215
216 interpolator.addValueSource( new PropertiesBasedValueSource( request.getUserProperties() ) );
217
218 interpolator.addValueSource( new PropertiesBasedValueSource( request.getSystemProperties() ) );
219
220 try
221 {
222 interpolator.addValueSource( new EnvarBasedValueSource() );
223 }
224 catch ( IOException e )
225 {
226 problems.add( SettingsProblem.Severity.WARNING, "Failed to use environment variables for interpolation: "
227 + e.getMessage(), -1, -1, e );
228 }
229
230 interpolator.addPostProcessor( new InterpolationPostProcessor()
231 {
232 public Object execute( String expression, Object value )
233 {
234 if ( value != null )
235 {
236
237 value = value.toString().replace( "&", "&" ).replace( "<", "<" ).replace( ">", ">" );
238 return value;
239 }
240 return null;
241 }
242 } );
243
244 try
245 {
246 serializedSettings = interpolator.interpolate( serializedSettings, "settings" );
247 }
248 catch ( InterpolationException e )
249 {
250 problems.add( SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1,
251 e );
252
253 return settings;
254 }
255
256 Settings result;
257 try
258 {
259 Map<String, ?> options = Collections.singletonMap( SettingsReader.IS_STRICT, Boolean.FALSE );
260 result = settingsReader.read( new StringReader( serializedSettings ), options );
261 }
262 catch ( IOException e )
263 {
264 problems.add( SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1,
265 e );
266 return settings;
267 }
268
269 return result;
270 }
271
272 }