1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.scm.plugin;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Map.Entry;
28 import java.util.Objects;
29 import java.util.Properties;
30
31 import org.apache.commons.lang3.StringUtils;
32 import org.apache.maven.plugin.AbstractMojo;
33 import org.apache.maven.plugin.MojoExecutionException;
34 import org.apache.maven.plugins.annotations.Parameter;
35 import org.apache.maven.scm.ScmBranch;
36 import org.apache.maven.scm.ScmException;
37 import org.apache.maven.scm.ScmFileSet;
38 import org.apache.maven.scm.ScmResult;
39 import org.apache.maven.scm.ScmRevision;
40 import org.apache.maven.scm.ScmTag;
41 import org.apache.maven.scm.ScmVersion;
42 import org.apache.maven.scm.manager.ScmManager;
43 import org.apache.maven.scm.provider.ScmProviderRepository;
44 import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
45 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
46 import org.apache.maven.scm.repository.ScmRepository;
47 import org.apache.maven.scm.repository.ScmRepositoryException;
48 import org.apache.maven.settings.Server;
49 import org.apache.maven.settings.Settings;
50 import org.apache.maven.settings.building.SettingsProblem;
51 import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
52 import org.apache.maven.settings.crypto.SettingsDecrypter;
53 import org.apache.maven.settings.crypto.SettingsDecryptionResult;
54 import org.apache.maven.shared.model.fileset.FileSet;
55 import org.apache.maven.shared.model.fileset.util.FileSetManager;
56
57
58
59
60
61 public abstract class AbstractScmMojo extends AbstractMojo {
62
63 protected static final String VERSION_TYPE_BRANCH = "branch";
64
65 protected static final String VERSION_TYPE_REVISION = "revision";
66
67 protected static final String VERSION_TYPE_TAG = "tag";
68
69 protected static final String[] VALID_VERSION_TYPES = {VERSION_TYPE_BRANCH, VERSION_TYPE_REVISION, VERSION_TYPE_TAG
70 };
71
72
73
74
75 @Parameter(property = "connectionUrl", defaultValue = "${project.scm.connection}")
76 private String connectionUrl;
77
78
79
80
81 @Parameter(property = "developerConnectionUrl", defaultValue = "${project.scm.developerConnection}")
82 private String developerConnectionUrl;
83
84
85
86
87 @Parameter(property = "connectionType", defaultValue = "connection")
88 private String connectionType;
89
90
91
92
93 @Parameter(property = "workingDirectory")
94 private File workingDirectory;
95
96
97
98
99
100 @Parameter(property = "username")
101 private String username;
102
103
104
105
106
107 @Parameter(property = "password")
108 private String password;
109
110
111
112
113
114 @Parameter(property = "privateKey")
115 private String privateKey;
116
117
118
119
120
121 @Parameter(property = "passphrase")
122 private String passphrase;
123
124
125
126
127
128
129
130
131
132
133
134
135 @Parameter(property = "project.scm.id")
136 private String serverId;
137
138
139
140
141
142
143 @Parameter(property = "tagBase")
144 private String tagBase;
145
146
147
148
149 @Parameter(property = "includes")
150 private String includes;
151
152
153
154
155 @Parameter(property = "excludes")
156 private String excludes;
157
158
159
160
161 @Parameter(property = "basedir", required = true)
162 private File basedir;
163
164 @Parameter(defaultValue = "${settings}", readonly = true)
165 private Settings settings;
166
167
168
169
170 @Parameter
171 private Properties systemProperties;
172
173
174
175
176
177
178 @Parameter
179 private Map<String, String> providerImplementations;
180
181
182
183
184
185
186
187
188
189 @Parameter(property = "pushChanges", defaultValue = "true")
190 private boolean pushChanges;
191
192
193
194
195
196
197
198 @Parameter(property = "workItem")
199 @Deprecated
200 private String workItem;
201
202 private final ScmManager manager;
203
204 private final SettingsDecrypter settingsDecrypter;
205
206 protected AbstractScmMojo(ScmManager manager, SettingsDecrypter settingsDecrypter) {
207 this.manager = manager;
208 this.settingsDecrypter = settingsDecrypter;
209 }
210
211
212 public void execute() throws MojoExecutionException {
213 if (systemProperties != null) {
214
215 Iterator<Object> iter = systemProperties.keySet().iterator();
216
217 while (iter.hasNext()) {
218 String key = (String) iter.next();
219
220 String value = systemProperties.getProperty(key);
221
222 System.setProperty(key, value);
223 }
224 }
225
226 if (providerImplementations != null && !providerImplementations.isEmpty()) {
227 for (Entry<String, String> entry : providerImplementations.entrySet()) {
228 String providerType = entry.getKey();
229 String providerImplementation = entry.getValue();
230 getLog().info("Change the default '" + providerType + "' provider implementation to '"
231 + providerImplementation + "'.");
232 getScmManager().setScmProviderImplementation(providerType, providerImplementation);
233 }
234 }
235 }
236
237 protected void setConnectionType(String connectionType) {
238 this.connectionType = connectionType;
239 }
240
241 public String getConnectionUrl() {
242 boolean requireDeveloperConnection = !"connection".equals(connectionType.toLowerCase());
243 if ((connectionUrl != null && !connectionUrl.isEmpty()) && !requireDeveloperConnection) {
244 return connectionUrl;
245 } else if (developerConnectionUrl != null && !developerConnectionUrl.isEmpty()) {
246 return developerConnectionUrl;
247 }
248 if (requireDeveloperConnection) {
249 throw new NullPointerException("You need to define a developerConnectionUrl parameter");
250 } else {
251 throw new NullPointerException("You need to define a connectionUrl parameter");
252 }
253 }
254
255 public void setConnectionUrl(String connectionUrl) {
256 this.connectionUrl = connectionUrl;
257 }
258
259 public File getWorkingDirectory() {
260 if (workingDirectory == null) {
261 return basedir;
262 }
263
264 return workingDirectory;
265 }
266
267 public File getBasedir() {
268 return this.basedir;
269 }
270
271 public void setWorkingDirectory(File workingDirectory) {
272 this.workingDirectory = workingDirectory;
273 }
274
275 public ScmManager getScmManager() {
276 return manager;
277 }
278
279 public ScmFileSet getFileSet() throws IOException {
280 if (includes != null || excludes != null) {
281 return new ScmFileSet(getWorkingDirectory(), includes, excludes);
282 } else {
283 return new ScmFileSet(getWorkingDirectory());
284 }
285 }
286
287 public ScmRepository getScmRepository() throws ScmException {
288 ScmRepository repository;
289
290 try {
291 repository = getScmManager().makeScmRepository(getConnectionUrl());
292
293 ScmProviderRepository providerRepo = repository.getProviderRepository();
294
295 providerRepo.setPushChanges(pushChanges);
296
297 if (!(workItem == null || workItem.isEmpty())) {
298 providerRepo.setWorkItem(workItem);
299 }
300
301 if (!(username == null || username.isEmpty())) {
302 providerRepo.setUser(username);
303 }
304
305 if (!(password == null || password.isEmpty())) {
306 providerRepo.setPassword(password);
307 }
308
309 if (repository.getProviderRepository() instanceof ScmProviderRepositoryWithHost) {
310 ScmProviderRepositoryWithHost repo = (ScmProviderRepositoryWithHost) repository.getProviderRepository();
311
312 loadInfosFromSettings(repo);
313
314 if (!(username == null || username.isEmpty())) {
315 repo.setUser(username);
316 }
317
318 if (!(password == null || password.isEmpty())) {
319 repo.setPassword(password);
320 }
321
322 if (!(privateKey == null || privateKey.isEmpty())) {
323 repo.setPrivateKey(privateKey);
324 }
325
326 if (!(passphrase == null || passphrase.isEmpty())) {
327 repo.setPassphrase(passphrase);
328 }
329 }
330
331 if (!(tagBase == null || tagBase.isEmpty())
332 && repository.getProvider().equals("svn")) {
333 SvnScmProviderRepository svnRepo = (SvnScmProviderRepository) repository.getProviderRepository();
334
335 svnRepo.setTagBase(tagBase);
336 }
337 } catch (ScmRepositoryException e) {
338 if (!e.getValidationMessages().isEmpty()) {
339 for (String message : e.getValidationMessages()) {
340 getLog().error(message);
341 }
342 }
343
344 throw new ScmException("Can't load the scm provider.", e);
345 } catch (Exception e) {
346 throw new ScmException("Can't load the scm provider.", e);
347 }
348
349 return repository;
350 }
351
352
353
354
355
356
357 private void loadInfosFromSettings(ScmProviderRepositoryWithHost repo) {
358 if (username == null || password == null) {
359 String serverId = this.serverId;
360 if (serverId == null || serverId.isEmpty()) {
361
362 serverId = repo.getHost();
363 int port = repo.getPort();
364 if (port > 0) {
365 serverId += ":" + port;
366 }
367 }
368
369 Server server = this.settings.getServer(serverId);
370
371 if (server != null) {
372 server = decrypt(server);
373
374 if (username == null) {
375 username = server.getUsername();
376 }
377
378 if (password == null) {
379 password = server.getPassword();
380 }
381
382 if (privateKey == null) {
383 privateKey = server.getPrivateKey();
384 }
385
386 if (passphrase == null) {
387 passphrase = server.getPassphrase();
388 }
389 }
390 }
391 }
392
393 private Server decrypt(Server server) {
394 SettingsDecryptionResult result = settingsDecrypter.decrypt(new DefaultSettingsDecryptionRequest(server));
395 for (SettingsProblem problem : result.getProblems()) {
396 getLog().error(problem.getMessage(), problem.getException());
397 }
398
399 return result.getServer();
400 }
401
402 public void checkResult(ScmResult result) throws MojoExecutionException {
403 if (!result.isSuccess()) {
404 getLog().error("Provider message:");
405
406 getLog().error(result.getProviderMessage() == null ? "" : result.getProviderMessage());
407
408 getLog().error("Command output:");
409
410 getLog().error(result.getCommandOutput() == null ? "" : result.getCommandOutput());
411
412 throw new MojoExecutionException("Command failed: " + Objects.toString(result.getProviderMessage()));
413 }
414 }
415
416 public String getIncludes() {
417 return includes;
418 }
419
420 public void setIncludes(String includes) {
421 this.includes = includes;
422 }
423
424 public String getExcludes() {
425 return excludes;
426 }
427
428 public void setExcludes(String excludes) {
429 this.excludes = excludes;
430 }
431
432 public ScmVersion getScmVersion(String versionType, String version) throws MojoExecutionException {
433 if ((versionType == null || versionType.isEmpty()) && (version != null && !version.isEmpty())) {
434 throw new MojoExecutionException("You must specify the version type.");
435 }
436
437 if (version == null || version.isEmpty()) {
438 return null;
439 }
440
441 if (VERSION_TYPE_BRANCH.equals(versionType)) {
442 return new ScmBranch(version);
443 }
444
445 if (VERSION_TYPE_TAG.equals(versionType)) {
446 return new ScmTag(version);
447 }
448
449 if (VERSION_TYPE_REVISION.equals(versionType)) {
450 return new ScmRevision(version);
451 }
452
453 throw new MojoExecutionException("Unknown '" + versionType + "' version type.");
454 }
455
456 protected void handleExcludesIncludesAfterCheckoutAndExport(File checkoutDirectory) throws MojoExecutionException {
457 List<String> includes = new ArrayList<>();
458
459 if (!StringUtils.isBlank(this.getIncludes())) {
460 String[] tokens = StringUtils.split(this.getIncludes(), ",");
461 for (int i = 0; i < tokens.length; ++i) {
462 includes.add(tokens[i]);
463 }
464 }
465
466 List<String> excludes = new ArrayList<>();
467
468 if (!StringUtils.isBlank(this.getExcludes())) {
469 String[] tokens = StringUtils.split(this.getExcludes(), ",");
470 for (int i = 0; i < tokens.length; ++i) {
471 excludes.add(tokens[i]);
472 }
473 }
474
475 if (includes.isEmpty() && excludes.isEmpty()) {
476 return;
477 }
478
479 FileSetManager fileSetManager = new FileSetManager();
480
481 FileSet fileset = new FileSet();
482 fileset.setDirectory(checkoutDirectory.getAbsolutePath());
483 fileset.setIncludes(excludes);
484 fileset.setExcludes(includes);
485 fileset.setUseDefaultExcludes(false);
486
487 try {
488 fileSetManager.delete(fileset);
489 } catch (IOException e) {
490 throw new MojoExecutionException(
491 "Error found while cleaning up output directory base on " + "excludes/includes configurations.", e);
492 }
493 }
494 }