1 | |
package org.apache.maven.plugin.idea; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
import org.apache.maven.artifact.Artifact; |
23 | |
import org.apache.maven.artifact.factory.ArtifactFactory; |
24 | |
import org.apache.maven.artifact.metadata.ArtifactMetadataSource; |
25 | |
import org.apache.maven.artifact.repository.ArtifactRepository; |
26 | |
import org.apache.maven.artifact.resolver.ArtifactNotFoundException; |
27 | |
import org.apache.maven.artifact.resolver.ArtifactResolutionException; |
28 | |
import org.apache.maven.artifact.resolver.ArtifactResolutionResult; |
29 | |
import org.apache.maven.artifact.resolver.ArtifactResolver; |
30 | |
import org.apache.maven.artifact.resolver.filter.ArtifactFilter; |
31 | |
import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; |
32 | |
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; |
33 | |
import org.apache.maven.artifact.versioning.VersionRange; |
34 | |
import org.apache.maven.model.Dependency; |
35 | |
import org.apache.maven.model.DependencyManagement; |
36 | |
import org.apache.maven.model.Exclusion; |
37 | |
import org.apache.maven.model.Plugin; |
38 | |
import org.apache.maven.plugin.AbstractMojo; |
39 | |
import org.apache.maven.plugin.logging.Log; |
40 | |
import org.apache.maven.project.MavenProject; |
41 | |
import org.apache.maven.project.ProjectBuildingException; |
42 | |
import org.apache.maven.project.artifact.InvalidDependencyVersionException; |
43 | |
import org.codehaus.plexus.util.StringUtils; |
44 | |
import org.codehaus.plexus.util.xml.Xpp3Dom; |
45 | |
import org.dom4j.Document; |
46 | |
import org.dom4j.DocumentException; |
47 | |
import org.dom4j.Element; |
48 | |
import org.dom4j.io.SAXReader; |
49 | |
import org.dom4j.io.XMLWriter; |
50 | |
|
51 | |
import java.io.File; |
52 | |
import java.io.IOException; |
53 | |
import java.util.ArrayList; |
54 | |
import java.util.Collections; |
55 | |
import java.util.HashMap; |
56 | |
import java.util.HashSet; |
57 | |
import java.util.Iterator; |
58 | |
import java.util.List; |
59 | |
import java.util.Map; |
60 | |
import java.util.Set; |
61 | |
import java.util.StringTokenizer; |
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | 114 | public abstract class AbstractIdeaMojo |
67 | |
extends AbstractMojo |
68 | |
{ |
69 | |
|
70 | |
|
71 | |
|
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
protected MavenProject executedProject; |
77 | |
|
78 | |
|
79 | |
protected Log log; |
80 | |
|
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
protected boolean overwrite; |
87 | |
|
88 | |
|
89 | |
|
90 | |
|
91 | |
protected ArtifactFactory artifactFactory; |
92 | |
|
93 | |
|
94 | |
|
95 | |
|
96 | |
|
97 | |
|
98 | |
protected ArtifactRepository localRepo; |
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
protected ArtifactResolver artifactResolver; |
104 | |
|
105 | |
|
106 | |
|
107 | |
|
108 | |
protected ArtifactMetadataSource artifactMetadataSource; |
109 | |
|
110 | |
public void initParam( MavenProject project, ArtifactFactory artifactFactory, ArtifactRepository localRepo, |
111 | |
ArtifactResolver artifactResolver, ArtifactMetadataSource artifactMetadataSource, Log log, |
112 | |
boolean overwrite ) |
113 | |
{ |
114 | 18 | this.executedProject = project; |
115 | |
|
116 | 18 | this.log = log; |
117 | |
|
118 | 18 | this.artifactFactory = artifactFactory; |
119 | |
|
120 | 18 | this.localRepo = localRepo; |
121 | |
|
122 | 18 | this.artifactResolver = artifactResolver; |
123 | |
|
124 | 18 | this.artifactMetadataSource = artifactMetadataSource; |
125 | |
|
126 | 18 | this.overwrite = overwrite; |
127 | 18 | } |
128 | |
|
129 | |
protected Document readXmlDocument( File file, String altFilename ) |
130 | |
throws DocumentException |
131 | |
{ |
132 | 105 | SAXReader reader = new SAXReader(); |
133 | 105 | if ( file.exists() && !overwrite ) |
134 | |
{ |
135 | 105 | return reader.read( file ); |
136 | |
} |
137 | |
else |
138 | |
{ |
139 | 0 | File altFile = new File( executedProject.getBasedir(), "src/main/idea/" + altFilename ); |
140 | 0 | if ( altFile.exists() ) |
141 | |
{ |
142 | 0 | return reader.read( altFile ); |
143 | |
} |
144 | |
else |
145 | |
{ |
146 | 0 | return reader.read( getClass().getResourceAsStream( "/templates/default/" + altFilename ) ); |
147 | |
} |
148 | |
} |
149 | |
} |
150 | |
|
151 | |
protected void writeXmlDocument( File file, Document document ) |
152 | |
throws IOException |
153 | |
{ |
154 | 105 | XMLWriter writer = new IdeaXmlWriter( file ); |
155 | 105 | writer.write( document ); |
156 | 105 | writer.close(); |
157 | 105 | } |
158 | |
|
159 | |
|
160 | |
|
161 | |
|
162 | |
|
163 | |
|
164 | |
|
165 | |
|
166 | |
protected Element findComponent( Element module, String name ) |
167 | |
{ |
168 | 183 | return findElement( module, "component", name ); |
169 | |
} |
170 | |
|
171 | |
protected Element findElement( Element element, String elementName, String attributeName ) |
172 | |
{ |
173 | 228 | for ( Iterator children = element.elementIterator( elementName ); children.hasNext(); ) |
174 | |
{ |
175 | 1155 | Element child = (Element) children.next(); |
176 | 1155 | if ( attributeName.equals( child.attributeValue( "name" ) ) ) |
177 | |
{ |
178 | 228 | return child; |
179 | |
} |
180 | |
} |
181 | 0 | return createElement( element, elementName ).addAttribute( "name", attributeName ); |
182 | |
} |
183 | |
|
184 | |
protected Element findElement( Element component, String name ) |
185 | |
{ |
186 | 213 | Element element = component.element( name ); |
187 | 213 | if ( element == null ) |
188 | |
{ |
189 | 0 | element = createElement( component, name ); |
190 | |
} |
191 | 213 | return element; |
192 | |
} |
193 | |
|
194 | |
|
195 | |
|
196 | |
|
197 | |
|
198 | |
|
199 | |
|
200 | |
|
201 | |
protected Element createElement( Element module, String name ) |
202 | |
{ |
203 | 663 | return module.addElement( name ); |
204 | |
} |
205 | |
|
206 | |
|
207 | |
|
208 | |
|
209 | |
|
210 | |
|
211 | |
|
212 | |
|
213 | |
protected String toRelative( String basedir, String absolutePath ) |
214 | |
{ |
215 | |
String relative; |
216 | |
|
217 | |
|
218 | 492 | String convertedBasedir = convertDriveLetter( basedir ); |
219 | 492 | String convertedAbsolutePath = convertDriveLetter( absolutePath ); |
220 | |
|
221 | |
|
222 | 492 | convertedBasedir = StringUtils.replace( convertedBasedir, "\\", "/" ); |
223 | 492 | convertedAbsolutePath = StringUtils.replace( convertedAbsolutePath, "\\", "/" ); |
224 | |
|
225 | |
|
226 | 492 | if ( convertedBasedir.endsWith( "/" ) ) |
227 | |
{ |
228 | 15 | convertedBasedir = convertedBasedir.substring( 0, convertedBasedir.length() - 1 ); |
229 | |
} |
230 | 492 | if ( convertedAbsolutePath.endsWith( "/" ) ) |
231 | |
{ |
232 | 6 | convertedAbsolutePath = convertedAbsolutePath.substring( 0, convertedAbsolutePath.length() - 1 ); |
233 | |
} |
234 | |
|
235 | |
|
236 | 492 | String matchableBasedir = convertedBasedir + "/"; |
237 | 492 | if ( convertedAbsolutePath.startsWith( matchableBasedir ) |
238 | |
&& convertedAbsolutePath.length() > matchableBasedir.length() ) |
239 | |
{ |
240 | |
|
241 | 438 | relative = convertedAbsolutePath.substring( matchableBasedir.length() ); |
242 | |
} |
243 | |
else |
244 | |
{ |
245 | |
|
246 | 54 | StringTokenizer baseTokens = new StringTokenizer( convertedBasedir, "/", false ); |
247 | |
|
248 | 54 | int baseCount = baseTokens.countTokens(); |
249 | 54 | List baseTokenList = new ArrayList( baseCount ); |
250 | 462 | while ( baseTokens.hasMoreTokens() ) |
251 | |
{ |
252 | 408 | baseTokenList.add( baseTokens.nextToken() ); |
253 | |
} |
254 | |
|
255 | 54 | StringTokenizer pathTokens = new StringTokenizer( convertedAbsolutePath, "/", false ); |
256 | |
|
257 | 54 | int pathCount = pathTokens.countTokens(); |
258 | 54 | List pathTokenList = new ArrayList( pathCount ); |
259 | 258 | while ( pathTokens.hasMoreTokens() ) |
260 | |
{ |
261 | 204 | pathTokenList.add( pathTokens.nextToken() ); |
262 | |
} |
263 | |
|
264 | 54 | int maxCount = Math.max( baseTokenList.size(), pathTokenList.size() ); |
265 | 54 | int differIndex = -1; |
266 | 84 | for ( int i = 0; i < maxCount; i++ ) |
267 | |
{ |
268 | 84 | if ( i >= pathTokenList.size() || i >= baseTokenList.size() ) |
269 | |
{ |
270 | 0 | differIndex = i; |
271 | 0 | break; |
272 | |
} |
273 | 84 | String basePart = (String) baseTokenList.get( i ); |
274 | 84 | String pathPart = (String) pathTokenList.get( i ); |
275 | 84 | if ( !basePart.equals( pathPart ) ) |
276 | |
{ |
277 | 54 | differIndex = i; |
278 | 54 | break; |
279 | |
} |
280 | |
} |
281 | 54 | if ( getLog().isDebugEnabled() ) |
282 | |
{ |
283 | 0 | getLog().debug( "Construction of relative path... differIndex=" + differIndex ); |
284 | |
} |
285 | 54 | if ( differIndex < 1 ) |
286 | |
{ |
287 | |
|
288 | 36 | relative = convertedAbsolutePath; |
289 | |
} |
290 | |
else |
291 | |
{ |
292 | 18 | StringBuffer result = new StringBuffer(); |
293 | 18 | int parentCount = baseTokenList.size() - differIndex; |
294 | 18 | if ( getLog().isDebugEnabled() ) |
295 | |
{ |
296 | 0 | getLog().debug( "parentCount=" + parentCount ); |
297 | |
} |
298 | 18 | boolean isFirst = true; |
299 | 36 | for ( int i = 0; i < parentCount; i++ ) |
300 | |
{ |
301 | |
|
302 | 18 | if ( isFirst ) |
303 | |
{ |
304 | 18 | isFirst = false; |
305 | |
} |
306 | |
else |
307 | |
{ |
308 | 0 | result.append( "/" ); |
309 | |
} |
310 | 18 | result.append( ".." ); |
311 | |
} |
312 | 42 | for ( int i = differIndex; i < pathTokenList.size(); i++ ) |
313 | |
{ |
314 | |
|
315 | 24 | if ( isFirst ) |
316 | |
{ |
317 | 0 | isFirst = false; |
318 | |
} |
319 | |
else |
320 | |
{ |
321 | 24 | result.append( "/" ); |
322 | |
} |
323 | 24 | result.append( pathTokenList.get( i ) ); |
324 | |
} |
325 | 18 | relative = result.toString(); |
326 | |
} |
327 | |
} |
328 | |
|
329 | 492 | if ( getLog().isDebugEnabled() ) |
330 | |
{ |
331 | 0 | getLog().debug( "toRelative(" + basedir + ", " + absolutePath + ") => " + relative ); |
332 | |
} |
333 | |
|
334 | 492 | return relative; |
335 | |
} |
336 | |
|
337 | |
|
338 | |
|
339 | |
|
340 | |
|
341 | |
|
342 | |
|
343 | |
|
344 | |
String convertDriveLetter( String absolutePath ) |
345 | |
{ |
346 | 1230 | if ( absolutePath != null && absolutePath.length() >= 3 && !absolutePath.startsWith( "/" ) ) |
347 | |
{ |
348 | |
|
349 | 1218 | if ( Character.isLetter( absolutePath.substring( 0, 1 ).charAt( 0 ) ) |
350 | |
&& absolutePath.substring( 1, 3 ).equals( ":\\" ) ) |
351 | |
{ |
352 | |
|
353 | 1164 | return absolutePath.substring( 0, 1 ).toUpperCase() + absolutePath.substring( 1 ); |
354 | |
} |
355 | |
} |
356 | 66 | return absolutePath; |
357 | |
} |
358 | |
|
359 | |
|
360 | |
|
361 | |
|
362 | |
|
363 | |
|
364 | |
|
365 | |
protected void removeOldElements( Element content, String name ) |
366 | |
{ |
367 | 291 | for ( Iterator children = content.elementIterator(); children.hasNext(); ) |
368 | |
{ |
369 | 618 | Element child = (Element) children.next(); |
370 | 618 | if ( name.equals( child.getName() ) ) |
371 | |
{ |
372 | 390 | content.remove( child ); |
373 | |
} |
374 | |
} |
375 | 291 | } |
376 | |
|
377 | |
protected void doDependencyResolution( MavenProject project, ArtifactRepository localRepo ) |
378 | |
throws InvalidDependencyVersionException, ProjectBuildingException, InvalidVersionSpecificationException |
379 | |
{ |
380 | 93 | Map managedVersions = |
381 | |
createManagedVersionMap( artifactFactory, project.getId(), project.getDependencyManagement() ); |
382 | |
|
383 | |
try |
384 | |
{ |
385 | 93 | ArtifactResolutionResult result = artifactResolver.resolveTransitively( getProjectArtifacts(), |
386 | |
project.getArtifact(), |
387 | |
managedVersions, localRepo, |
388 | |
project.getRemoteArtifactRepositories(), |
389 | |
artifactMetadataSource ); |
390 | |
|
391 | 87 | project.setArtifacts( result.getArtifacts() ); |
392 | |
} |
393 | 0 | catch ( ArtifactNotFoundException e ) |
394 | |
{ |
395 | 0 | getLog().debug( e.getMessage(), e ); |
396 | |
|
397 | 0 | StringBuffer msg = new StringBuffer(); |
398 | 0 | msg.append( "An error occurred during dependency resolution.\n\n" ); |
399 | 0 | msg.append( " Failed to retrieve " + e.getDownloadUrl() + "\n" ); |
400 | 0 | msg.append( "from the following repositories:" ); |
401 | 0 | for ( Iterator repositories = e.getRemoteRepositories().iterator(); repositories.hasNext(); ) |
402 | |
{ |
403 | 0 | ArtifactRepository repository = (ArtifactRepository) repositories.next(); |
404 | 0 | msg.append( "\n " + repository.getId() + "(" + repository.getUrl() + ")" ); |
405 | |
} |
406 | 0 | msg.append( "\nCaused by: " + e.getMessage() ); |
407 | |
|
408 | 0 | getLog().warn( msg ); |
409 | |
} |
410 | 6 | catch ( ArtifactResolutionException e ) |
411 | |
{ |
412 | 6 | getLog().debug( e.getMessage(), e ); |
413 | |
|
414 | 6 | StringBuffer msg = new StringBuffer(); |
415 | 6 | msg.append( "An error occurred during dependency resolution of the following artifact:\n\n" ); |
416 | 6 | msg.append( " " + e.getGroupId() + ":" + e.getArtifactId() + e.getVersion() + "\n\n" ); |
417 | 6 | msg.append( "Caused by: " + e.getMessage() ); |
418 | |
|
419 | 6 | getLog().warn( msg ); |
420 | 87 | } |
421 | 93 | } |
422 | |
|
423 | |
|
424 | |
|
425 | |
|
426 | |
protected String getPluginSetting( String artifactId, String optionName, String defaultValue ) |
427 | |
{ |
428 | 21 | for ( Iterator it = executedProject.getBuildPlugins().iterator(); it.hasNext(); ) |
429 | |
{ |
430 | 0 | Plugin plugin = (Plugin) it.next(); |
431 | 0 | if ( plugin.getArtifactId().equals( artifactId ) ) |
432 | |
{ |
433 | 0 | Xpp3Dom o = (Xpp3Dom) plugin.getConfiguration(); |
434 | 0 | if ( o != null && o.getChild( optionName ) != null ) |
435 | |
{ |
436 | 0 | return o.getChild( optionName ).getValue(); |
437 | |
} |
438 | |
} |
439 | |
} |
440 | 21 | return defaultValue; |
441 | |
} |
442 | |
|
443 | |
private Set getProjectArtifacts() |
444 | |
throws InvalidVersionSpecificationException |
445 | |
{ |
446 | 93 | Set artifacts = new HashSet(); |
447 | |
|
448 | 93 | for ( Iterator dependencies = executedProject.getDependencies().iterator(); dependencies.hasNext(); ) |
449 | |
{ |
450 | 189 | Dependency dep = (Dependency) dependencies.next(); |
451 | |
|
452 | 189 | String groupId = dep.getGroupId(); |
453 | 189 | String artifactId = dep.getArtifactId(); |
454 | 189 | VersionRange versionRange = VersionRange.createFromVersionSpec( dep.getVersion() ); |
455 | 189 | String type = dep.getType(); |
456 | 189 | if ( type == null ) |
457 | |
{ |
458 | 0 | type = "jar"; |
459 | |
} |
460 | 189 | String classifier = dep.getClassifier(); |
461 | 189 | boolean optional = dep.isOptional(); |
462 | 189 | String scope = dep.getScope(); |
463 | 189 | if ( scope == null ) |
464 | |
{ |
465 | 0 | scope = Artifact.SCOPE_COMPILE; |
466 | |
} |
467 | |
|
468 | 189 | Artifact artifact = artifactFactory.createDependencyArtifact( groupId, artifactId, versionRange, type, |
469 | |
classifier, scope, optional ); |
470 | |
|
471 | 189 | if ( scope.equalsIgnoreCase( Artifact.SCOPE_SYSTEM ) ) |
472 | |
{ |
473 | 6 | artifact.setFile( new File( dep.getSystemPath() ) ); |
474 | |
} |
475 | |
|
476 | 189 | List exclusions = new ArrayList(); |
477 | 189 | for ( Iterator j = dep.getExclusions().iterator(); j.hasNext(); ) |
478 | |
{ |
479 | 0 | Exclusion e = (Exclusion) j.next(); |
480 | 0 | exclusions.add( e.getGroupId() + ":" + e.getArtifactId() ); |
481 | |
} |
482 | |
|
483 | 189 | ArtifactFilter newFilter = new ExcludesArtifactFilter( exclusions ); |
484 | |
|
485 | 189 | artifact.setDependencyFilter( newFilter ); |
486 | |
|
487 | 189 | artifacts.add( artifact ); |
488 | |
} |
489 | |
|
490 | 93 | return artifacts; |
491 | |
} |
492 | |
|
493 | |
private Map createManagedVersionMap( ArtifactFactory artifactFactory, String projectId, |
494 | |
DependencyManagement dependencyManagement ) |
495 | |
throws ProjectBuildingException |
496 | |
{ |
497 | |
Map map; |
498 | 93 | if ( dependencyManagement != null && dependencyManagement.getDependencies() != null ) |
499 | |
{ |
500 | 0 | map = new HashMap(); |
501 | 0 | for ( Iterator i = dependencyManagement.getDependencies().iterator(); i.hasNext(); ) |
502 | |
{ |
503 | 0 | Dependency d = (Dependency) i.next(); |
504 | |
|
505 | |
try |
506 | |
{ |
507 | 0 | VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() ); |
508 | 0 | Artifact artifact = artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), |
509 | |
versionRange, d.getType(), |
510 | |
d.getClassifier(), d.getScope(), |
511 | |
d.isOptional() ); |
512 | 0 | map.put( d.getManagementKey(), artifact ); |
513 | |
} |
514 | 0 | catch ( InvalidVersionSpecificationException e ) |
515 | |
{ |
516 | 0 | throw new ProjectBuildingException( projectId, "Unable to parse version '" + d.getVersion() |
517 | |
+ "' for dependency '" + d.getManagementKey() + "': " + e.getMessage(), e ); |
518 | 0 | } |
519 | |
} |
520 | |
} |
521 | |
else |
522 | |
{ |
523 | 93 | map = Collections.EMPTY_MAP; |
524 | |
} |
525 | 93 | return map; |
526 | |
} |
527 | |
|
528 | |
public Log getLog() |
529 | |
{ |
530 | 633 | if ( log == null ) |
531 | |
{ |
532 | 69 | log = super.getLog(); |
533 | |
} |
534 | |
|
535 | 633 | return log; |
536 | |
} |
537 | |
} |