1 package org.apache.maven.shared.release.config;
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.FileInputStream;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.util.Map;
30 import java.util.Properties;
31
32 import org.apache.maven.model.Scm;
33 import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder.BuilderReleaseDescriptor;
34 import org.apache.maven.shared.release.scm.IdentifiedScm;
35 import org.codehaus.plexus.component.annotations.Component;
36 import org.codehaus.plexus.component.annotations.Requirement;
37 import org.codehaus.plexus.logging.AbstractLogEnabled;
38 import org.codehaus.plexus.util.StringUtils;
39 import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
40 import org.sonatype.plexus.components.cipher.PlexusCipherException;
41 import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
42 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
43 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
44 import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
45 import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
46
47
48
49
50
51
52 @Component( role = ReleaseDescriptorStore.class, hint = "properties" )
53 public class PropertiesReleaseDescriptorStore
54 extends AbstractLogEnabled
55 implements ReleaseDescriptorStore
56 {
57
58
59
60
61
62 @Requirement( role = SecDispatcher.class, hint = "mng-4384" )
63 private DefaultSecDispatcher secDispatcher;
64
65 @Override
66 public ReleaseDescriptorBuilder read( ReleaseDescriptorBuilder mergeDescriptor )
67 throws ReleaseDescriptorStoreException
68 {
69 return read( mergeDescriptor, getDefaultReleasePropertiesFile( mergeDescriptor.build() ) );
70 }
71
72 public ReleaseDescriptorBuilder read( File file )
73 throws ReleaseDescriptorStoreException
74 {
75 return read( null, file );
76 }
77
78 public ReleaseDescriptorBuilder read( ReleaseDescriptorBuilder mergeDescriptor, File file )
79 throws ReleaseDescriptorStoreException
80 {
81 Properties properties = new Properties();
82
83 try ( InputStream inStream = new FileInputStream( file ) )
84 {
85 properties.load( inStream );
86 }
87 catch ( FileNotFoundException e )
88 {
89 getLogger().debug( file.getName() + " not found - using empty properties" );
90 }
91 catch ( IOException e )
92 {
93 throw new ReleaseDescriptorStoreException(
94 "Error reading properties file '" + file.getName() + "': " + e.getMessage(), e );
95 }
96
97 ReleaseDescriptorBuilder builder;
98 if ( mergeDescriptor != null )
99 {
100 builder = mergeDescriptor;
101 }
102 else
103 {
104 builder = new ReleaseDescriptorBuilder();
105 }
106
107 ReleaseUtils.copyPropertiesToReleaseDescriptor( properties, builder );
108
109 return builder;
110 }
111
112 @Override
113 public void write( ReleaseDescriptor config )
114 throws ReleaseDescriptorStoreException
115 {
116 write( (BuilderReleaseDescriptor) config, getDefaultReleasePropertiesFile( config ) );
117 }
118
119 @Override
120 public void delete( ReleaseDescriptor config )
121 {
122 File file = getDefaultReleasePropertiesFile( config );
123 if ( file.exists() )
124 {
125 file.delete();
126 }
127 }
128
129 public void write( BuilderReleaseDescriptor config, File file )
130 throws ReleaseDescriptorStoreException
131 {
132 Properties properties = new Properties();
133 properties.setProperty( "completedPhase", config.getCompletedPhase() );
134 if ( config.isCommitByProject() )
135 {
136 properties.setProperty( "commitByProject", "true" );
137 }
138 properties.setProperty( "scm.url", config.getScmSourceUrl() );
139 if ( config.getScmId() != null )
140 {
141 properties.setProperty( "scm.id", config.getScmId() );
142 }
143 if ( config.getScmUsername() != null )
144 {
145 properties.setProperty( "scm.username", config.getScmUsername() );
146 }
147 if ( config.getScmPassword() != null )
148 {
149 String password = config.getScmPassword();
150 try
151 {
152 password = encryptAndDecorate( password );
153 }
154 catch ( IllegalStateException | SecDispatcherException | PlexusCipherException e )
155 {
156 getLogger().debug( e.getMessage() );
157 }
158 properties.setProperty( "scm.password", password );
159 }
160 if ( config.getScmPrivateKey() != null )
161 {
162 properties.setProperty( "scm.privateKey", config.getScmPrivateKey() );
163 }
164 if ( config.getScmPrivateKeyPassPhrase() != null )
165 {
166 String passPhrase = config.getScmPrivateKeyPassPhrase();
167 try
168 {
169 passPhrase = encryptAndDecorate( passPhrase );
170 }
171 catch ( IllegalStateException | SecDispatcherException | PlexusCipherException e )
172 {
173 getLogger().debug( e.getMessage() );
174 }
175 properties.setProperty( "scm.passphrase", passPhrase );
176 }
177 if ( config.getScmTagBase() != null )
178 {
179 properties.setProperty( "scm.tagBase", config.getScmTagBase() );
180 }
181 if ( config.getScmBranchBase() != null )
182 {
183 properties.setProperty( "scm.branchBase", config.getScmBranchBase() );
184 }
185 if ( config.getScmReleaseLabel() != null )
186 {
187 properties.setProperty( "scm.tag", config.getScmReleaseLabel() );
188 }
189 if ( config.getScmTagNameFormat() != null )
190 {
191 properties.setProperty( "scm.tagNameFormat", config.getScmTagNameFormat() );
192 }
193 if ( config.getScmCommentPrefix() != null )
194 {
195 properties.setProperty( "scm.commentPrefix", config.getScmCommentPrefix() );
196 }
197 if ( config.getScmDevelopmentCommitComment() != null )
198 {
199 properties.setProperty( "scm.developmentCommitComment", config.getScmDevelopmentCommitComment() );
200 }
201 if ( config.getScmReleaseCommitComment() != null )
202 {
203 properties.setProperty( "scm.releaseCommitComment", config.getScmReleaseCommitComment() );
204 }
205 if ( config.getScmBranchCommitComment() != null )
206 {
207 properties.setProperty( "scm.branchCommitComment", config.getScmBranchCommitComment() );
208 }
209 if ( config.getScmRollbackCommitComment() != null )
210 {
211 properties.setProperty( "scm.rollbackCommitComment", config.getScmRollbackCommitComment() );
212 }
213 if ( config.getAdditionalArguments() != null )
214 {
215 properties.setProperty( "exec.additionalArguments", config.getAdditionalArguments() );
216 }
217 if ( config.getPomFileName() != null )
218 {
219 properties.setProperty( "exec.pomFileName", config.getPomFileName() );
220 }
221 if ( !config.getActivateProfiles().isEmpty() )
222 {
223 properties.setProperty( "exec.activateProfiles",
224 StringUtils.join( config.getActivateProfiles().iterator(), "," ) );
225 }
226 if ( config.getPreparationGoals() != null )
227 {
228 properties.setProperty( "preparationGoals", config.getPreparationGoals() );
229 }
230 if ( config.getCompletionGoals() != null )
231 {
232 properties.setProperty( "completionGoals", config.getCompletionGoals() );
233 }
234 if ( config.getProjectVersionPolicyId() != null )
235 {
236 properties.setProperty( "projectVersionPolicyId", config.getProjectVersionPolicyId() );
237 }
238 if ( config.getProjectNamingPolicyId() != null )
239 {
240 properties.setProperty( "projectNamingPolicyId", config.getProjectNamingPolicyId() );
241 }
242 if ( config.getReleaseStrategyId() != null )
243 {
244 properties.setProperty( "releaseStrategyId", config.getReleaseStrategyId() );
245 }
246
247 properties.setProperty( "exec.snapshotReleasePluginAllowed",
248 Boolean.toString( config.isSnapshotReleasePluginAllowed() ) );
249
250 properties.setProperty( "remoteTagging", Boolean.toString( config.isRemoteTagging() ) );
251
252 properties.setProperty( "pushChanges", Boolean.toString( config.isPushChanges() ) );
253
254 if ( config.getWorkItem() != null )
255 {
256 properties.setProperty( "workItem", config.getWorkItem() );
257 }
258
259
260
261
262
263 for ( Map.Entry<String, ReleaseStageVersions> entry : config.getProjectVersions().entrySet() )
264 {
265 if ( entry.getValue().getRelease() != null )
266 {
267 properties.setProperty( "project.rel." + entry.getKey(), entry.getValue().getRelease() );
268 }
269 if ( entry.getValue().getDevelopment() != null )
270 {
271 properties.setProperty( "project.dev." + entry.getKey(), entry.getValue().getDevelopment() );
272 }
273 }
274
275 for ( Map.Entry<String, Scm> entry : config.getOriginalScmInfo().entrySet() )
276 {
277 Scm scm = entry.getValue();
278 String prefix = "project.scm." + entry.getKey();
279 if ( scm != null )
280 {
281 if ( scm.getConnection() != null )
282 {
283 properties.setProperty( prefix + ".connection", scm.getConnection() );
284 }
285 if ( scm.getDeveloperConnection() != null )
286 {
287 properties.setProperty( prefix + ".developerConnection", scm.getDeveloperConnection() );
288 }
289 if ( scm.getUrl() != null )
290 {
291 properties.setProperty( prefix + ".url", scm.getUrl() );
292 }
293 if ( scm.getTag() != null )
294 {
295 properties.setProperty( prefix + ".tag", scm.getTag() );
296 }
297 if ( scm instanceof IdentifiedScm )
298 {
299 IdentifiedScm identifiedScm = (IdentifiedScm) scm;
300 if ( identifiedScm.getId() != null )
301 {
302 properties.setProperty( prefix + ".id", identifiedScm.getId() );
303 }
304 }
305 }
306 else
307 {
308 properties.setProperty( prefix + ".empty", "true" );
309 }
310 }
311
312 if ( ( config.getResolvedSnapshotDependencies() != null )
313 && ( config.getResolvedSnapshotDependencies().size() > 0 ) )
314 {
315 processResolvedDependencies( properties, config.getResolvedSnapshotDependencies() );
316 }
317
318 try ( OutputStream outStream = new FileOutputStream( file ) )
319 {
320 properties.store( outStream, "release configuration" );
321 }
322 catch ( IOException e )
323 {
324 throw new ReleaseDescriptorStoreException(
325 "Error writing properties file '" + file.getName() + "': " + e.getMessage(), e );
326 }
327 }
328
329 private void processResolvedDependencies( Properties prop, Map<String, ReleaseStageVersions> resolvedDependencies )
330 {
331 for ( Map.Entry<String, ReleaseStageVersions> currentEntry : resolvedDependencies.entrySet() )
332 {
333 ReleaseStageVersions versionMap = currentEntry.getValue();
334
335 prop.setProperty( "dependency." + currentEntry.getKey() + ".release",
336 versionMap.getRelease() );
337 prop.setProperty( "dependency." + currentEntry.getKey() + ".development",
338 versionMap.getDevelopment() );
339 }
340 }
341
342 private static File getDefaultReleasePropertiesFile( ReleaseDescriptor mergeDescriptor )
343 {
344 return new File( mergeDescriptor.getWorkingDirectory(), "release.properties" );
345 }
346
347
348 private String encryptAndDecorate( String passwd )
349 throws IllegalStateException, SecDispatcherException, PlexusCipherException
350 {
351 String configurationFile = secDispatcher.getConfigurationFile();
352
353 if ( configurationFile.startsWith( "~" ) )
354 {
355 configurationFile = System.getProperty( "user.home" ) + configurationFile.substring( 1 );
356 }
357
358 String file = System.getProperty( DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile );
359
360 String master = null;
361
362 SettingsSecurity sec = SecUtil.read( file, true );
363 if ( sec != null )
364 {
365 master = sec.getMaster();
366 }
367
368 if ( master == null )
369 {
370 throw new IllegalStateException( "Master password is not set in the setting security file: " + file );
371 }
372
373 DefaultPlexusCipher cipher = new DefaultPlexusCipher();
374 String masterPasswd = cipher.decryptDecorated( master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION );
375 return cipher.encryptAndDecorate( passwd, masterPasswd );
376 }
377
378 }