1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.install;
20
21 import java.io.File;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.io.Reader;
27 import java.io.Writer;
28 import java.nio.file.Files;
29 import java.util.Enumeration;
30 import java.util.jar.JarEntry;
31 import java.util.jar.JarFile;
32 import java.util.regex.Pattern;
33
34 import org.apache.maven.execution.MavenSession;
35 import org.apache.maven.model.Model;
36 import org.apache.maven.model.Parent;
37 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
38 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
39 import org.apache.maven.plugin.AbstractMojo;
40 import org.apache.maven.plugin.MojoExecutionException;
41 import org.apache.maven.plugin.MojoFailureException;
42 import org.apache.maven.plugins.annotations.Component;
43 import org.apache.maven.plugins.annotations.Mojo;
44 import org.apache.maven.plugins.annotations.Parameter;
45 import org.codehaus.plexus.util.FileUtils;
46 import org.codehaus.plexus.util.IOUtil;
47 import org.codehaus.plexus.util.StringUtils;
48 import org.codehaus.plexus.util.xml.XmlStreamReader;
49 import org.codehaus.plexus.util.xml.XmlStreamWriter;
50 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
51 import org.eclipse.aether.DefaultRepositoryCache;
52 import org.eclipse.aether.DefaultRepositorySystemSession;
53 import org.eclipse.aether.RepositorySystem;
54 import org.eclipse.aether.RepositorySystemSession;
55 import org.eclipse.aether.artifact.Artifact;
56 import org.eclipse.aether.artifact.ArtifactType;
57 import org.eclipse.aether.artifact.DefaultArtifact;
58 import org.eclipse.aether.installation.InstallRequest;
59 import org.eclipse.aether.installation.InstallationException;
60 import org.eclipse.aether.repository.LocalRepository;
61 import org.eclipse.aether.repository.LocalRepositoryManager;
62 import org.eclipse.aether.util.artifact.SubArtifact;
63
64
65
66
67
68
69 @Mojo(name = "install-file", requiresProject = false, aggregator = true, threadSafe = true)
70 public class InstallFileMojo extends AbstractMojo {
71 private static final String LS = System.getProperty("line.separator");
72
73 @Component
74 private RepositorySystem repositorySystem;
75
76 @Parameter(defaultValue = "${session}", required = true, readonly = true)
77 private MavenSession session;
78
79
80
81
82
83 @Parameter(property = "groupId")
84 private String groupId;
85
86
87
88
89
90 @Parameter(property = "artifactId")
91 private String artifactId;
92
93
94
95
96
97 @Parameter(property = "version")
98 private String version;
99
100
101
102
103
104 @Parameter(property = "packaging")
105 private String packaging;
106
107
108
109
110
111
112
113 @Parameter(property = "classifier")
114 private String classifier;
115
116
117
118
119 @Parameter(property = "file", required = true)
120 private File file;
121
122
123
124
125
126
127 @Parameter(property = "javadoc")
128 private File javadoc;
129
130
131
132
133
134
135 @Parameter(property = "sources")
136 private File sources;
137
138
139
140
141
142
143
144 @Parameter(property = "pomFile")
145 private File pomFile;
146
147
148
149
150
151
152
153 @Parameter(property = "generatePom")
154 private Boolean generatePom;
155
156
157
158
159
160
161
162 @Parameter(property = "localRepositoryPath")
163 private File localRepositoryPath;
164
165 @Override
166 public void execute() throws MojoExecutionException, MojoFailureException {
167 if (!file.exists()) {
168 String message = "The specified file '" + file.getPath() + "' does not exist";
169 getLog().error(message);
170 throw new MojoFailureException(message);
171 }
172
173 RepositorySystemSession repositorySystemSession = session.getRepositorySession();
174 if (localRepositoryPath != null) {
175
176 DefaultRepositorySystemSession newSession =
177 new DefaultRepositorySystemSession(session.getRepositorySession());
178
179 newSession.setCache(new DefaultRepositoryCache());
180
181 String contentType = newSession.getLocalRepository().getContentType();
182 if ("enhanced".equals(contentType)) {
183 contentType = "default";
184 }
185 LocalRepositoryManager localRepositoryManager = repositorySystem.newLocalRepositoryManager(
186 newSession, new LocalRepository(localRepositoryPath, contentType));
187 newSession.setLocalRepositoryManager(localRepositoryManager);
188 repositorySystemSession = newSession;
189 getLog().debug("localRepoPath: "
190 + localRepositoryManager.getRepository().getBasedir());
191 }
192
193 File temporaryPom = null;
194
195 if (pomFile != null) {
196 processModel(readModel(pomFile));
197 } else {
198 temporaryPom = readingPomFromJarFile();
199 if (!Boolean.TRUE.equals(generatePom)) {
200 pomFile = temporaryPom;
201 getLog().debug("Using JAR embedded POM as pomFile");
202 }
203 }
204
205 if (groupId == null || artifactId == null || version == null || packaging == null) {
206 throw new MojoExecutionException("The artifact information is incomplete: 'groupId', 'artifactId', "
207 + "'version' and 'packaging' are required.");
208 }
209
210 if (!isValidId(groupId) || !isValidId(artifactId) || !isValidVersion(version)) {
211 throw new MojoExecutionException("The artifact information is not valid: uses invalid characters.");
212 }
213
214 InstallRequest installRequest = new InstallRequest();
215
216 boolean isFilePom = classifier == null && "pom".equals(packaging);
217 if (!isFilePom) {
218 ArtifactType artifactType =
219 repositorySystemSession.getArtifactTypeRegistry().get(packaging);
220 if (artifactType != null
221 && StringUtils.isEmpty(classifier)
222 && !StringUtils.isEmpty(artifactType.getClassifier())) {
223 classifier = artifactType.getClassifier();
224 }
225 }
226 Artifact mainArtifact = new DefaultArtifact(
227 groupId, artifactId, classifier, isFilePom ? "pom" : getExtension(file), version)
228 .setFile(file);
229 installRequest.addArtifact(mainArtifact);
230
231 File artifactLocalFile = getLocalRepositoryFile(repositorySystemSession, mainArtifact);
232 File pomLocalFile = getPomLocalRepositoryFile(repositorySystemSession, mainArtifact);
233
234 if (file.equals(artifactLocalFile)) {
235 throw new MojoFailureException("Cannot install artifact. " + "Artifact is already in the local repository."
236 + LS + LS + "File in question is: " + file + LS);
237 }
238
239 if (!"pom".equals(packaging)) {
240 if (pomFile != null) {
241 installRequest.addArtifact(new SubArtifact(mainArtifact, "", "pom", pomFile));
242 } else {
243 if (Boolean.TRUE.equals(generatePom) || (generatePom == null && !pomLocalFile.exists())) {
244 temporaryPom = generatePomFile();
245 getLog().debug("Installing generated POM");
246 installRequest.addArtifact(new SubArtifact(mainArtifact, "", "pom", temporaryPom));
247 } else if (generatePom == null) {
248 getLog().debug("Skipping installation of generated POM, already present in local repository");
249 }
250 }
251 }
252
253 if (sources != null) {
254 installRequest.addArtifact(new SubArtifact(mainArtifact, "sources", "jar", sources));
255 }
256
257 if (javadoc != null) {
258 installRequest.addArtifact(new SubArtifact(mainArtifact, "javadoc", "jar", javadoc));
259 }
260
261 try {
262 repositorySystem.install(repositorySystemSession, installRequest);
263 } catch (InstallationException e) {
264 throw new MojoExecutionException(e.getMessage(), e);
265 } finally {
266 if (temporaryPom != null) {
267
268 temporaryPom.delete();
269 }
270 }
271 }
272
273 private File readingPomFromJarFile() throws MojoExecutionException {
274 File pomFile = null;
275
276 JarFile jarFile = null;
277 try {
278 Pattern pomEntry = Pattern.compile("META-INF/maven/.*/pom\\.xml");
279
280 jarFile = new JarFile(file);
281
282 Enumeration<JarEntry> jarEntries = jarFile.entries();
283
284 while (jarEntries.hasMoreElements()) {
285 JarEntry entry = jarEntries.nextElement();
286
287 if (pomEntry.matcher(entry.getName()).matches()) {
288 getLog().debug("Loading " + entry.getName());
289
290 InputStream pomInputStream = null;
291 OutputStream pomOutputStream = null;
292
293 try {
294 pomInputStream = jarFile.getInputStream(entry);
295
296 String base = file.getName();
297 if (base.indexOf('.') > 0) {
298 base = base.substring(0, base.lastIndexOf('.'));
299 }
300 pomFile = File.createTempFile(base, ".pom");
301
302 pomOutputStream = Files.newOutputStream(pomFile.toPath());
303
304 IOUtil.copy(pomInputStream, pomOutputStream);
305
306 pomOutputStream.close();
307 pomOutputStream = null;
308
309 pomInputStream.close();
310 pomInputStream = null;
311
312 processModel(readModel(pomFile));
313
314 break;
315 } finally {
316 IOUtil.close(pomInputStream);
317 IOUtil.close(pomOutputStream);
318 }
319 }
320 }
321
322 if (pomFile == null) {
323 getLog().info("pom.xml not found in " + file.getName());
324 }
325 } catch (IOException e) {
326
327 } finally {
328 if (jarFile != null) {
329 try {
330 jarFile.close();
331 } catch (IOException e) {
332
333 }
334 }
335 }
336 return pomFile;
337 }
338
339
340
341
342
343
344
345
346 private Model readModel(File pomFile) throws MojoExecutionException {
347 Reader reader = null;
348 try {
349 reader = new XmlStreamReader(pomFile);
350 final Model model = new MavenXpp3Reader().read(reader);
351 reader.close();
352 reader = null;
353 return model;
354 } catch (FileNotFoundException e) {
355 throw new MojoExecutionException("File not found " + pomFile, e);
356 } catch (IOException e) {
357 throw new MojoExecutionException("Error reading POM " + pomFile, e);
358 } catch (XmlPullParserException e) {
359 throw new MojoExecutionException("Error parsing POM " + pomFile, e);
360 } finally {
361 IOUtil.close(reader);
362 }
363 }
364
365
366
367
368
369
370 private void processModel(Model model) {
371 Parent parent = model.getParent();
372
373 if (this.groupId == null) {
374 this.groupId = model.getGroupId();
375 if (this.groupId == null && parent != null) {
376 this.groupId = parent.getGroupId();
377 }
378 }
379 if (this.artifactId == null) {
380 this.artifactId = model.getArtifactId();
381 }
382 if (this.version == null) {
383 this.version = model.getVersion();
384 if (this.version == null && parent != null) {
385 this.version = parent.getVersion();
386 }
387 }
388 if (this.packaging == null) {
389 this.packaging = model.getPackaging();
390 }
391 }
392
393
394
395
396
397
398 private Model generateModel() {
399 Model model = new Model();
400
401 model.setModelVersion("4.0.0");
402
403 model.setGroupId(groupId);
404 model.setArtifactId(artifactId);
405 model.setVersion(version);
406 model.setPackaging(packaging);
407
408 model.setDescription("POM was created from install:install-file");
409
410 return model;
411 }
412
413
414
415
416
417
418
419
420 private File generatePomFile() throws MojoExecutionException {
421 Model model = generateModel();
422
423 Writer writer = null;
424 try {
425 File pomFile = File.createTempFile("mvninstall", ".pom");
426
427 writer = new XmlStreamWriter(pomFile);
428 new MavenXpp3Writer().write(writer, model);
429 writer.close();
430 writer = null;
431
432 return pomFile;
433 } catch (IOException e) {
434 throw new MojoExecutionException("Error writing temporary POM file: " + e.getMessage(), e);
435 } finally {
436 IOUtil.close(writer);
437 }
438 }
439
440
441
442
443
444 private File getLocalRepositoryFile(RepositorySystemSession session, Artifact artifact) {
445 String path = session.getLocalRepositoryManager().getPathForLocalArtifact(artifact);
446 return new File(session.getLocalRepository().getBasedir(), path);
447 }
448
449
450
451
452
453 private File getPomLocalRepositoryFile(RepositorySystemSession session, Artifact artifact) {
454 SubArtifact pomArtifact = new SubArtifact(artifact, "", "pom");
455 String path = session.getLocalRepositoryManager().getPathForLocalArtifact(pomArtifact);
456 return new File(session.getLocalRepository().getBasedir(), path);
457 }
458
459
460
461
462
463
464 private String getExtension(final File file) {
465 String filename = file.getName();
466 if (filename.contains(".tar.")) {
467 return "tar." + FileUtils.getExtension(filename);
468 } else {
469 return FileUtils.getExtension(filename);
470 }
471 }
472
473
474
475
476 private boolean isValidId(String id) {
477 if (id == null) {
478 return false;
479 }
480 for (int i = 0; i < id.length(); i++) {
481 char c = id.charAt(i);
482 if (!(c >= 'a' && c <= 'z'
483 || c >= 'A' && c <= 'Z'
484 || c >= '0' && c <= '9'
485 || c == '-'
486 || c == '_'
487 || c == '.')) {
488 return false;
489 }
490 }
491 return true;
492 }
493
494 private static final String ILLEGAL_VERSION_CHARS = "\\/:\"<>|?*[](){},";
495
496
497
498
499 private boolean isValidVersion(String version) {
500 if (version == null) {
501 return false;
502 }
503 for (int i = version.length() - 1; i >= 0; i--) {
504 if (ILLEGAL_VERSION_CHARS.indexOf(version.charAt(i)) >= 0) {
505 return false;
506 }
507 }
508 return true;
509 }
510 }