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 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 this.executedProject = project;
115
116 this.log = log;
117
118 this.artifactFactory = artifactFactory;
119
120 this.localRepo = localRepo;
121
122 this.artifactResolver = artifactResolver;
123
124 this.artifactMetadataSource = artifactMetadataSource;
125
126 this.overwrite = overwrite;
127 }
128
129 protected Document readXmlDocument( File file, String altFilename )
130 throws DocumentException
131 {
132 SAXReader reader = new SAXReader();
133 if ( file.exists() && !overwrite )
134 {
135 return reader.read( file );
136 }
137 else
138 {
139 File altFile = new File( executedProject.getBasedir(), "src/main/idea/" + altFilename );
140 if ( altFile.exists() )
141 {
142 return reader.read( altFile );
143 }
144 else
145 {
146 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 XMLWriter writer = new IdeaXmlWriter( file );
155 writer.write( document );
156 writer.close();
157 }
158
159
160
161
162
163
164
165
166 protected Element findComponent( Element module, String name )
167 {
168 return findElement( module, "component", name );
169 }
170
171 protected Element findElement( Element element, String elementName, String attributeName )
172 {
173 for ( Iterator children = element.elementIterator( elementName ); children.hasNext(); )
174 {
175 Element child = (Element) children.next();
176 if ( attributeName.equals( child.attributeValue( "name" ) ) )
177 {
178 return child;
179 }
180 }
181 return createElement( element, elementName ).addAttribute( "name", attributeName );
182 }
183
184 protected Element findElement( Element component, String name )
185 {
186 Element element = component.element( name );
187 if ( element == null )
188 {
189 element = createElement( component, name );
190 }
191 return element;
192 }
193
194
195
196
197
198
199
200
201 protected Element createElement( Element module, String name )
202 {
203 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 String convertedBasedir = convertDriveLetter( basedir );
219 String convertedAbsolutePath = convertDriveLetter( absolutePath );
220
221
222 convertedBasedir = StringUtils.replace( convertedBasedir, "\\", "/" );
223 convertedAbsolutePath = StringUtils.replace( convertedAbsolutePath, "\\", "/" );
224
225
226 if ( convertedBasedir.endsWith( "/" ) )
227 {
228 convertedBasedir = convertedBasedir.substring( 0, convertedBasedir.length() - 1 );
229 }
230 if ( convertedAbsolutePath.endsWith( "/" ) )
231 {
232 convertedAbsolutePath = convertedAbsolutePath.substring( 0, convertedAbsolutePath.length() - 1 );
233 }
234
235
236 String matchableBasedir = convertedBasedir + "/";
237 if ( convertedAbsolutePath.startsWith( matchableBasedir )
238 && convertedAbsolutePath.length() > matchableBasedir.length() )
239 {
240
241 relative = convertedAbsolutePath.substring( matchableBasedir.length() );
242 }
243 else
244 {
245
246 StringTokenizer baseTokens = new StringTokenizer( convertedBasedir, "/", false );
247
248 int baseCount = baseTokens.countTokens();
249 List baseTokenList = new ArrayList( baseCount );
250 while ( baseTokens.hasMoreTokens() )
251 {
252 baseTokenList.add( baseTokens.nextToken() );
253 }
254
255 StringTokenizer pathTokens = new StringTokenizer( convertedAbsolutePath, "/", false );
256
257 int pathCount = pathTokens.countTokens();
258 List pathTokenList = new ArrayList( pathCount );
259 while ( pathTokens.hasMoreTokens() )
260 {
261 pathTokenList.add( pathTokens.nextToken() );
262 }
263
264 int maxCount = Math.max( baseTokenList.size(), pathTokenList.size() );
265 int differIndex = -1;
266 for ( int i = 0; i < maxCount; i++ )
267 {
268 if ( i >= pathTokenList.size() || i >= baseTokenList.size() )
269 {
270 differIndex = i;
271 break;
272 }
273 String basePart = (String) baseTokenList.get( i );
274 String pathPart = (String) pathTokenList.get( i );
275 if ( !basePart.equals( pathPart ) )
276 {
277 differIndex = i;
278 break;
279 }
280 }
281 if ( getLog().isDebugEnabled() )
282 {
283 getLog().debug( "Construction of relative path... differIndex=" + differIndex );
284 }
285 if ( differIndex < 1 )
286 {
287
288 relative = convertedAbsolutePath;
289 }
290 else
291 {
292 StringBuilder result = new StringBuilder();
293 int parentCount = baseTokenList.size() - differIndex;
294 if ( getLog().isDebugEnabled() )
295 {
296 getLog().debug( "parentCount=" + parentCount );
297 }
298 boolean isFirst = true;
299 for ( int i = 0; i < parentCount; i++ )
300 {
301
302 if ( isFirst )
303 {
304 isFirst = false;
305 }
306 else
307 {
308 result.append( "/" );
309 }
310 result.append( ".." );
311 }
312 for ( int i = differIndex; i < pathTokenList.size(); i++ )
313 {
314
315 if ( isFirst )
316 {
317 isFirst = false;
318 }
319 else
320 {
321 result.append( "/" );
322 }
323 result.append( pathTokenList.get( i ) );
324 }
325 relative = result.toString();
326 }
327 }
328
329 if ( getLog().isDebugEnabled() )
330 {
331 getLog().debug( "toRelative(" + basedir + ", " + absolutePath + ") => " + relative );
332 }
333
334 return relative;
335 }
336
337
338
339
340
341
342
343
344 String convertDriveLetter( String absolutePath )
345 {
346 if ( absolutePath != null && absolutePath.length() >= 3 && !absolutePath.startsWith( "/" ) )
347 {
348
349 if ( Character.isLetter( absolutePath.substring( 0, 1 ).charAt( 0 ) )
350 && absolutePath.substring( 1, 3 ).equals( ":\\" ) )
351 {
352
353 return absolutePath.substring( 0, 1 ).toUpperCase() + absolutePath.substring( 1 );
354 }
355 }
356 return absolutePath;
357 }
358
359
360
361
362
363
364
365 protected void removeOldElements( Element content, String name )
366 {
367 for ( Iterator children = content.elementIterator(); children.hasNext(); )
368 {
369 Element child = (Element) children.next();
370 if ( name.equals( child.getName() ) )
371 {
372 content.remove( child );
373 }
374 }
375 }
376
377 protected void doDependencyResolution( MavenProject project, ArtifactRepository localRepo )
378 throws InvalidDependencyVersionException, ProjectBuildingException, InvalidVersionSpecificationException
379 {
380 Map managedVersions =
381 createManagedVersionMap( artifactFactory, project.getId(), project.getDependencyManagement() );
382
383 try
384 {
385 ArtifactResolutionResult result = artifactResolver.resolveTransitively( getProjectArtifacts(),
386 project.getArtifact(),
387 managedVersions, localRepo,
388 project.getRemoteArtifactRepositories(),
389 artifactMetadataSource );
390
391 project.setArtifacts( result.getArtifacts() );
392 }
393 catch ( ArtifactNotFoundException e )
394 {
395 getLog().debug( e.getMessage(), e );
396
397 StringBuilder msg = new StringBuilder();
398 msg.append( "An error occurred during dependency resolution.\n\n" );
399 msg.append( " Failed to retrieve " + e.getDownloadUrl() + "\n" );
400 msg.append( "from the following repositories:" );
401 for ( Iterator repositories = e.getRemoteRepositories().iterator(); repositories.hasNext(); )
402 {
403 ArtifactRepository repository = (ArtifactRepository) repositories.next();
404 msg.append( "\n " + repository.getId() + "(" + repository.getUrl() + ")" );
405 }
406 msg.append( "\nCaused by: " + e.getMessage() );
407
408 getLog().warn( msg );
409 }
410 catch ( ArtifactResolutionException e )
411 {
412 getLog().debug( e.getMessage(), e );
413
414 StringBuilder msg = new StringBuilder();
415 msg.append( "An error occurred during dependency resolution of the following artifact:\n\n" );
416 msg.append( " " + e.getGroupId() + ":" + e.getArtifactId() + e.getVersion() + "\n\n" );
417 msg.append( "Caused by: " + e.getMessage() );
418
419 getLog().warn( msg );
420 }
421 }
422
423
424
425
426 protected String getPluginSetting( String artifactId, String optionName, String defaultValue )
427 {
428 for ( Iterator it = executedProject.getBuildPlugins().iterator(); it.hasNext(); )
429 {
430 Plugin plugin = (Plugin) it.next();
431 if ( plugin.getArtifactId().equals( artifactId ) )
432 {
433 Xpp3Dom o = (Xpp3Dom) plugin.getConfiguration();
434 if ( o != null && o.getChild( optionName ) != null )
435 {
436 return o.getChild( optionName ).getValue();
437 }
438 }
439 }
440 return defaultValue;
441 }
442
443 private Set getProjectArtifacts()
444 throws InvalidVersionSpecificationException
445 {
446 Set artifacts = new HashSet();
447
448 for ( Iterator dependencies = executedProject.getDependencies().iterator(); dependencies.hasNext(); )
449 {
450 Dependency dep = (Dependency) dependencies.next();
451
452 String groupId = dep.getGroupId();
453 String artifactId = dep.getArtifactId();
454 VersionRange versionRange = VersionRange.createFromVersionSpec( dep.getVersion() );
455 String type = dep.getType();
456 if ( type == null )
457 {
458 type = "jar";
459 }
460 String classifier = dep.getClassifier();
461 boolean optional = dep.isOptional();
462 String scope = dep.getScope();
463 if ( scope == null )
464 {
465 scope = Artifact.SCOPE_COMPILE;
466 }
467
468 Artifact artifact = artifactFactory.createDependencyArtifact( groupId, artifactId, versionRange, type,
469 classifier, scope, optional );
470
471 if ( scope.equalsIgnoreCase( Artifact.SCOPE_SYSTEM ) )
472 {
473 artifact.setFile( new File( dep.getSystemPath() ) );
474 }
475
476 List exclusions = new ArrayList();
477 for ( Iterator j = dep.getExclusions().iterator(); j.hasNext(); )
478 {
479 Exclusion e = (Exclusion) j.next();
480 exclusions.add( e.getGroupId() + ":" + e.getArtifactId() );
481 }
482
483 ArtifactFilter newFilter = new ExcludesArtifactFilter( exclusions );
484
485 artifact.setDependencyFilter( newFilter );
486
487 artifacts.add( artifact );
488 }
489
490 return artifacts;
491 }
492
493 private Map createManagedVersionMap( ArtifactFactory artifactFactory, String projectId,
494 DependencyManagement dependencyManagement )
495 throws ProjectBuildingException
496 {
497 Map map;
498 if ( dependencyManagement != null && dependencyManagement.getDependencies() != null )
499 {
500 map = new HashMap();
501 for ( Iterator i = dependencyManagement.getDependencies().iterator(); i.hasNext(); )
502 {
503 Dependency d = (Dependency) i.next();
504
505 try
506 {
507 VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
508 Artifact artifact = artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(),
509 versionRange, d.getType(),
510 d.getClassifier(), d.getScope(),
511 d.isOptional() );
512 map.put( d.getManagementKey(), artifact );
513 }
514 catch ( InvalidVersionSpecificationException e )
515 {
516 throw new ProjectBuildingException( projectId, "Unable to parse version '" + d.getVersion()
517 + "' for dependency '" + d.getManagementKey() + "': " + e.getMessage(), e );
518 }
519 }
520 }
521 else
522 {
523 map = Collections.EMPTY_MAP;
524 }
525 return map;
526 }
527
528 public Log getLog()
529 {
530 if ( log == null )
531 {
532 log = super.getLog();
533 }
534
535 return log;
536 }
537 }