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 Settings globalSettings = readSettings( request.getGlobalSettingsFile(), request, problems );
90
91 Settings userSettings = readSettings( request.getUserSettingsFile(), request, problems );
92
93 settingsMerger.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL );
94
95 problems.setSource( "" );
96
97 userSettings = interpolate( userSettings, request, problems );
98
99
100 String localRepository = userSettings.getLocalRepository();
101 if ( localRepository != null && localRepository.length() > 0 )
102 {
103 File file = new File( localRepository );
104 if ( !file.isAbsolute() && file.getPath().startsWith( File.separator ) )
105 {
106 userSettings.setLocalRepository( file.getAbsolutePath() );
107 }
108 }
109
110 if ( hasErrors( problems.getProblems() ) )
111 {
112 throw new SettingsBuildingException( problems.getProblems() );
113 }
114
115 return new DefaultSettingsBuildingResult( userSettings, problems.getProblems() );
116 }
117
118 private boolean hasErrors( List<SettingsProblem> problems )
119 {
120 if ( problems != null )
121 {
122 for ( SettingsProblem problem : problems )
123 {
124 if ( SettingsProblem.Severity.ERROR.compareTo( problem.getSeverity() ) >= 0 )
125 {
126 return true;
127 }
128 }
129 }
130
131 return false;
132 }
133
134 private Settings readSettings( File settingsFile, SettingsBuildingRequest request,
135 DefaultSettingsProblemCollector problems )
136 {
137 if ( settingsFile == null || !settingsFile.exists() )
138 {
139 return new Settings();
140 }
141
142 problems.setSource( settingsFile.getAbsolutePath() );
143
144 Settings settings;
145
146 try
147 {
148 Map<String, ?> options = Collections.singletonMap( SettingsReader.IS_STRICT, Boolean.TRUE );
149
150 try
151 {
152 settings = settingsReader.read( settingsFile, options );
153 }
154 catch ( SettingsParseException e )
155 {
156 options = Collections.singletonMap( SettingsReader.IS_STRICT, Boolean.FALSE );
157
158 settings = settingsReader.read( settingsFile, options );
159
160 problems.add( SettingsProblem.Severity.WARNING, e.getMessage(), e.getLineNumber(), e.getColumnNumber(),
161 e );
162 }
163 }
164 catch ( SettingsParseException e )
165 {
166 problems.add( SettingsProblem.Severity.FATAL, "Non-parseable settings " + settingsFile + ": "
167 + e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e );
168 return new Settings();
169 }
170 catch ( IOException e )
171 {
172 problems.add( SettingsProblem.Severity.FATAL, "Non-readable settings " + settingsFile + ": "
173 + e.getMessage(), -1, -1, e );
174 return new Settings();
175 }
176
177 settingsValidator.validate( settings, problems );
178
179 return settings;
180 }
181
182 private Settings interpolate( Settings settings, SettingsBuildingRequest request, SettingsProblemCollector problems )
183 {
184 StringWriter writer = new StringWriter( 1024 * 4 );
185
186 try
187 {
188 settingsWriter.write( writer, null, settings );
189 }
190 catch ( IOException e )
191 {
192 throw new IllegalStateException( "Failed to serialize settings to memory", e );
193 }
194
195 String serializedSettings = writer.toString();
196
197 RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
198
199 interpolator.addValueSource( new PropertiesBasedValueSource( request.getUserProperties() ) );
200
201 interpolator.addValueSource( new PropertiesBasedValueSource( request.getSystemProperties() ) );
202
203 try
204 {
205 interpolator.addValueSource( new EnvarBasedValueSource() );
206 }
207 catch ( IOException e )
208 {
209 problems.add( SettingsProblem.Severity.WARNING, "Failed to use environment variables for interpolation: "
210 + e.getMessage(), -1, -1, e );
211 }
212
213 interpolator.addPostProcessor( new InterpolationPostProcessor()
214 {
215 public Object execute( String expression, Object value )
216 {
217 if ( value != null )
218 {
219
220 value = value.toString().replace( "&", "&" ).replace( "<", "<" ).replace( ">", ">" );
221 return value;
222 }
223 return null;
224 }
225 } );
226
227 try
228 {
229 serializedSettings = interpolator.interpolate( serializedSettings, "settings" );
230 }
231 catch ( InterpolationException e )
232 {
233 problems.add( SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1,
234 e );
235
236 return settings;
237 }
238
239 Settings result;
240 try
241 {
242 Map<String, ?> options = Collections.singletonMap( SettingsReader.IS_STRICT, Boolean.FALSE );
243 result = settingsReader.read( new StringReader( serializedSettings ), options );
244 }
245 catch ( IOException e )
246 {
247 problems.add( SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1,
248 e );
249 return settings;
250 }
251
252 return result;
253 }
254
255 }